[gtksourceview/wip/chergert/vim] synchronize text history to "." register



commit 9e797b7e4943da0f57819bd8e9430a5c1e9525b4
Author: Christian Hergert <chergert redhat com>
Date:   Tue Nov 2 12:09:59 2021 -0700

    synchronize text history to "." register

 gtksourceview/vim/gtk-source-vim-text-history.c | 76 +++++++++++++++++++++++++
 1 file changed, 76 insertions(+)
---
diff --git a/gtksourceview/vim/gtk-source-vim-text-history.c b/gtksourceview/vim/gtk-source-vim-text-history.c
index ece86630..9f99276c 100644
--- a/gtksourceview/vim/gtk-source-vim-text-history.c
+++ b/gtksourceview/vim/gtk-source-vim-text-history.c
@@ -23,6 +23,7 @@
 
 #include "gtksourcebuffer.h"
 
+#include "gtk-source-vim-registers.h"
 #include "gtk-source-vim-text-history.h"
 
 typedef enum
@@ -200,10 +201,54 @@ gtk_source_vim_text_history_begin (GtkSourceVimTextHistory *self)
                                 G_CONNECT_SWAPPED);
 }
 
+/*
+ * string_truncate_n_chars:
+ * @str: the GString
+ * @n_chars: the number of chars to remove
+ *
+ * Removes @n_chars from the tail of @str, possibly taking into
+ * account UTF-8 characters that are multi-width.
+ */
+static void
+string_truncate_n_chars (GString *str,
+                         gsize    n_chars)
+{
+       if (str == NULL)
+       {
+               return;
+       }
+
+       if (n_chars >= str->len)
+       {
+               g_string_truncate (str, 0);
+               return;
+       }
+
+       g_assert (str->len > 0);
+
+       while (n_chars > 0 && str->len > 0)
+       {
+               guchar ch = str->str[--str->len];
+
+               /* If high bit is zero we have a one-byte char. If we have
+                * reached the byte with 0xC0 mask set then we are at the
+                * first character of a multi-byte char.
+                */
+               if ((ch & 0x80) == 0 || (ch & 0xC0) == 0xC0)
+               {
+                       n_chars--;
+               }
+       }
+
+       str->str[str->len] = 0;
+}
+
 void
 gtk_source_vim_text_history_end (GtkSourceVimTextHistory *self)
 {
+       GtkSourceVimState *registers;
        GtkSourceBuffer *buffer;
+       GString *inserted;
 
        g_return_if_fail (GTK_SOURCE_IS_VIM_TEXT_HISTORY (self));
 
@@ -215,6 +260,37 @@ gtk_source_vim_text_history_end (GtkSourceVimTextHistory *self)
        g_signal_handlers_disconnect_by_func (buffer,
                                              G_CALLBACK (gtk_source_vim_text_history_delete_range_cb),
                                              self);
+
+       /* Collect the inserted text into a single string and then set that
+        * in the "." register which is a read-only register to the user
+        * containing the last inserted text.
+        */
+       inserted = g_string_new (NULL);
+       for (guint i = 0; i < self->ops->len; i++)
+       {
+               const Op *op = &g_array_index (self->ops, Op, i);
+               const char *str = self->bytes->str + op->offset;
+
+               switch (op->kind)
+               {
+                       case OP_INSERT:
+                               g_string_append_len (inserted, str, g_utf8_offset_to_pointer (str, 
op->length) - str);
+                               break;
+
+                       case OP_BACKSPACE:
+                               string_truncate_n_chars (inserted, op->length);
+                               break;
+
+                       default:
+                       case OP_DELETE:
+                               break;
+               }
+       }
+
+       registers = gtk_source_vim_state_get_registers (GTK_SOURCE_VIM_STATE (self));
+       gtk_source_vim_registers_take (GTK_SOURCE_VIM_REGISTERS (registers),
+                                      ".",
+                                      g_string_free (inserted, FALSE));
 }
 
 void


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