[gspell/wip/apostrophe: 28/30] apostrophes: write _gspell_text_iter word-related functions



commit 487eb71050ef436bc3cbab9231c9df02f8e050d5
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Fri Feb 12 16:09:32 2016 +0100

    apostrophes: write _gspell_text_iter word-related functions
    
    https://bugzilla.gnome.org/show_bug.cgi?id=131576

 docs/reference/Makefile.am |    1 +
 gspell/Makefile.am         |    2 +
 gspell/gspell-text-iter.c  |  184 ++++++++++++++++++++++++++++++++++++++++++++
 gspell/gspell-text-iter.h  |   46 +++++++++++
 po/POTFILES.in             |    1 +
 5 files changed, 234 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index d81c64f..e27c6ef 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -23,6 +23,7 @@ IGNORE_HFILES =                                       \
        gspell-buffer-notifier.h                \
        gspell-inline-checker-text-buffer.h     \
        gspell-osx.h                            \
+       gspell-text-iter.h                      \
        gspell-text-region.h                    \
        gspell-utils.h
 
diff --git a/gspell/Makefile.am b/gspell/Makefile.am
index 1e6ddc3..80aba68 100644
--- a/gspell/Makefile.am
+++ b/gspell/Makefile.am
@@ -44,6 +44,7 @@ gspell_private_headers =                      \
        gconstructor.h                          \
        gspell-buffer-notifier.h                \
        gspell-inline-checker-text-buffer.h     \
+       gspell-text-iter.h                      \
        gspell-text-region.h                    \
        gspell-utils.h
 
@@ -51,6 +52,7 @@ gspell_private_c_files =                      \
        gspell-buffer-notifier.c                \
        gspell-init.c                           \
        gspell-inline-checker-text-buffer.c     \
+       gspell-text-iter.c                      \
        gspell-text-region.c                    \
        gspell-utils.c
 
