[gnome-builder/wip/scrolloff] gb-source-vim: Add support for vim scrolloff



commit f3629e3542ab4560e96fdbd794e65bcb5f1211ce
Author: Carlos Soriano <carlos soriano89 gmail com>
Date:   Tue Jan 6 00:01:02 2015 +0100

    gb-source-vim: Add support for vim scrolloff
    
    Vim scrolloff allow the user to set a margin of a number of lines
    while moving through the buffer.
    Add support to it and add a setting to let the user adjust the number
    of lines.
    
    As a detail, a scrolloff greater than half of the number of lines in the
    buffer keeps the current line always in the middle.

 configure.ac                                     |    1 +
 data/gsettings.mk                                |    1 +
 data/org.gnome.builder.editor.vim.gschema.xml.in |    8 ++
 src/gnome-builder.mk                             |    2 +
 src/preferences/gb-preferences-page-vim.c        |   94 ++++++++++++++++++
 src/preferences/gb-preferences-page-vim.h        |   55 ++++++++++
 src/preferences/gb-preferences-window.c          |    2 +
 src/resources/gnome-builder.gresource.xml        |    1 +
 src/resources/ui/gb-preferences-page-vim.ui      |   82 +++++++++++++++
 src/resources/ui/gb-preferences-window.ui        |    9 ++
 src/vim/gb-source-vim.c                          |  115 ++++++++++++++++++----
 11 files changed, 349 insertions(+), 21 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index b4e0b7f..23eb9ee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -51,6 +51,7 @@ AC_CONFIG_FILES([
        data/icons/Makefile
        data/org.gnome.builder.editor.gschema.xml
        data/org.gnome.builder.editor.language.gschema.xml
+       data/org.gnome.builder.editor.vim.gschema.xml
 ])
 
 # Last change to configure things and write configuration files.
diff --git a/data/gsettings.mk b/data/gsettings.mk
index e15f2b6..fbd3e0b 100644
--- a/data/gsettings.mk
+++ b/data/gsettings.mk
@@ -1,5 +1,6 @@
 gsettingsschema_in_files = \
        data/org.gnome.builder.editor.gschema.xml.in \
+       data/org.gnome.builder.editor.vim.gschema.xml.in \
        data/org.gnome.builder.editor.language.gschema.xml.in
 
 gsettings_SCHEMAS = $(gsettingsschema_in_files:.xml.in=.xml)
diff --git a/data/org.gnome.builder.editor.vim.gschema.xml.in 
b/data/org.gnome.builder.editor.vim.gschema.xml.in
new file mode 100644
index 0000000..9f2a829
--- /dev/null
+++ b/data/org.gnome.builder.editor.vim.gschema.xml.in
@@ -0,0 +1,8 @@
+<schemalist>
+  <schema id="org.gnome.builder.editor.vim" path="/org/gnome/builder/editor/vim/" 
gettext-domain="gnome-builder">
+    <key name="scroll-off" type="i">
+      <range min="0" max="999"/>
+      <default>0</default>
+    </key>
+  </schema>
+</schemalist>
diff --git a/src/gnome-builder.mk b/src/gnome-builder.mk
index bcdc5f9..6c877ac 100644
--- a/src/gnome-builder.mk
+++ b/src/gnome-builder.mk
@@ -141,6 +141,8 @@ libgnome_builder_la_SOURCES = \
        src/preferences/gb-preferences-page-git.h \
        src/preferences/gb-preferences-page-language.c \
        src/preferences/gb-preferences-page-language.h \
+       src/preferences/gb-preferences-page-vim.c \
+       src/preferences/gb-preferences-page-vim.h \
        src/preferences/gb-preferences-page.c \
        src/preferences/gb-preferences-page.h \
        src/preferences/gb-preferences-window.c \
