[gtksourceview/wip/chergert/vim: 68/73] half page and line viewport changes




commit e4b4fe359a2a2dab1ea2d06dd6dae665722adf4b
Author: Christian Hergert <chergert redhat com>
Date:   Mon Oct 25 22:31:58 2021 -0700

    half page and line viewport changes

 gtksourceview/vim/gtk-source-vim-normal.c |  49 +++++++++++-
 gtksourceview/vim/gtk-source-vim-state.c  | 123 ++++++++++++++++++++++++++++++
 gtksourceview/vim/gtk-source-vim-state.h  |  52 +++++++------
 3 files changed, 201 insertions(+), 23 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-normal.c b/gtksourceview/vim/gtk-source-vim-normal.c
index 43782077..567e298d 100644
--- a/gtksourceview/vim/gtk-source-vim-normal.c
+++ b/gtksourceview/vim/gtk-source-vim-normal.c
@@ -157,9 +157,49 @@ key_handler_viewport (GtkSourceVimNormal *self,
                       GdkModifierType     mods,
                       const char         *string)
 {
+       GtkSourceVimState *state = (GtkSourceVimState *)self;
+
        g_assert (GTK_SOURCE_IS_VIM_NORMAL (self));
 
-       return TRUE;
+       if ((mods & GDK_CONTROL_MASK) != 0)
+       {
+               switch (keyval)
+               {
+                       case GDK_KEY_d:
+                               gtk_source_vim_state_scroll_half_page (state, MAX (1, self->repeat));
+                               gtk_source_vim_normal_clear (self);
+                               return TRUE;
+
+                       case GDK_KEY_u:
+                               gtk_source_vim_state_scroll_half_page (state, MIN (-1, -self->repeat));
+                               gtk_source_vim_normal_clear (self);
+                               return TRUE;
+
+                       case GDK_KEY_e:
+                               gtk_source_vim_state_scroll_line (state, MAX (1, self->repeat));
+                               gtk_source_vim_normal_clear (self);
+                               return TRUE;
+
+                       case GDK_KEY_y:
+                               gtk_source_vim_state_scroll_line (state, MIN (-1, -self->repeat));
+                               gtk_source_vim_normal_clear (self);
+                               return TRUE;
+
+                       default:
+                               break;
+               }
+       }
+
+       switch (keyval)
+       {
+               case GDK_KEY_z:
+                       break;
+
+               default:
+                       break;
+       }
+
+       return gtk_source_vim_normal_bail (self);
 }
 
 static gboolean
