[gspell: 3/3] EntryUtils: improve word boundaries



commit 9cb5042708263f26ba5b689101388b67e1133990
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Wed Dec 21 18:03:36 2016 +0100

    EntryUtils: improve word boundaries

 gspell/gspell-entry-utils.c |   59 ++++++++++++++++++++++++++++++++++++++++++-
 testsuite/test-entry.c      |   40 +++++++++++++++++++++++++++++
 2 files changed, 98 insertions(+), 1 deletions(-)
---
diff --git a/gspell/gspell-entry-utils.c b/gspell/gspell-entry-utils.c
index 4d97a65..8e2dd10 100644
--- a/gspell/gspell-entry-utils.c
+++ b/gspell/gspell-entry-utils.c
@@ -19,6 +19,7 @@
 
 #include "gspell-entry-utils.h"
 #include <string.h>
+#include "gspell-utils.h"
 
 GspellEntryWord *
 _gspell_entry_word_new (void)
@@ -38,6 +39,58 @@ _gspell_entry_word_free (gpointer data)
        }
 }
 
+static void
+improve_word_boundaries (const gchar  *text,
+                        PangoLogAttr *log_attrs,
+                        gint          n_attrs)
+{
+       const gchar *cur_text_pos;
+       gint attr_num;
+
+       attr_num = 0;
+       cur_text_pos = text;
+
+       while (attr_num < n_attrs)
+       {
+               PangoLogAttr *log_attr_before;
+               gunichar ch;
+               PangoLogAttr *log_attr_after;
+
+               if (cur_text_pos == NULL ||
+                   *cur_text_pos == '\0')
+               {
+                       if (attr_num != n_attrs - 1)
+                       {
+                               g_warning ("%s(): problem in loop iteration, attr_num=%d but should be %d.",
+                                          G_STRFUNC,
+                                          attr_num,
+                                          n_attrs - 1);
+                       }
+
+                       break;
+               }
+
+               g_assert_cmpint (attr_num + 1, <, n_attrs);
+
+               /* ch is between log_attr_before and log_attr_after. */
+               log_attr_before = log_attrs + attr_num;
+               ch = g_utf8_get_char (cur_text_pos);
+               log_attr_after = log_attr_before + 1;
+
+               /* Same algo as in gspell-text-iter.c. */
+               if (_gspell_utils_is_apostrophe_or_dash (ch) &&
+                   log_attr_before->is_word_end &&
+                   log_attr_after->is_word_start)
+               {
+                       log_attr_before->is_word_end = FALSE;
+                       log_attr_after->is_word_start = FALSE;
+               }
+
+               attr_num++;
+               cur_text_pos = g_utf8_find_next_char (cur_text_pos, NULL);
+       }
+}
+
 /* Without the preedit string.
  * Free @log_attrs with g_free().
  */
@@ -47,21 +100,25 @@ get_pango_log_attrs (GtkEntry      *entry,
                     gint          *n_attrs)
 {
        GtkEntryBuffer *buffer;
+       const gchar *text;
 
        g_assert (log_attrs != NULL);
        g_assert (n_attrs != NULL);
 
        buffer = gtk_entry_get_buffer (entry);
+       text = gtk_entry_buffer_get_text (buffer);
 
        *n_attrs = gtk_entry_buffer_get_length (buffer) + 1;
        *log_attrs = g_new0 (PangoLogAttr, *n_attrs);
 
-       pango_get_log_attrs (gtk_entry_buffer_get_text (buffer),
+       pango_get_log_attrs (text,
                             gtk_entry_buffer_get_bytes (buffer),
                             -1,
                             NULL,
                             *log_attrs,
                             *n_attrs);
+
+       improve_word_boundaries (text, *log_attrs, *n_attrs);
 }
 
 /* Returns: (transfer full) (element-type GspellEntryWord): the list of words in
diff --git a/testsuite/test-entry.c b/testsuite/test-entry.c
index c372893..74a52a9 100644
--- a/testsuite/test-entry.c
+++ b/testsuite/test-entry.c
@@ -191,6 +191,46 @@ test_get_words (void)
        free_word_list (expected_list);
        free_word_list (received_list);
 
+       /* One apostrophe */
+       gtk_entry_set_text (entry, "doesn't");
+       expected_list = add_word_full (NULL, "doesn't", 0, 7, 0, 7);
+       received_list = _gspell_entry_utils_get_words (entry);
+       check_entry_word_list_equal (expected_list, received_list);
+       free_word_list (expected_list);
+       free_word_list (received_list);
+
+       /* Several apostrophes */
+       gtk_entry_set_text (entry, "rock'n'roll");
+       expected_list = add_word_full (NULL, "rock'n'roll", 0, 11, 0, 11);
+       received_list = _gspell_entry_utils_get_words (entry);
+       check_entry_word_list_equal (expected_list, received_list);
+       free_word_list (expected_list);
+       free_word_list (received_list);
+
+       /* Apostrophe at end of word. Not yet supported. */
+       gtk_entry_set_text (entry, "doin'");
+       expected_list = add_word_full (NULL, "doin", 0, 4, 0, 4);
+       received_list = _gspell_entry_utils_get_words (entry);
+       check_entry_word_list_equal (expected_list, received_list);
+       free_word_list (expected_list);
+       free_word_list (received_list);
+
+       /* Apostrophe at beginning of word. Not yet supported. */
+       gtk_entry_set_text (entry, "'til");
+       expected_list = add_word_full (NULL, "til", 1, 4, 1, 4);
+       received_list = _gspell_entry_utils_get_words (entry);
+       check_entry_word_list_equal (expected_list, received_list);
+       free_word_list (expected_list);
+       free_word_list (received_list);
+
+       /* Dash */
+       gtk_entry_set_text (entry, "spell-checking");
+       expected_list = add_word_full (NULL, "spell-checking", 0, 14, 0, 14);
+       received_list = _gspell_entry_utils_get_words (entry);
+       check_entry_word_list_equal (expected_list, received_list);
+       free_word_list (expected_list);
+       free_word_list (received_list);
+
        g_object_unref (entry);
 }
 


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