diff --git a/src/preferences/gb-preferences-page-vim.c b/src/preferences/gb-preferences-page-vim.c
new file mode 100644
index 0000000..deb642d
--- /dev/null
+++ b/src/preferences/gb-preferences-page-vim.c
@@ -0,0 +1,94 @@
+/* gb-preferences-page-vim.c
+ *
+ * Copyright (C) 2015 Carlos Soriano <csoriano gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "prefs-page-editor"
+
+#include <glib/gi18n.h>
+
+#include "gb-preferences-page-vim.h"
+
+struct _GbPreferencesPageVimPrivate
+{
+  GSettings             *settings;
+
+  /* Widgets owned by Template */
+  GtkSpinButton         *scroll_off_spin;
+
+  /* Template widgets used for filtering */
+  GtkWidget             *scroll_off_container;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GbPreferencesPageVim, gb_preferences_page_vim,
+                            GB_TYPE_PREFERENCES_PAGE)
+
+static void
+gb_preferences_page_vim_constructed (GObject *object)
+{
+  GbPreferencesPageVimPrivate *priv;
+  GbPreferencesPageVim *vim = (GbPreferencesPageVim *)object;
+
+  g_return_if_fail (GB_IS_PREFERENCES_PAGE_VIM (vim));
+
+  priv = vim->priv;
+
+  priv->settings = g_settings_new ("org.gnome.builder.editor.vim");
+
+  g_settings_bind (priv->settings, "scroll-off", priv->scroll_off_spin, "value",
+                   G_SETTINGS_BIND_DEFAULT);
+}
+
+static void
+gb_preferences_page_vim_finalize (GObject *object)
+{
+  GbPreferencesPageVimPrivate *priv = GB_PREFERENCES_PAGE_VIM (object)->priv;
+
+  g_clear_object (&priv->settings);
+
+  G_OBJECT_CLASS (gb_preferences_page_vim_parent_class)->finalize (object);
+}
+
+static void
+gb_preferences_page_vim_class_init (GbPreferencesPageVimClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = gb_preferences_page_vim_finalize;
+  object_class->constructed = gb_preferences_page_vim_constructed;
+
+  gtk_widget_class_set_template_from_resource (widget_class,
+                                               "/org/gnome/builder/ui/gb-preferences-page-vim.ui");
+
+  gtk_widget_class_bind_template_child_private (widget_class, GbPreferencesPageVim, scroll_off_spin);
+
+  gtk_widget_class_bind_template_child_private (widget_class, GbPreferencesPageVim, scroll_off_container);
+}
+
+static void
+gb_preferences_page_vim_init (GbPreferencesPageVim *self)
+{
+  self->priv = gb_preferences_page_vim_get_instance_private (self);
+
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  gb_preferences_page_set_keywords_for_widget (GB_PREFERENCES_PAGE (self),
+                                               _("lines margin scrolloff scroll off"),
+                                               self->priv->scroll_off_container,
+                                               self->priv->scroll_off_spin,
+                                               NULL);
+}
diff --git a/src/preferences/gb-preferences-page-vim.h b/src/preferences/gb-preferences-page-vim.h
new file mode 100644
index 0000000..f3a7b0e
--- /dev/null
+++ b/src/preferences/gb-preferences-page-vim.h
@@ -0,0 +1,55 @@
+/* gb-preferences-page-vim.h
+ *
+ * Copyright (C) 2015 Carlos Soriano <csoriano gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GB_PREFERENCES_PAGE_VIM_H
+#define GB_PREFERENCES_PAGE_VIM_H
+
+#include "gb-preferences-page.h"
+
+G_BEGIN_DECLS
+
+#define GB_TYPE_PREFERENCES_PAGE_VIM            (gb_preferences_page_vim_get_type())
+#define GB_PREFERENCES_PAGE_VIM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GB_TYPE_PREFERENCES_PAGE_VIM, GbPreferencesPageVim))
+#define GB_PREFERENCES_PAGE_VIM_CONST(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GB_TYPE_PREFERENCES_PAGE_VIM, GbPreferencesPageVim const))
+#define GB_PREFERENCES_PAGE_VIM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  
GB_TYPE_PREFERENCES_PAGE_VIM, GbPreferencesPageVimClass))
+#define GB_IS_PREFERENCES_PAGE_VIM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GB_TYPE_PREFERENCES_PAGE_VIM))
+#define GB_IS_PREFERENCES_PAGE_VIM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  
GB_TYPE_PREFERENCES_PAGE_VIM))
+#define GB_PREFERENCES_PAGE_VIM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  
GB_TYPE_PREFERENCES_PAGE_VIM, GbPreferencesPageVimClass))
+
+typedef struct _GbPreferencesPageVim        GbPreferencesPageVim;
+typedef struct _GbPreferencesPageVimClass   GbPreferencesPageVimClass;
+typedef struct _GbPreferencesPageVimPrivate GbPreferencesPageVimPrivate;
+
+struct _GbPreferencesPageVim
+{
+  GbPreferencesPage parent;
+
+  /*< private >*/
+  GbPreferencesPageVimPrivate *priv;
+};
+
+struct _GbPreferencesPageVimClass
+{
+  GbPreferencesPageClass parent;
+};
+
+GType                     gb_preferences_page_vim_get_type (void);
+
+G_END_DECLS
+
+#endif /* GB_PREFERENCES_PAGE_VIM_H */
diff --git a/src/preferences/gb-preferences-window.c b/src/preferences/gb-preferences-window.c
index 35d4427..26eee97 100644
--- a/src/preferences/gb-preferences-window.c
+++ b/src/preferences/gb-preferences-window.c
@@ -27,6 +27,7 @@
 #include "gb-preferences-page-editor.h"
 #include "gb-preferences-page-git.h"
 #include "gb-preferences-page-language.h"
