[gspell/wip/entry-context-menu: 1/2] EntryUtils: add function to get char position at GdkEventButton



commit fe2fa8d643697950022f9f70a1eeed3a7c4cb078
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Fri Nov 25 18:45:05 2016 +0100

    EntryUtils: add function to get char position at GdkEventButton

 gspell/gspell-entry-utils.c |   72 +++++++++++++++++++++++++++++++++++++++++++
 gspell/gspell-entry-utils.h |   10 ++++--
 2 files changed, 79 insertions(+), 3 deletions(-)
---
diff --git a/gspell/gspell-entry-utils.c b/gspell/gspell-entry-utils.c
index 5ab8342..4d97a65 100644
--- a/gspell/gspell-entry-utils.c
+++ b/gspell/gspell-entry-utils.c
@@ -149,4 +149,76 @@ _gspell_entry_utils_get_words (GtkEntry *entry)
        return g_slist_reverse (list);
 }
 
+static gint
+get_layout_index (GtkEntry *entry,
+                 gint      x)
+{
+       PangoLayout *layout;
+       PangoLayoutLine *line;
+       gint layout_index; /* in bytes */
+       gint trailing_chars;
+       const gchar *layout_text;
+       const gchar *pos_in_layout_text;
+       gint layout_text_byte_length;
+       gint max_trailing_chars;
+
+       layout = gtk_entry_get_layout (entry);
+       line = pango_layout_get_line_readonly (layout, 0);
+
+       pango_layout_line_x_to_index (line,
+                                     x * PANGO_SCALE,
+                                     &layout_index,
+                                     &trailing_chars);
+
+       layout_text = pango_layout_get_text (layout);
+
+       /* Performance should not be a problem here, it's better too much
+        * security than too few.
+        */
+       layout_text_byte_length = strlen (layout_text);
+       if (layout_index >= layout_text_byte_length)
+       {
+               return layout_text_byte_length;
+       }
+
+       if (trailing_chars == 0)
+       {
+               return layout_index;
+       }
+
+       pos_in_layout_text = layout_text + layout_index;
+       max_trailing_chars = g_utf8_strlen (pos_in_layout_text, -1);
+       trailing_chars = MIN (trailing_chars, max_trailing_chars);
+
+       pos_in_layout_text = g_utf8_offset_to_pointer (pos_in_layout_text, trailing_chars);
+
+       return pos_in_layout_text - layout_text;
+}
+
+/* The return value is in characters, not bytes. And a position suitable for the
+ * text in the GtkEntryBuffer, i.e. without the preedit string.
+ */
+gint
+_gspell_entry_utils_get_char_position_at_event (GtkEntry       *entry,
+                                               GdkEventButton *event)
+{
+       gint scroll_offset;
+       gint x;
+       gint layout_index; /* in bytes */
+       gint text_index; /* in bytes */
+       const gchar *buffer_text;
+
+       g_object_get (entry,
+                     "scroll-offset", &scroll_offset,
+                     NULL);
+
+       x = event->x + scroll_offset;
+
+       layout_index = get_layout_index (entry, x);
+       text_index = gtk_entry_layout_index_to_text_index (entry, layout_index);
+
+       buffer_text = gtk_entry_get_text (entry);
+       return g_utf8_pointer_to_offset (buffer_text, buffer_text + text_index);
+}
+
 /* ex:set ts=8 noet: */
diff --git a/gspell/gspell-entry-utils.h b/gspell/gspell-entry-utils.h
index 813b5b2..7370f81 100644
--- a/gspell/gspell-entry-utils.h
+++ b/gspell/gspell-entry-utils.h
@@ -43,13 +43,17 @@ struct _GspellEntryWord
 };
 
 G_GNUC_INTERNAL
-GspellEntryWord *_gspell_entry_word_new                        (void);
+GspellEntryWord *_gspell_entry_word_new                                (void);
 
 G_GNUC_INTERNAL
-void            _gspell_entry_word_free                (gpointer data);
+void            _gspell_entry_word_free                        (gpointer data);
 
 G_GNUC_INTERNAL
-GSList *        _gspell_entry_utils_get_words          (GtkEntry *entry);
+GSList *        _gspell_entry_utils_get_words                  (GtkEntry *entry);
+
+G_GNUC_INTERNAL
+gint            _gspell_entry_utils_get_char_position_at_event (GtkEntry       *entry,
+                                                                GdkEventButton *event);
 
 G_END_DECLS
 


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