[gtksourceview/wip/chergert/vim] half page and line viewport changes
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/chergert/vim] half page and line viewport changes
- Date: Tue, 26 Oct 2021 05:43:36 +0000 (UTC)
commit 89549ebe679caa61bebaa6c44b0b4dec6a3f1293
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]