@@ -378,6 +418,13 @@ key_handler_initial (GtkSourceVimNormal *self,
                                self->handler = key_handler_increment;
                                break;
 
+                       case GDK_KEY_d:
+                       case GDK_KEY_u:
+                       case GDK_KEY_e:
+                       case GDK_KEY_y:
+                               self->handler = key_handler_viewport;
+                               break;
+
                        case GDK_KEY_v:
                                self->handler = key_handler_visual;
                                break;
diff --git a/gtksourceview/vim/gtk-source-vim-state.c b/gtksourceview/vim/gtk-source-vim-state.c
index 345f737e..f7d576f1 100644
--- a/gtksourceview/vim/gtk-source-vim-state.c
+++ b/gtksourceview/vim/gtk-source-vim-state.c
@@ -22,6 +22,7 @@
 #include "config.h"
 
 #include "gtksourcebuffer.h"
+#include "gtksourceutils-private.h"
 #include "gtksourceview.h"
 
 #include "gtk-source-vim-state.h"
@@ -472,3 +473,125 @@ gtk_source_vim_state_synthesize (GtkSourceVimState *self,
        keyval_to_string (keyval, mods, string);
        return GTK_SOURCE_VIM_STATE_GET_CLASS (self)->handle_keypress (self, keyval, 0, mods, string);
 }
+
+void
+gtk_source_vim_state_select (GtkSourceVimState *self,
+                             const GtkTextIter *insert,
+                             const GtkTextIter *selection)
+{
+       GtkSourceVimStatePrivate *priv = gtk_source_vim_state_get_instance_private (self);
+       GtkTextBuffer *buffer;
+
+       g_return_if_fail (GTK_SOURCE_IS_VIM_STATE (self));
+       g_return_if_fail (insert != NULL);
+
+       if (selection == NULL)
+               selection = insert;
+
+       buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->view));
+       gtk_text_buffer_select_range (buffer, insert, selection);
+}
+
+int
+gtk_source_vim_state_get_visible_lines (GtkSourceVimState *self)
+{
+       GtkSourceVimStatePrivate *priv = gtk_source_vim_state_get_instance_private (self);
+       GtkTextIter begin, end;
+       GdkRectangle rect;
+       guint bline, eline;
+
+       g_return_val_if_fail (GTK_SOURCE_IS_VIM_STATE (self), 2);
+
+       gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (priv->view), &rect);
+       gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (priv->view), &begin, rect.x, rect.y);
+       gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (priv->view), &end, rect.x, rect.y + rect.height);
+
+       bline = gtk_text_iter_get_line (&begin);
+       eline = gtk_text_iter_get_line (&end);
+
+       return MAX (2, eline - bline);
+}
+
+void
+gtk_source_vim_state_scroll_line (GtkSourceVimState *self,
+                                  int                count)
+{
+       GtkSourceView *view;
+       GdkRectangle rect;
+       GtkTextIter top;
+       int y, height;
+
+       g_return_if_fail (GTK_SOURCE_IS_VIM_STATE (self));
+
+       if (count == 0)
+               count = 1;
+
+       view = gtk_source_vim_state_get_view (self);
+       gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (view), &rect);
+       gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &top, rect.x, rect.y);
+       gtk_text_view_get_line_yrange (GTK_TEXT_VIEW (view), &top, &y, &height);
+
+       /* Add a line is slightly visible. Works in both directions */
+       if (y < rect.y)
+               count++;
+
+       if (count > 0)
+               gtk_text_iter_forward_lines (&top, count);
+       else
+               gtk_text_iter_backward_lines (&top, -count);
+
+       _gtk_source_view_jump_to_iter (GTK_TEXT_VIEW (view), &top, 0.0, TRUE, 1.0, 0.0);
+
+       /* Note: This doesn't seem to update immediate for CTRL+Y, probably
+        * because the viewport area has not calculated that the insert
+        * mark has fully moved off screen. We might need to do something
+        * like force revalidation but delaying the movement can cause
+        * ordering issues.
+        */
+       gtk_text_view_place_cursor_onscreen (GTK_TEXT_VIEW (view));
+}
+
+void
+gtk_source_vim_state_scroll_half_page (GtkSourceVimState *self,
+                                       int                count)
+{
+       GtkSourceView *view;
+       GdkRectangle rect, loc;
+       GtkTextIter iter;
+       GtkTextIter top, bottom;
+       int visible_lines;
+
+       g_return_if_fail (GTK_SOURCE_IS_VIM_STATE (self));
+
+       if (count == 0)
+               count = 1;
+
+       gtk_source_vim_state_get_buffer (self, &iter, NULL);
+       view = gtk_source_vim_state_get_view (self);
+       gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (view), &rect);
+
+       gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &top, rect.x, rect.y);
+       gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &bottom, rect.x, rect.y + rect.height);
+
+       visible_lines = gtk_text_iter_get_line (&bottom) - gtk_text_iter_get_line (&top);
+       if (visible_lines < 2)
+               visible_lines = 2;
+
+       gtk_text_view_get_iter_location (GTK_TEXT_VIEW (view), &iter, &loc);
+       gtk_text_view_buffer_to_window_coords (GTK_TEXT_VIEW (view), GTK_TEXT_WINDOW_TEXT, loc.x, loc.y, 
&loc.x, &loc.y);
+
+       if (count > 0)
+       {
+               gtk_text_iter_forward_lines (&top, count * visible_lines);
+               _gtk_source_view_jump_to_iter (GTK_TEXT_VIEW (view), &top, 0.0, TRUE, 1.0, 0.0);
+       }
+       else
+       {
+               gtk_text_iter_backward_lines (&bottom, -count * visible_lines);
+               _gtk_source_view_jump_to_iter (GTK_TEXT_VIEW (view), &bottom, 0.0, TRUE, 1.0, 1.0);
+       }
+
+       gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (view), GTK_TEXT_WINDOW_TEXT, loc.x, loc.y, 
&loc.x, &loc.y);
+       gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &iter, loc.x, loc.y);
+       gtk_source_vim_state_select (self, &iter, &iter);
+}
diff --git a/gtksourceview/vim/gtk-source-vim-state.h b/gtksourceview/vim/gtk-source-vim-state.h
index 202746db..24b07e30 100644
--- a/gtksourceview/vim/gtk-source-vim-state.h
+++ b/gtksourceview/vim/gtk-source-vim-state.h
@@ -54,28 +54,36 @@ struct _GtkSourceVimStateClass
                                     int                repeat);
 };
 