+#include "gb-preferences-page-vim.h"
 #include "gb-preferences-window.h"
 
 struct _GbPreferencesWindowPrivate
@@ -210,6 +211,7 @@ gb_preferences_window_class_init (GbPreferencesWindowClass *klass)
   g_type_ensure (GB_TYPE_PREFERENCES_PAGE_GIT);
   g_type_ensure (GB_TYPE_PREFERENCES_PAGE_EDITOR);
   g_type_ensure (GB_TYPE_PREFERENCES_PAGE_LANGUAGE);
+  g_type_ensure (GB_TYPE_PREFERENCES_PAGE_VIM);
 }
 
 static void
diff --git a/src/resources/gnome-builder.gresource.xml b/src/resources/gnome-builder.gresource.xml
index 2c046a5..3cfe32b 100644
--- a/src/resources/gnome-builder.gresource.xml
+++ b/src/resources/gnome-builder.gresource.xml
@@ -39,6 +39,7 @@
     <file>ui/gb-preferences-page-editor.ui</file>
     <file>ui/gb-preferences-page-git.ui</file>
     <file>ui/gb-preferences-page-language.ui</file>
+    <file>ui/gb-preferences-page-vim.ui</file>
     <file>ui/gb-search-box.ui</file>
     <file>ui/gb-search-display.ui</file>
     <file>ui/gb-workbench.ui</file>
diff --git a/src/resources/ui/gb-preferences-page-vim.ui b/src/resources/ui/gb-preferences-page-vim.ui
new file mode 100644
index 0000000..8e2bc5e
--- /dev/null
+++ b/src/resources/ui/gb-preferences-page-vim.ui
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.8 -->
+  <template class="GbPreferencesPageVim" parent="GbPreferencesPage">
+    <child>
+      <object class="GtkBox">
+        <property name="visible">true</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child>
+          <object class="GtkGrid" id="grid1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="row_spacing">12</property>
+            <property name="column_spacing">12</property>
+            <child>
+              <object class="GtkSpinButton" id="scroll_off_spin">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="valign">center</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox" id="scroll_off_container">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkLabel" id="label5">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Scroll Off&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                    <property name="xalign">0</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label8">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="label" translatable="yes">Margin in lines for cursor movement.</property>
+                    <property name="xalign">0</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">0</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/resources/ui/gb-preferences-window.ui b/src/resources/ui/gb-preferences-window.ui
index d2e38d6..1859c80 100644
--- a/src/resources/ui/gb-preferences-window.ui
+++ b/src/resources/ui/gb-preferences-window.ui
@@ -132,6 +132,15 @@
                 <property name="title" translatable="yes">Git</property>
               </packing>
             </child>
+            <child>
+              <object class="GbPreferencesPageVim" id="vim_page">
+                <property name="visible">True</property>
+              </object>
+              <packing>
+                <property name="name">vim</property>
+                <property name="title" translatable="yes">Vim</property>
+              </packing>
+            </child>
           </object>
         </child>
       </object>
diff --git a/src/vim/gb-source-vim.c b/src/vim/gb-source-vim.c
index 5694d81..adffad2 100644
--- a/src/vim/gb-source-vim.c
+++ b/src/vim/gb-source-vim.c
@@ -17,7 +17,7 @@
  */
 
 #define G_LOG_DOMAIN "vim"
-#define SCROLL_OFF 3
+#define SCROLL_OFF 10
 
 #include <errno.h>
 #include <glib/gi18n.h>