diff --git a/gspell/gspell-text-iter.c b/gspell/gspell-text-iter.c
new file mode 100644
index 0000000..bd47bbe
--- /dev/null
+++ b/gspell/gspell-text-iter.c
@@ -0,0 +1,184 @@
+/*
+ * This file is part of gspell, a spell-checking library.
+ *
+ * Copyright 2016 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gspell-text-iter.h"
+
+/* The same functions as the gtk_text_iter_* equivalents, but take into account
+ * word contractions with an apostrophe. For example "doesn't", which is a
+ * contraction of the two words "does not".
+ *
+ * When to include an apostrophe in a word? The heuristic is that the apostrophe
+ * must be surrounded by a pango-defined word on *each* side of the apostrophe.
+ * In other words, there must be a word end on the left side and a word start on
+ * the right side.
+ *
+ * Note that with that rule, a word can contain several apostrophes, like
+ * "rock'n'roll". Usually such a word would be considered as misspelled, but
+ * it's important to take every apostrophes, otherwise the word boundaries would
+ * change depending on the GtkTextIter location, which would lead to bugs.
+ *
+ * Possible improvement: support words like "doin'" or "'til". That is, if the
+ * "internal" word ("doin" or "til") is surrounded by only one apostrophe, take
+ * the apostrophe. The implementation would be slightly more complicated, since
+ * a function behavior depends on the other side of the word.
+ *
+ * If the following Pango bug is fixed, normally the gtk_text_iter_* functions
+ * can be used directly.
+ * FIXME: https://bugzilla.gnome.org/show_bug.cgi?id=97545
+ * "Make pango_default_break follow Unicode TR #29"
+ */
+
+static gboolean
+is_apostrophe (const GtkTextIter *iter)
+{
+       gunichar ch;
+
+       ch = gtk_text_iter_get_char (iter);
+
+       return ch == '\'';
+}
+
+gboolean
+_gspell_text_iter_forward_word_end (GtkTextIter *iter)
+{
+       g_return_val_if_fail (iter != NULL, FALSE);
+
+       while (gtk_text_iter_forward_word_end (iter))
+       {
+               GtkTextIter next_char;
+
+               if (!is_apostrophe (iter))
+               {
+                       return TRUE;
+               }
+
+               next_char = *iter;
+               gtk_text_iter_forward_char (&next_char);
+
+               if (!gtk_text_iter_starts_word (&next_char))
+               {
+                       return TRUE;
+               }
+
+               *iter = next_char;
+       }
+
+       return FALSE;
+}
+
+gboolean
+_gspell_text_iter_backward_word_start (GtkTextIter *iter)
+{
+       g_return_val_if_fail (iter != NULL, FALSE);
+
+       while (gtk_text_iter_backward_word_start (iter))
+       {
+               GtkTextIter prev_char = *iter;
+
+               if (!gtk_text_iter_backward_char (&prev_char) ||
+                   !is_apostrophe (&prev_char) ||
+                   !gtk_text_iter_ends_word (&prev_char))
+               {
+                       return TRUE;
+               }
+
+               *iter = prev_char;
+       }
+
+       return FALSE;
+}
+
+gboolean
+_gspell_text_iter_starts_word (const GtkTextIter *iter)
+{
+       GtkTextIter prev_char;
+
+       g_return_val_if_fail (iter != NULL, FALSE);
+
+       if (!gtk_text_iter_starts_word (iter))
+       {
+               return FALSE;
+       }
+
+       prev_char = *iter;
+       if (!gtk_text_iter_backward_char (&prev_char))
+       {
+               return TRUE;
+       }
+
+       if (is_apostrophe (&prev_char) &&
+           gtk_text_iter_ends_word (&prev_char))
+       {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+gboolean
+_gspell_text_iter_ends_word (const GtkTextIter *iter)
+{
+       GtkTextIter next_char;
+
+       g_return_val_if_fail (iter != NULL, FALSE);
+
+       if (!gtk_text_iter_ends_word (iter))
+       {
+               return FALSE;
+       }
+
+       if (gtk_text_iter_is_end (iter))
+       {
+               return TRUE;
+       }
+
+       next_char = *iter;
+       gtk_text_iter_forward_char (&next_char);
+
+       if (is_apostrophe (iter) &&
+           gtk_text_iter_starts_word (&next_char))
+       {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+gboolean
+_gspell_text_iter_inside_word (const GtkTextIter *iter)
+{
+       g_return_val_if_fail (iter != NULL, FALSE);
+
+       if (gtk_text_iter_inside_word (iter))
+       {
+               return TRUE;
+       }
+
+       if (gtk_text_iter_ends_word (iter) &&
+           is_apostrophe (iter))
+       {
+               GtkTextIter next_char = *iter;
+               gtk_text_iter_forward_char (&next_char);
+               return gtk_text_iter_starts_word (&next_char);
+       }
+
+       return FALSE;
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gspell/gspell-text-iter.h b/gspell/gspell-text-iter.h
new file mode 100644
index 0000000..b344d43
--- /dev/null
+++ b/gspell/gspell-text-iter.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of gspell, a spell-checking library.
+ *
+ * Copyright 2016 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GSPELL_TEXT_ITER_H__
+#define __GSPELL_TEXT_ITER_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+G_GNUC_INTERNAL
+gboolean       _gspell_text_iter_forward_word_end      (GtkTextIter *iter);
+
+G_GNUC_INTERNAL
+gboolean       _gspell_text_iter_backward_word_start   (GtkTextIter *iter);
+
+G_GNUC_INTERNAL
+gboolean       _gspell_text_iter_starts_word           (const GtkTextIter *iter);
+
+G_GNUC_INTERNAL
+gboolean       _gspell_text_iter_ends_word             (const GtkTextIter *iter);
+
+G_GNUC_INTERNAL
+gboolean       _gspell_text_iter_inside_word           (const GtkTextIter *iter);
+
+G_END_DECLS
+
+#endif /* __GSPELL_TEXT_ITER_H__ */
+
+/* ex:set ts=8 noet: */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ea6ed5c..9cb374b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -12,6 +12,7 @@ gspell/gspell-navigator.c
 gspell/gspell-navigator-text-view.c
 gspell/gspell-osx.c
 gspell/gspell-text-buffer.c
+gspell/gspell-text-iter.c
 gspell/gspell-utils.c
 gspell/resources/checker-dialog.ui
 gspell/resources/language-dialog.ui


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