-void               gtk_source_vim_state_push           (GtkSourceVimState *self,
-                                                        GtkSourceVimState *new_state);
-void               gtk_source_vim_state_pop            (GtkSourceVimState *self);
-void               gtk_source_vim_state_beep           (GtkSourceVimState *self);
-GtkSourceVimState *gtk_source_vim_state_get_child      (GtkSourceVimState *self);
-GtkSourceVimState *gtk_source_vim_state_get_current    (GtkSourceVimState *self);
-GtkSourceView     *gtk_source_vim_state_get_view       (GtkSourceVimState *self);
-GtkSourceBuffer   *gtk_source_vim_state_get_buffer     (GtkSourceVimState *self,
-                                                        GtkTextIter       *insert,
-                                                        GtkTextIter       *selection_bound);
-GtkSourceVimState *gtk_source_vim_state_get_root       (GtkSourceVimState *self);
-GtkSourceVimState *gtk_source_vim_state_get_parent     (GtkSourceVimState *self);
-gboolean           gtk_source_vim_state_handle_event   (GtkSourceVimState *self,
-                                                        GdkEvent          *event);
-void               gtk_source_vim_state_set_overwrite  (GtkSourceVimState *self,
-                                                        gboolean           overwrite);
-gboolean           gtk_source_vim_state_get_can_repeat (GtkSourceVimState *self);
-gboolean           gtk_source_vim_state_synthesize     (GtkSourceVimState *self,
-                                                        guint              keyval,
-                                                        GdkModifierType    mods);
-void               gtk_source_vim_state_repeat         (GtkSourceVimState *self,
-                                                        int                repeat);
+void               gtk_source_vim_state_push              (GtkSourceVimState *self,
+                                                           GtkSourceVimState *new_state);
+void               gtk_source_vim_state_pop               (GtkSourceVimState *self);
+void               gtk_source_vim_state_beep              (GtkSourceVimState *self);
+GtkSourceVimState *gtk_source_vim_state_get_child         (GtkSourceVimState *self);
+GtkSourceVimState *gtk_source_vim_state_get_current       (GtkSourceVimState *self);
+GtkSourceView     *gtk_source_vim_state_get_view          (GtkSourceVimState *self);
+GtkSourceBuffer   *gtk_source_vim_state_get_buffer        (GtkSourceVimState *self,
+                                                           GtkTextIter       *insert,
+                                                           GtkTextIter       *selection_bound);
+GtkSourceVimState *gtk_source_vim_state_get_root          (GtkSourceVimState *self);
+GtkSourceVimState *gtk_source_vim_state_get_parent        (GtkSourceVimState *self);
+gboolean           gtk_source_vim_state_handle_event      (GtkSourceVimState *self,
+                                                           GdkEvent          *event);
+void               gtk_source_vim_state_set_overwrite     (GtkSourceVimState *self,
+                                                           gboolean           overwrite);
+gboolean           gtk_source_vim_state_get_can_repeat    (GtkSourceVimState *self);
+gboolean           gtk_source_vim_state_synthesize        (GtkSourceVimState *self,
+                                                           guint              keyval,
+                                                           GdkModifierType    mods);
+void               gtk_source_vim_state_repeat            (GtkSourceVimState *self,
+                                                           int                repeat);
+int                gtk_source_vim_state_get_visible_lines (GtkSourceVimState *self);
+void               gtk_source_vim_state_scroll_half_page  (GtkSourceVimState *self,
+                                                           int                count);
+void               gtk_source_vim_state_scroll_line       (GtkSourceVimState *self,
+                                                           int                count);
+void               gtk_source_vim_state_select            (GtkSourceVimState *self,
+                                                           const GtkTextIter *insert,
+                                                           const GtkTextIter *selection);
 
 static inline gboolean
 gtk_source_vim_state_is_escape (guint           keyval,


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