@@ -108,6 +108,14 @@ typedef enum
 
 typedef enum
 {
+  GB_SOURCE_VIM_ALIGMENT_NONE,
+  GB_SOURCE_VIM_ALIGMENT_KEEP,
+  GB_SOURCE_VIM_ALIGMENT_TOP,
+  GB_SOURCE_VIM_ALIGMENT_BOTTOM
+} GbSourceVimAligment;
+
+typedef enum
+{
   GB_SOURCE_VIM_COMMAND_NOOP,
   GB_SOURCE_VIM_COMMAND_MOVEMENT,
   GB_SOURCE_VIM_COMMAND_CHANGE,
@@ -139,6 +147,12 @@ typedef struct
   GbSourceVimCommandFlags flags;
 } GbSourceVimCommand;
 
+typedef struct
+{
+  gfloat yalign;
+  gint   line;
+} GbSourceVimAdjustedScroll;
+
 typedef enum
 {
   GB_SOURCE_VIM_PHRASE_FAILED,
@@ -209,6 +223,10 @@ static void gb_source_vim_cmd_delete_to_end (GbSourceVim *vim,
 static void gb_source_vim_cmd_insert_before_line (GbSourceVim *vim,
                                                   guint        count,
                                                   gchar        modifier);
+static GbSourceVimAdjustedScroll
+gb_source_vim_adjust_scroll (GbSourceVim *vim,
+                             gint         line,
+                             GbSourceVimAligment aligment);
 
 GbSourceVim *
 gb_source_vim_new (GtkTextView *text_view)
@@ -1458,6 +1476,7 @@ gb_source_vim_move_down (GbSourceVim *vim)
   GtkTextIter selection;
   gboolean has_selection;
   guint line;
+  GbSourceVimAdjustedScroll scroll;
   guint offset;
 
   g_assert (GB_IS_SOURCE_VIM (vim));
@@ -1530,6 +1549,9 @@ select_to_end:
 move_mark:
   insert = gtk_text_buffer_get_insert (buffer);
   gtk_text_view_scroll_mark_onscreen (vim->priv->text_view, insert);
+  scroll= gb_source_vim_adjust_scroll (vim, line + 1, GB_SOURCE_VIM_ALIGMENT_NONE);
+  gtk_text_view_scroll_to_iter (vim->priv->text_view, &iter, 0.0,
+                                TRUE, 0.5, scroll.yalign);
 }
 
 static void
@@ -1542,6 +1564,7 @@ gb_source_vim_move_up (GbSourceVim *vim)
   GtkTextIter selection;
   gboolean has_selection;
   guint line;
+  GbSourceVimAdjustedScroll scroll;
   guint offset;
 
   g_assert (GB_IS_SOURCE_VIM (vim));
@@ -1598,6 +1621,9 @@ gb_source_vim_move_up (GbSourceVim *vim)
 move_mark:
   insert = gtk_text_buffer_get_insert (buffer);
   gtk_text_view_scroll_mark_onscreen (vim->priv->text_view, insert);
+  scroll= gb_source_vim_adjust_scroll (vim, line - 1, GB_SOURCE_VIM_ALIGMENT_NONE);
+  gtk_text_view_scroll_to_iter (vim->priv->text_view, &iter, 0.0,
+                                TRUE, 0.5, scroll.yalign);
 }
 
 static void
@@ -2626,6 +2652,64 @@ gb_source_vim_move_to_iter (GbSourceVim *vim,
                                 TRUE, 0.5, yalign);
 }
 
+static GbSourceVimAdjustedScroll
+gb_source_vim_adjust_scroll (GbSourceVim         *vim,
+                             gint                 line,
+                             GbSourceVimAligment  aligment)
+{
+  GdkRectangle rect;
+  gint line_top, line_bottom, line_current;
+  gint page_lines;
+  GtkTextIter iter_top, iter_bottom, iter_current;
+  GtkTextBuffer *buffer;
+  gfloat min_yalign, max_yalign, yalign;
+  GbSourceVimAdjustedScroll result;
+
+  g_assert (GB_IS_SOURCE_VIM (vim));
+
+  gtk_text_view_get_visible_rect (vim->priv->text_view, &rect);
+  gtk_text_view_get_iter_at_location (vim->priv->text_view, &iter_top,
+                                      rect.x, rect.y);
+  gtk_text_view_get_iter_at_location (vim->priv->text_view, &iter_bottom,
+                                      rect.x, rect.y + rect.height);
+
+  buffer = gtk_text_view_get_buffer (vim->priv->text_view);
+  gtk_text_buffer_get_selection_bounds (buffer, &iter_current, NULL);
+
+  line_top = gtk_text_iter_get_line (&iter_top);
+  line_bottom = gtk_text_iter_get_line (&iter_bottom);
+  line_current = gtk_text_iter_get_line (&iter_current);
+  page_lines = line_bottom - line_top;
+  min_yalign = MIN (SCROLL_OFF / (float) page_lines, 0.5);
+  max_yalign = 1.0 - min_yalign;
+  yalign = (line - line_top) / (float) page_lines;
+
+  switch (aligment)
+    {
+    case GB_SOURCE_VIM_ALIGMENT_NONE:
+      result.yalign = CLAMP (yalign, min_yalign, max_yalign);
+      result.line = line;
+      break;
+    case GB_SOURCE_VIM_ALIGMENT_KEEP:
+      result.yalign = MAX (0.0, (float)(line_current - line_top) /
+                                (float)(line_bottom - line_top));
+      result.line = line;
+      break;
+    case GB_SOURCE_VIM_ALIGMENT_TOP:
+      result.yalign = CLAMP (0.0, min_yalign, max_yalign);
+      result.line = line + result.yalign * page_lines;
+      break;
+    case GB_SOURCE_VIM_ALIGMENT_BOTTOM:
+      result.yalign = CLAMP (1.0, min_yalign, max_yalign);
+      result.line = line - (1.0 - result.yalign) * page_lines;
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+  return result;
+}
+
 static void
 gb_source_vim_move_page (GbSourceVim                 *vim,
                          GbSourceVimPageDirectionType direction)
@@ -2635,7 +2719,7 @@ gb_source_vim_move_page (GbSourceVim                 *vim,
   guint offset;
   gint line, line_top, line_bottom, line_current;
   GtkTextBuffer *buffer;
-  gfloat yalign = 0.0;
+  GbSourceVimAdjustedScroll adjusted_scroll;
 
   g_assert (GB_IS_SOURCE_VIM (vim));
 
@@ -2652,47 +2736,36 @@ gb_source_vim_move_page (GbSourceVim                 *vim,
   line_bottom = gtk_text_iter_get_line (&iter_bottom);
   line_current = gtk_text_iter_get_line (&iter_current);
 
-  if (direction == GB_SOURCE_VIM_HALF_PAGE_UP ||
-      direction == GB_SOURCE_VIM_HALF_PAGE_DOWN)
-    {
-      /* keep current yalign */
-      if (line_bottom != line_top)
-        yalign = MAX (0.0, (float)(line_current - line_top) /
-                           (float)(line_bottom - line_top));
-    }
-
   switch (direction)
     {
     case GB_SOURCE_VIM_HALF_PAGE_UP:
       line = line_current - (line_bottom - line_top) / 2;
+      adjusted_scroll = gb_source_vim_adjust_scroll (vim, line, GB_SOURCE_VIM_ALIGMENT_KEEP);
       break;
     case GB_SOURCE_VIM_HALF_PAGE_DOWN:
       line = line_current + (line_bottom - line_top) / 2;
+      adjusted_scroll = gb_source_vim_adjust_scroll (vim, line, GB_SOURCE_VIM_ALIGMENT_KEEP);
       break;
     case GB_SOURCE_VIM_PAGE_UP:
-      yalign = 1.0;
-      line = gtk_text_iter_get_line (&iter_top) + SCROLL_OFF;
+      line = gtk_text_iter_get_line (&iter_top);
+      adjusted_scroll = gb_source_vim_adjust_scroll (vim, line, GB_SOURCE_VIM_ALIGMENT_BOTTOM);
       break;
     case GB_SOURCE_VIM_PAGE_DOWN:
-      yalign = 0.0;
-      /*
-       * rect.y + rect.height is the next line after the end of the buffer so
-       * now we have to decrease one more.
-       */
-      line = MAX (0, gtk_text_iter_get_line (&iter_bottom) - SCROLL_OFF - 1);
+      line = MAX (0, gtk_text_iter_get_line (&iter_bottom));
+      adjusted_scroll = gb_source_vim_adjust_scroll (vim, line, GB_SOURCE_VIM_ALIGMENT_TOP);
       break;
     default:
       g_assert_not_reached();
     }
 
-  gtk_text_iter_set_line (&iter_current, line);
+  gtk_text_iter_set_line (&iter_current, adjusted_scroll.line);
 
   for (offset = vim->priv->target_line_offset; offset; offset--)
     if (gtk_text_iter_ends_line (&iter_current) ||
         !gtk_text_iter_forward_char (&iter_current))
       break;
 
-  gb_source_vim_move_to_iter (vim, &iter_current, yalign);
+  gb_source_vim_move_to_iter (vim, &iter_current, adjusted_scroll.yalign);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]