[gspell/gspell-1-0] Update GtkTextRegion -> GtkSourceRegion
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gspell/gspell-1-0] Update GtkTextRegion -> GtkSourceRegion
- Date: Sat, 9 Jul 2016 13:29:08 +0000 (UTC)
commit ed03328224b127f2c560d557c4fff8f269793cc4
Author: Sébastien Wilmet <swilmet gnome org>
Date: Wed Apr 6 11:40:38 2016 +0200
Update GtkTextRegion -> GtkSourceRegion
The filenames are now gspellregion.*, not gspell-region.*, so it's easy
to distinguish the foreign code (to count the number of lines for
example).
docs/reference/Makefile.am | 2 +-
gspell/Makefile.am | 4 +-
gspell/gspell-inline-checker-text-buffer.c | 101 +--
gspell/gspell-text-region.c | 688 ----------------
gspell/gspell-text-region.h | 100 ---
gspell/gspellregion.c | 1176 ++++++++++++++++++++++++++++
gspell/gspellregion.h | 113 +++
gspell/update-sourceregion.sh | 31 +
gspell/update-textregion.sh | 32 -
9 files changed, 1349 insertions(+), 898 deletions(-)
---
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index 10b8673..b9504eb 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -24,11 +24,11 @@ CFILE_GLOB = $(top_srcdir)/gspell/*.c
# Header files or dirs to ignore when scanning. Use base file/dir names
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
IGNORE_HFILES = \
+ gspellregion.h \
gspell-init.h \
gspell-inline-checker-text-buffer.h \
gspell-osx.h \
gspell-text-iter.h \
- gspell-text-region.h \
gspell-utils.h
# Extra options to supply to gtkdoc-mkdb
diff --git a/gspell/Makefile.am b/gspell/Makefile.am
index 5752db7..8791f2a 100644
--- a/gspell/Makefile.am
+++ b/gspell/Makefile.am
@@ -43,17 +43,17 @@ gspell_public_c_files = \
gspell_private_headers = \
gconstructor.h \
+ gspellregion.h \
gspell-init.h \
gspell-inline-checker-text-buffer.h \
gspell-text-iter.h \
- gspell-text-region.h \
gspell-utils.h
gspell_private_c_files = \
+ gspellregion.c \
gspell-init.c \
gspell-inline-checker-text-buffer.c \
gspell-text-iter.c \
- gspell-text-region.c \
gspell-utils.c
# Helper Libtool library, so that the private functions can be used in unit
diff --git a/gspell/gspell-inline-checker-text-buffer.c b/gspell/gspell-inline-checker-text-buffer.c
index 34c04ca..9fcfe78 100644
--- a/gspell/gspell-inline-checker-text-buffer.c
+++ b/gspell/gspell-inline-checker-text-buffer.c
@@ -26,10 +26,10 @@
#include "gspell-inline-checker-text-buffer.h"
#include <string.h>
#include <glib/gi18n-lib.h>
+#include "gspellregion.h"
#include "gspell-checker.h"
#include "gspell-text-buffer.h"
#include "gspell-text-iter.h"
-#include "gspell-text-region.h"
#include "gspell-utils.h"
struct _GspellInlineCheckerTextBuffer
@@ -47,7 +47,7 @@ struct _GspellInlineCheckerTextBuffer
GtkTextMark *mark_click;
- GspellTextRegion *scan_region;
+ GspellRegion *scan_region;
guint timeout_id;
/* When a word is being typed, it should not be marked as misspelled,
@@ -258,47 +258,6 @@ get_visible_region (GtkTextView *view,
gtk_text_iter_forward_line (end);
}
-/* A TextRegion can contain empty subregions. So checking the number of
- * subregions is not sufficient.
- * When calling text_region_add() with equal iters, the subregion is not
- * added. But when a subregion becomes empty, due to text deletion, the
- * subregion is not removed from the TextRegion.
- */
-static gboolean
-is_text_region_empty (GspellTextRegion *region)
-{
- GspellTextRegionIterator region_iter;
-
- if (region == NULL)
- {
- return TRUE;
- }
-
- _gspell_text_region_get_iterator (region, ®ion_iter, 0);
-
- while (!_gspell_text_region_iterator_is_end (®ion_iter))
- {
- GtkTextIter region_start;
- GtkTextIter region_end;
-
- if (!_gspell_text_region_iterator_get_subregion (®ion_iter,
- ®ion_start,
- ®ion_end))
- {
- return TRUE;
- }
-
- if (!gtk_text_iter_equal (®ion_start, ®ion_end))
- {
- return FALSE;
- }
-
- _gspell_text_region_iterator_next (®ion_iter);
- }
-
- return TRUE;
-}
-
/* Returns TRUE if there is a current word. */
static gboolean
get_current_word_boundaries (GtkTextBuffer *buffer,
@@ -334,8 +293,8 @@ check_visible_region_in_view (GspellInlineCheckerTextBuffer *spell,
{
GtkTextIter visible_start;
GtkTextIter visible_end;
- GspellTextRegion *intersect;
- GspellTextRegionIterator intersect_iter;
+ GspellRegion *intersect;
+ GspellRegionIter intersect_iter;
if (spell->scan_region == NULL)
{
@@ -352,9 +311,9 @@ check_visible_region_in_view (GspellInlineCheckerTextBuffer *spell,
gtk_text_buffer_get_bounds (spell->buffer, &visible_start, &visible_end);
}
- intersect = _gspell_text_region_intersect (spell->scan_region,
- &visible_start,
- &visible_end);
+ intersect = _gspell_region_intersect (spell->scan_region,
+ &visible_start,
+ &visible_end);
if (intersect == NULL)
{
@@ -375,37 +334,35 @@ check_visible_region_in_view (GspellInlineCheckerTextBuffer *spell,
¤t_word_start,
¤t_word_end);
- _gspell_text_region_subtract (intersect,
- ¤t_word_start,
- ¤t_word_end);
+ _gspell_region_subtract (intersect,
+ ¤t_word_start,
+ ¤t_word_end);
/* Be sure that the current word will be re-checked
* later when it will no longer be the current word.
*/
- _gspell_text_region_add (spell->scan_region,
- ¤t_word_start,
- ¤t_word_end);
+ _gspell_region_add (spell->scan_region,
+ ¤t_word_start,
+ ¤t_word_end);
}
}
- if (is_text_region_empty (intersect))
+ if (_gspell_region_is_empty (intersect))
{
- _gspell_text_region_destroy (intersect);
+ g_clear_object (&intersect);
goto out;
}
- _gspell_text_region_get_iterator (intersect, &intersect_iter, 0);
+ _gspell_region_get_start_region_iter (intersect, &intersect_iter);
- while (!_gspell_text_region_iterator_is_end (&intersect_iter))
+ while (!_gspell_region_iter_is_end (&intersect_iter))
{
GtkTextIter start;
GtkTextIter end;
GtkTextIter orig_start;
GtkTextIter orig_end;
- if (!_gspell_text_region_iterator_get_subregion (&intersect_iter,
- &start,
- &end))
+ if (!_gspell_region_iter_get_subregion (&intersect_iter, &start, &end))
{
break;
}
@@ -422,17 +379,16 @@ check_visible_region_in_view (GspellInlineCheckerTextBuffer *spell,
g_assert (gtk_text_iter_compare (&start, &orig_start) <= 0);
g_assert (gtk_text_iter_compare (&orig_end, &end) <= 0);
- _gspell_text_region_subtract (spell->scan_region, &start, &end);
+ _gspell_region_subtract (spell->scan_region, &start, &end);
- _gspell_text_region_iterator_next (&intersect_iter);
+ _gspell_region_iter_next (&intersect_iter);
}
- _gspell_text_region_destroy (intersect);
+ g_clear_object (&intersect);
- if (is_text_region_empty (spell->scan_region))
+ if (_gspell_region_is_empty (spell->scan_region))
{
- _gspell_text_region_destroy (spell->scan_region);
- spell->scan_region = NULL;
+ g_clear_object (&spell->scan_region);
}
out:
@@ -506,10 +462,10 @@ add_subregion_to_scan (GspellInlineCheckerTextBuffer *spell,
{
if (spell->scan_region == NULL)
{
- spell->scan_region = _gspell_text_region_new (spell->buffer);
+ spell->scan_region = _gspell_region_new (spell->buffer);
}
- _gspell_text_region_add (spell->scan_region, start, end);
+ _gspell_region_add (spell->scan_region, start, end);
}
static void
@@ -1364,18 +1320,13 @@ _gspell_inline_checker_text_buffer_dispose (GObject *object)
g_clear_object (&spell->highlight_tag);
g_clear_object (&spell->no_spell_check_tag);
+ g_clear_object (&spell->scan_region);
g_slist_free (spell->views);
spell->views = NULL;
spell->mark_click = NULL;
- if (spell->scan_region != NULL)
- {
- _gspell_text_region_destroy (spell->scan_region);
- spell->scan_region = NULL;
- }
-
if (spell->timeout_id != 0)
{
g_source_remove (spell->timeout_id);
diff --git a/gspell/gspellregion.c b/gspell/gspellregion.c
new file mode 100644
index 0000000..3b41f30
--- /dev/null
+++ b/gspell/gspellregion.c
@@ -0,0 +1,1176 @@
+/* Do not edit: this file is generated from
https://git.gnome.org/browse/gtksourceview/plain/gtksourceview/gtksourceregion.c */
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * gspellregion.c - GtkTextMark-based region utility
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo giraldez gmx net>
+ * Copyright (C) 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "gspellregion.h"
+
+/**
+ * SECTION:region
+ * @Short_description: Region utility
+ * @Title: GspellRegion
+ * @See_also: #GtkTextBuffer
+ *
+ * A #GspellRegion permits to store a group of subregions of a
+ * #GtkTextBuffer. #GspellRegion stores the subregions with pairs of
+ * #GtkTextMark's, so the region is still valid after insertions and deletions
+ * in the #GtkTextBuffer.
+ *
+ * The #GtkTextMark for the start of a subregion has a left gravity, while the
+ * #GtkTextMark for the end of a subregion has a right gravity.
+ *
+ * The typical use-case of #GspellRegion is to scan a #GtkTextBuffer chunk by
+ * chunk, not the whole buffer at once to not block the user interface. The
+ * #GspellRegion represents in that case the remaining region to scan. You
+ * can listen to the #GtkTextBuffer::insert-text and
+ * #GtkTextBuffer::delete-range signals to update the #GspellRegion
+ * accordingly.
+ *
+ * To iterate through the subregions, you need to use a #GspellRegionIter,
+ * for example:
+ * |[
+ * GspellRegion *region;
+ * GspellRegionIter region_iter;
+ *
+ * _gspell_region_get_start_region_iter (region, ®ion_iter);
+ *
+ * while (!_gspell_region_iter_is_end (®ion_iter))
+ * {
+ * GtkTextIter subregion_start;
+ * GtkTextIter subregion_end;
+ *
+ * if (!_gspell_region_iter_get_subregion (®ion_iter,
+ * &subregion_start,
+ * &subregion_end))
+ * {
+ * break;
+ * }
+ *
+ * // Do something useful with the subregion.
+ *
+ * _gspell_region_iter_next (®ion_iter);
+ * }
+ * ]|
+ */
+
+/* With the gravities of the GtkTextMarks, it is possible for subregions to
+ * become interlaced:
+ * Buffer content:
+ * "hello world"
+ * Add two subregions:
+ * "[hello] [world]"
+ * Delete the space:
+ * "[hello][world]"
+ * Undo:
+ * "[hello[ ]world]"
+ *
+ * FIXME: when iterating through the subregions, it should simplify them first.
+ * I don't know if it's done (swilmet).
+ */
+
+#undef ENABLE_DEBUG
+/*
+#define ENABLE_DEBUG
+*/
+
+#ifdef ENABLE_DEBUG
+#define DEBUG(x) (x)
+#else
+#define DEBUG(x)
+#endif
+
+typedef struct _GspellRegionPrivate GspellRegionPrivate;
+typedef struct _Subregion Subregion;
+typedef struct _GspellRegionIterReal GspellRegionIterReal;
+
+struct _GspellRegionPrivate
+{
+ /* Weak pointer to the buffer. */
+ GtkTextBuffer *buffer;
+
+ /* List of sorted 'Subregion*' */
+ GList *subregions;
+
+ guint32 timestamp;
+};
+
+struct _Subregion
+{
+ GtkTextMark *start;
+ GtkTextMark *end;
+};
+
+struct _GspellRegionIterReal
+{
+ GspellRegion *region;
+ guint32 region_timestamp;
+ GList *subregions;
+};
+
+enum
+{
+ PROP_0,
+ PROP_BUFFER,
+ LAST_PROP
+};
+
+static GParamSpec *properties[LAST_PROP];
+
+G_DEFINE_TYPE_WITH_PRIVATE (GspellRegion, _gspell_region, G_TYPE_OBJECT)
+
+#ifdef ENABLE_DEBUG
+static void
+print_region (GspellRegion *region)
+{
+ gchar *str;
+
+ str = _gspell_region_to_string (region);
+ g_print ("%s\n", str);
+ g_free (str);
+}
+#endif
+
+/* Find and return a subregion node which contains the given text
+ * iter. If left_side is TRUE, return the subregion which contains
+ * the text iter or which is the leftmost; else return the rightmost
+ * subregion.
+ */
+static GList *
+find_nearest_subregion (GspellRegion *region,
+ const GtkTextIter *iter,
+ GList *begin,
+ gboolean leftmost,
+ gboolean include_edges)
+{
+ GspellRegionPrivate *priv = _gspell_region_get_instance_private (region);
+ GList *retval;
+ GList *l;
+
+ g_assert (iter != NULL);
+
+ if (begin == NULL)
+ {
+ begin = priv->subregions;
+ }
+
+ if (begin != NULL)
+ {
+ retval = begin->prev;
+ }
+ else
+ {
+ retval = NULL;
+ }
+
+ for (l = begin; l != NULL; l = l->next)
+ {
+ GtkTextIter sr_iter;
+ Subregion *sr = l->data;
+ gint cmp;
+
+ if (!leftmost)
+ {
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &sr_iter, sr->end);
+ cmp = gtk_text_iter_compare (iter, &sr_iter);
+ if (cmp < 0 || (cmp == 0 && include_edges))
+ {
+ retval = l;
+ break;
+ }
+
+ }
+ else
+ {
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &sr_iter, sr->start);
+ cmp = gtk_text_iter_compare (iter, &sr_iter);
+ if (cmp > 0 || (cmp == 0 && include_edges))
+ {
+ retval = l;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ return retval;
+}
+
+static void
+_gspell_region_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GspellRegion *region = GSPELL_REGION (object);
+
+ switch (prop_id)
+ {
+ case PROP_BUFFER:
+ g_value_set_object (value, _gspell_region_get_buffer (region));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_gspell_region_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GspellRegionPrivate *priv = _gspell_region_get_instance_private (GSPELL_REGION (object));
+
+ switch (prop_id)
+ {
+ case PROP_BUFFER:
+ g_assert (priv->buffer == NULL);
+ priv->buffer = g_value_get_object (value);
+ g_object_add_weak_pointer (G_OBJECT (priv->buffer),
+ (gpointer *) &priv->buffer);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_gspell_region_dispose (GObject *object)
+{
+ GspellRegionPrivate *priv = _gspell_region_get_instance_private (GSPELL_REGION (object));
+
+ while (priv->subregions != NULL)
+ {
+ Subregion *sr = priv->subregions->data;
+
+ if (priv->buffer != NULL)
+ {
+ gtk_text_buffer_delete_mark (priv->buffer, sr->start);
+ gtk_text_buffer_delete_mark (priv->buffer, sr->end);
+ }
+
+ g_slice_free (Subregion, sr);
+ priv->subregions = g_list_delete_link (priv->subregions, priv->subregions);
+ }
+
+ if (priv->buffer != NULL)
+ {
+ g_object_remove_weak_pointer (G_OBJECT (priv->buffer),
+ (gpointer *) &priv->buffer);
+
+ priv->buffer = NULL;
+ }
+
+ G_OBJECT_CLASS (_gspell_region_parent_class)->dispose (object);
+}
+
+static void
+_gspell_region_class_init (GspellRegionClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = _gspell_region_get_property;
+ object_class->set_property = _gspell_region_set_property;
+ object_class->dispose = _gspell_region_dispose;
+
+ /**
+ * GspellRegion:buffer:
+ *
+ * The #GtkTextBuffer. The #GspellRegion has a weak reference to the
+ * buffer.
+ *
+ * Since: 3.22
+ */
+ properties[PROP_BUFFER] =
+ g_param_spec_object ("buffer",
+ "Buffer",
+ "",
+ GTK_TYPE_TEXT_BUFFER,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, properties);
+}
+
+static void
+_gspell_region_init (GspellRegion *region)
+{
+}
+
+/**
+ * _gspell_region_new:
+ * @buffer: a #GtkTextBuffer.
+ *
+ * Returns: a new #GspellRegion object for @buffer.
+ * Since: 3.22
+ */
+GspellRegion *
+_gspell_region_new (GtkTextBuffer *buffer)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
+
+ return g_object_new (GSPELL_TYPE_REGION,
+ "buffer", buffer,
+ NULL);
+}
+
+/**
+ * _gspell_region_get_buffer:
+ * @region: a #GspellRegion.
+ *
+ * Returns: (transfer none) (nullable): the #GtkTextBuffer.
+ * Since: 3.22
+ */
+GtkTextBuffer *
+_gspell_region_get_buffer (GspellRegion *region)
+{
+ GspellRegionPrivate *priv;
+
+ g_return_val_if_fail (GSPELL_IS_REGION (region), NULL);
+
+ priv = _gspell_region_get_instance_private (region);
+ return priv->buffer;
+}
+
+static void
+_gspell_region_clear_zero_length_subregions (GspellRegion *region)
+{
+ GspellRegionPrivate *priv = _gspell_region_get_instance_private (region);
+ GList *node;
+
+ node = priv->subregions;
+ while (node != NULL)
+ {
+ Subregion *sr = node->data;
+ GtkTextIter start;
+ GtkTextIter end;
+
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &start, sr->start);
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &end, sr->end);
+
+ if (gtk_text_iter_equal (&start, &end))
+ {
+ gtk_text_buffer_delete_mark (priv->buffer, sr->start);
+ gtk_text_buffer_delete_mark (priv->buffer, sr->end);
+ g_slice_free (Subregion, sr);
+
+ if (node == priv->subregions)
+ {
+ priv->subregions = node = g_list_delete_link (node, node);
+ }
+ else
+ {
+ node = g_list_delete_link (node, node);
+ }
+
+ priv->timestamp++;
+ }
+ else
+ {
+ node = node->next;
+ }
+ }
+}
+
+/**
+ * _gspell_region_add:
+ * @region: a #GspellRegion.
+ * @_start: the start of the subregion.
+ * @_end: the end of the subregion.
+ *
+ * Adds the subregion delimited by @_start and @_end to @region.
+ *
+ * Since: 3.22
+ */
+void
+_gspell_region_add (GspellRegion *region,
+ const GtkTextIter *_start,
+ const GtkTextIter *_end)
+{
+ GspellRegionPrivate *priv;
+ GList *start_node;
+ GList *end_node;
+ GtkTextIter start;
+ GtkTextIter end;
+
+ g_return_if_fail (GSPELL_IS_REGION (region));
+ g_return_if_fail (_start != NULL);
+ g_return_if_fail (_end != NULL);
+
+ priv = _gspell_region_get_instance_private (region);
+
+ if (priv->buffer == NULL)
+ {
+ return;
+ }
+
+ start = *_start;
+ end = *_end;
+
+ DEBUG (g_print ("---\n"));
+ DEBUG (print_region (region));
+ DEBUG (g_message ("region_add (%d, %d)",
+ gtk_text_iter_get_offset (&start),
+ gtk_text_iter_get_offset (&end)));
+
+ gtk_text_iter_order (&start, &end);
+
+ /* Don't add zero-length regions. */
+ if (gtk_text_iter_equal (&start, &end))
+ {
+ return;
+ }
+
+ /* Find bounding subregions. */
+ start_node = find_nearest_subregion (region, &start, NULL, FALSE, TRUE);
+ end_node = find_nearest_subregion (region, &end, start_node, TRUE, TRUE);
+
+ if (start_node == NULL || end_node == NULL || end_node == start_node->prev)
+ {
+ /* Create the new subregion. */
+ Subregion *sr = g_slice_new0 (Subregion);
+ sr->start = gtk_text_buffer_create_mark (priv->buffer, NULL, &start, TRUE);
+ sr->end = gtk_text_buffer_create_mark (priv->buffer, NULL, &end, FALSE);
+
+ if (start_node == NULL)
+ {
+ /* Append the new region. */
+ priv->subregions = g_list_append (priv->subregions, sr);
+ }
+ else if (end_node == NULL)
+ {
+ /* Prepend the new region. */
+ priv->subregions = g_list_prepend (priv->subregions, sr);
+ }
+ else
+ {
+ /* We are in the middle of two subregions. */
+ priv->subregions = g_list_insert_before (priv->subregions, start_node, sr);
+ }
+ }
+ else
+ {
+ GtkTextIter iter;
+ Subregion *sr = start_node->data;
+
+ if (start_node != end_node)
+ {
+ /* We need to merge some subregions. */
+ GList *l = start_node->next;
+ Subregion *q;
+
+ gtk_text_buffer_delete_mark (priv->buffer, sr->end);
+
+ while (l != end_node)
+ {
+ q = l->data;
+ gtk_text_buffer_delete_mark (priv->buffer, q->start);
+ gtk_text_buffer_delete_mark (priv->buffer, q->end);
+ g_slice_free (Subregion, q);
+ l = g_list_delete_link (l, l);
+ }
+
+ q = l->data;
+ gtk_text_buffer_delete_mark (priv->buffer, q->start);
+ sr->end = q->end;
+ g_slice_free (Subregion, q);
+ l = g_list_delete_link (l, l);
+ }
+
+ /* Now move marks if that action expands the region. */
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &iter, sr->start);
+ if (gtk_text_iter_compare (&iter, &start) > 0)
+ {
+ gtk_text_buffer_move_mark (priv->buffer, sr->start, &start);
+ }
+
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &iter, sr->end);
+ if (gtk_text_iter_compare (&iter, &end) < 0)
+ {
+ gtk_text_buffer_move_mark (priv->buffer, sr->end, &end);
+ }
+ }
+
+ priv->timestamp++;
+
+ DEBUG (print_region (region));
+}
+
+/**
+ * _gspell_region_subtract:
+ * @region: a #GspellRegion.
+ * @_start: the start of the subregion.
+ * @_end: the end of the subregion.
+ *
+ * Subtracts the subregion delimited by @_start and @_end from @region.
+ *
+ * Since: 3.22
+ */
+void
+_gspell_region_subtract (GspellRegion *region,
+ const GtkTextIter *_start,
+ const GtkTextIter *_end)
+{
+ GspellRegionPrivate *priv;
+ GList *start_node;
+ GList *end_node;
+ GList *node;
+ GtkTextIter sr_start_iter;
+ GtkTextIter sr_end_iter;
+ gboolean done;
+ gboolean start_is_outside;
+ gboolean end_is_outside;
+ Subregion *sr;
+ GtkTextIter start;
+ GtkTextIter end;
+
+ g_return_if_fail (GSPELL_IS_REGION (region));
+ g_return_if_fail (_start != NULL);
+ g_return_if_fail (_end != NULL);
+
+ priv = _gspell_region_get_instance_private (region);
+
+ if (priv->buffer == NULL)
+ {
+ return;
+ }
+
+ start = *_start;
+ end = *_end;
+
+ DEBUG (g_print ("---\n"));
+ DEBUG (print_region (region));
+ DEBUG (g_message ("region_substract (%d, %d)",
+ gtk_text_iter_get_offset (&start),
+ gtk_text_iter_get_offset (&end)));
+
+ gtk_text_iter_order (&start, &end);
+
+ /* Find bounding subregions. */
+ start_node = find_nearest_subregion (region, &start, NULL, FALSE, FALSE);
+ end_node = find_nearest_subregion (region, &end, start_node, TRUE, FALSE);
+
+ /* Easy case first. */
+ if (start_node == NULL || end_node == NULL || end_node == start_node->prev)
+ {
+ return;
+ }
+
+ /* Deal with the start point. */
+ start_is_outside = end_is_outside = FALSE;
+
+ sr = start_node->data;
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &sr_start_iter, sr->start);
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &sr_end_iter, sr->end);
+
+ if (gtk_text_iter_in_range (&start, &sr_start_iter, &sr_end_iter) &&
+ !gtk_text_iter_equal (&start, &sr_start_iter))
+ {
+ /* The starting point is inside the first subregion. */
+ if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter) &&
+ !gtk_text_iter_equal (&end, &sr_end_iter))
+ {
+ /* The ending point is also inside the first
+ * subregion: we need to split.
+ */
+ Subregion *new_sr = g_slice_new0 (Subregion);
+ new_sr->end = sr->end;
+ new_sr->start = gtk_text_buffer_create_mark (priv->buffer,
+ NULL,
+ &end,
+ TRUE);
+
+ start_node = g_list_insert_before (start_node, start_node->next, new_sr);
+
+ sr->end = gtk_text_buffer_create_mark (priv->buffer,
+ NULL,
+ &start,
+ FALSE);
+
+ /* No further processing needed. */
+ DEBUG (g_message ("subregion splitted"));
+
+ return;
+ }
+ else
+ {
+ /* The ending point is outside, so just move
+ * the end of the subregion to the starting point.
+ */
+ gtk_text_buffer_move_mark (priv->buffer, sr->end, &start);
+ }
+ }
+ else
+ {
+ /* The starting point is outside (and so to the left)
+ * of the first subregion.
+ */
+ DEBUG (g_message ("start is outside"));
+
+ start_is_outside = TRUE;
+ }
+
+ /* Deal with the end point. */
+ if (start_node != end_node)
+ {
+ sr = end_node->data;
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &sr_start_iter, sr->start);
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &sr_end_iter, sr->end);
+ }
+
+ if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter) &&
+ !gtk_text_iter_equal (&end, &sr_end_iter))
+ {
+ /* Ending point is inside, move the start mark. */
+ gtk_text_buffer_move_mark (priv->buffer, sr->start, &end);
+ }
+ else
+ {
+ end_is_outside = TRUE;
+ DEBUG (g_message ("end is outside"));
+ }
+
+ /* Finally remove any intermediate subregions. */
+ done = FALSE;
+ node = start_node;
+
+ while (!done)
+ {
+ if (node == end_node)
+ {
+ /* We are done, exit in the next iteration. */
+ done = TRUE;
+ }
+
+ if ((node == start_node && !start_is_outside) ||
+ (node == end_node && !end_is_outside))
+ {
+ /* Skip starting or ending node. */
+ node = node->next;
+ }
+ else
+ {
+ GList *l = node->next;
+ sr = node->data;
+ gtk_text_buffer_delete_mark (priv->buffer, sr->start);
+ gtk_text_buffer_delete_mark (priv->buffer, sr->end);
+ g_slice_free (Subregion, sr);
+ priv->subregions = g_list_delete_link (priv->subregions, node);
+ node = l;
+ }
+ }
+
+ priv->timestamp++;
+
+ DEBUG (print_region (region));
+
+ /* Now get rid of empty subregions. */
+ _gspell_region_clear_zero_length_subregions (region);
+
+ DEBUG (print_region (region));
+}
+
+/**
+ * _gspell_region_is_empty:
+ * @region: (nullable): a #GspellRegion, or %NULL.
+ *
+ * Returns whether the @region is empty. A %NULL @region is considered empty.
+ *
+ * Returns: whether the @region is empty.
+ * Since: 3.22
+ */
+gboolean
+_gspell_region_is_empty (GspellRegion *region)
+{
+ GspellRegionIter region_iter;
+
+ if (region == NULL)
+ {
+ return TRUE;
+ }
+
+ /* A #GspellRegion can contain empty subregions. So checking the
+ * number of subregions is not sufficient.
+ * When calling _gspell_region_add() with equal iters, the subregion
+ * is not added. But when a subregion becomes empty, due to text
+ * deletion, the subregion is not removed from the #GspellRegion.
+ */
+
+ _gspell_region_get_start_region_iter (region, ®ion_iter);
+
+ while (!_gspell_region_iter_is_end (®ion_iter))
+ {
+ GtkTextIter subregion_start;
+ GtkTextIter subregion_end;
+
+ if (!_gspell_region_iter_get_subregion (®ion_iter,
+ &subregion_start,
+ &subregion_end))
+ {
+ return TRUE;
+ }
+
+ if (!gtk_text_iter_equal (&subregion_start, &subregion_end))
+ {
+ return FALSE;
+ }
+
+ _gspell_region_iter_next (®ion_iter);
+ }
+
+ return TRUE;
+}
+
+/**
+ * _gspell_region_get_bounds:
+ * @region: a #GspellRegion.
+ * @start: (out) (optional): iterator to initialize with the start of @region,
+ * or %NULL.
+ * @end: (out) (optional): iterator to initialize with the end of @region,
+ * or %NULL.
+ *
+ * Gets the @start and @end bounds of the @region.
+ *
+ * Returns: %TRUE if @start and @end have been set successfully (if non-%NULL),
+ * or %FALSE if the @region is empty.
+ * Since: 3.22
+ */
+gboolean
+_gspell_region_get_bounds (GspellRegion *region,
+ GtkTextIter *start,
+ GtkTextIter *end)
+{
+ GspellRegionPrivate *priv;
+
+ g_return_val_if_fail (GSPELL_IS_REGION (region), FALSE);
+
+ priv = _gspell_region_get_instance_private (region);
+
+ if (priv->buffer == NULL ||
+ _gspell_region_is_empty (region))
+ {
+ return FALSE;
+ }
+
+ g_assert (priv->subregions != NULL);
+
+ if (start != NULL)
+ {
+ Subregion *first_subregion = priv->subregions->data;
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, start, first_subregion->start);
+ }
+
+ if (end != NULL)
+ {
+ Subregion *last_subregion = g_list_last (priv->subregions)->data;
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, end, last_subregion->end);
+ }
+
+ return TRUE;
+}
+
+/**
+ * _gspell_region_intersect:
+ * @region: a #GspellRegion.
+ * @_start: the start of the subregion.
+ * @_end: the end of the subregion.
+ *
+ * Computes the intersection between @region and the subregion delimited by
+ * @_start and @_end.
+ *
+ * Returns: (transfer full) (nullable): the intersection as a new
+ * #GspellRegion.
+ * Since: 3.22
+ */
+GspellRegion *
+_gspell_region_intersect (GspellRegion *region,
+ const GtkTextIter *_start,
+ const GtkTextIter *_end)
+{
+ GspellRegionPrivate *priv;
+ GspellRegion *new_region;
+ GspellRegionPrivate *new_priv;
+ GList *start_node;
+ GList *end_node;
+ GList *node;
+ GtkTextIter sr_start_iter;
+ GtkTextIter sr_end_iter;
+ Subregion *sr;
+ Subregion *new_sr;
+ gboolean done;
+ GtkTextIter start;
+ GtkTextIter end;
+
+ g_return_val_if_fail (GSPELL_IS_REGION (region), NULL);
+ g_return_val_if_fail (_start != NULL, NULL);
+ g_return_val_if_fail (_end != NULL, NULL);
+
+ priv = _gspell_region_get_instance_private (region);
+
+ if (priv->buffer == NULL)
+ {
+ return NULL;
+ }
+
+ start = *_start;
+ end = *_end;
+
+ gtk_text_iter_order (&start, &end);
+
+ /* Find bounding subregions. */
+ start_node = find_nearest_subregion (region, &start, NULL, FALSE, FALSE);
+ end_node = find_nearest_subregion (region, &end, start_node, TRUE, FALSE);
+
+ /* Easy case first. */
+ if (start_node == NULL || end_node == NULL || end_node == start_node->prev)
+ {
+ return NULL;
+ }
+
+ new_region = _gspell_region_new (priv->buffer);
+ new_priv = _gspell_region_get_instance_private (new_region);
+ done = FALSE;
+
+ sr = start_node->data;
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &sr_start_iter, sr->start);
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &sr_end_iter, sr->end);
+
+ /* Starting node. */
+ if (gtk_text_iter_in_range (&start, &sr_start_iter, &sr_end_iter))
+ {
+ new_sr = g_slice_new0 (Subregion);
+ new_priv->subregions = g_list_prepend (new_priv->subregions, new_sr);
+
+ new_sr->start = gtk_text_buffer_create_mark (new_priv->buffer,
+ NULL,
+ &start,
+ TRUE);
+
+ if (start_node == end_node)
+ {
+ /* Things will finish shortly. */
+ done = TRUE;
+ if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter))
+ {
+ new_sr->end = gtk_text_buffer_create_mark (new_priv->buffer,
+ NULL,
+ &end,
+ FALSE);
+ }
+ else
+ {
+ new_sr->end = gtk_text_buffer_create_mark (new_priv->buffer,
+ NULL,
+ &sr_end_iter,
+ FALSE);
+ }
+ }
+ else
+ {
+ new_sr->end = gtk_text_buffer_create_mark (new_priv->buffer,
+ NULL,
+ &sr_end_iter,
+ FALSE);
+ }
+
+ node = start_node->next;
+ }
+ else
+ {
+ /* start should be the same as the subregion, so copy it in the
+ * loop.
+ */
+ node = start_node;
+ }
+
+ if (!done)
+ {
+ while (node != end_node)
+ {
+ /* Copy intermediate subregions verbatim. */
+ sr = node->data;
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &sr_start_iter, sr->start);
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &sr_end_iter, sr->end);
+
+ new_sr = g_slice_new0 (Subregion);
+ new_priv->subregions = g_list_prepend (new_priv->subregions, new_sr);
+
+ new_sr->start = gtk_text_buffer_create_mark (new_priv->buffer,
+ NULL,
+ &sr_start_iter,
+ TRUE);
+
+ new_sr->end = gtk_text_buffer_create_mark (new_priv->buffer,
+ NULL,
+ &sr_end_iter,
+ FALSE);
+
+ /* Next node. */
+ node = node->next;
+ }
+
+ /* Ending node. */
+ sr = node->data;
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &sr_start_iter, sr->start);
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &sr_end_iter, sr->end);
+
+ new_sr = g_slice_new0 (Subregion);
+ new_priv->subregions = g_list_prepend (new_priv->subregions, new_sr);
+
+ new_sr->start = gtk_text_buffer_create_mark (new_priv->buffer,
+ NULL,
+ &sr_start_iter,
+ TRUE);
+
+ if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter))
+ {
+ new_sr->end = gtk_text_buffer_create_mark (new_priv->buffer,
+ NULL,
+ &end,
+ FALSE);
+ }
+ else
+ {
+ new_sr->end = gtk_text_buffer_create_mark (new_priv->buffer,
+ NULL,
+ &sr_end_iter,
+ FALSE);
+ }
+ }
+
+ new_priv->subregions = g_list_reverse (new_priv->subregions);
+ return new_region;
+}
+
+static gboolean
+check_iterator (GspellRegionIterReal *real)
+{
+ GspellRegionPrivate *priv;
+
+ if (real->region == NULL)
+ {
+ goto invalid;
+ }
+
+ priv = _gspell_region_get_instance_private (real->region);
+
+ if (real->region_timestamp == priv->timestamp)
+ {
+ return TRUE;
+ }
+
+invalid:
+ g_warning ("Invalid GspellRegionIter: either the iterator is "
+ "uninitialized, or the region has been modified since the "
+ "iterator was created.");
+
+ return FALSE;
+}
+
+/**
+ * _gspell_region_get_start_region_iter:
+ * @region: a #GspellRegion.
+ * @iter: (out): iterator to initialize to the first subregion.
+ *
+ * Initializes a #GspellRegionIter to the first subregion of @region. If
+ * @region is empty, @iter will be initialized to the end iterator.
+ *
+ * Since: 3.22
+ */
+void
+_gspell_region_get_start_region_iter (GspellRegion *region,
+ GspellRegionIter *iter)
+{
+ GspellRegionPrivate *priv;
+ GspellRegionIterReal *real;
+
+ g_return_if_fail (GSPELL_IS_REGION (region));
+ g_return_if_fail (iter != NULL);
+
+ priv = _gspell_region_get_instance_private (region);
+ real = (GspellRegionIterReal *)iter;
+
+ /* priv->subregions may be NULL, -> end iter */
+
+ real->region = region;
+ real->subregions = priv->subregions;
+ real->region_timestamp = priv->timestamp;
+}
+
+/**
+ * _gspell_region_iter_is_end:
+ * @iter: a #GspellRegionIter.
+ *
+ * Returns: whether @iter is the end iterator.
+ * Since: 3.22
+ */
+gboolean
+_gspell_region_iter_is_end (GspellRegionIter *iter)
+{
+ GspellRegionIterReal *real;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ real = (GspellRegionIterReal *)iter;
+ g_return_val_if_fail (check_iterator (real), FALSE);
+
+ return real->subregions == NULL;
+}
+
+/**
+ * _gspell_region_iter_next:
+ * @iter: a #GspellRegionIter.
+ *
+ * Moves @iter to the next subregion.
+ *
+ * Returns: %TRUE if @iter moved and is dereferenceable, or %FALSE if @iter has
+ * been set to the end iterator.
+ * Since: 3.22
+ */
+gboolean
+_gspell_region_iter_next (GspellRegionIter *iter)
+{
+ GspellRegionIterReal *real;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ real = (GspellRegionIterReal *)iter;
+ g_return_val_if_fail (check_iterator (real), FALSE);
+
+ if (real->subregions != NULL)
+ {
+ real->subregions = real->subregions->next;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * _gspell_region_iter_get_subregion:
+ * @iter: a #GspellRegionIter.
+ * @start: (out) (optional): iterator to initialize with the subregion start, or %NULL.
+ * @end: (out) (optional): iterator to initialize with the subregion end, or %NULL.
+ *
+ * Gets the subregion at this iterator.
+ *
+ * Returns: %TRUE if @start and @end have been set successfully (if non-%NULL),
+ * or %FALSE if @iter is the end iterator or if the region is empty.
+ * Since: 3.22
+ */
+gboolean
+_gspell_region_iter_get_subregion (GspellRegionIter *iter,
+ GtkTextIter *start,
+ GtkTextIter *end)
+{
+ GspellRegionIterReal *real;
+ GspellRegionPrivate *priv;
+ Subregion *sr;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ real = (GspellRegionIterReal *)iter;
+ g_return_val_if_fail (check_iterator (real), FALSE);
+
+ if (real->subregions == NULL)
+ {
+ return FALSE;
+ }
+
+ priv = _gspell_region_get_instance_private (real->region);
+
+ if (priv->buffer == NULL)
+ {
+ return FALSE;
+ }
+
+ sr = real->subregions->data;
+ g_return_val_if_fail (sr != NULL, FALSE);
+
+ if (start != NULL)
+ {
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, start, sr->start);
+ }
+
+ if (end != NULL)
+ {
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, end, sr->end);
+ }
+
+ return TRUE;
+}
+
+/**
+ * _gspell_region_to_string:
+ * @region: a #GspellRegion.
+ *
+ * Gets a string represention of @region, for debugging purposes.
+ *
+ * The returned string contains the character offsets of the subregions. It
+ * doesn't include a newline character at the end of the string.
+ *
+ * Returns: (transfer full) (nullable): a string represention of @region. Free
+ * with g_free() when no longer needed.
+ * Since: 3.22
+ */
+gchar *
+_gspell_region_to_string (GspellRegion *region)
+{
+ GspellRegionPrivate *priv;
+ GString *string;
+ GList *l;
+
+ g_return_val_if_fail (GSPELL_IS_REGION (region), NULL);
+
+ priv = _gspell_region_get_instance_private (region);
+
+ if (priv->buffer == NULL)
+ {
+ return NULL;
+ }
+
+ string = g_string_new ("Subregions:");
+
+ for (l = priv->subregions; l != NULL; l = l->next)
+ {
+ Subregion *sr = l->data;
+ GtkTextIter start;
+ GtkTextIter end;
+
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &start, sr->start);
+ gtk_text_buffer_get_iter_at_mark (priv->buffer, &end, sr->end);
+
+ g_string_append_printf (string,
+ " %d-%d",
+ gtk_text_iter_get_offset (&start),
+ gtk_text_iter_get_offset (&end));
+ }
+
+ return g_string_free (string, FALSE);
+}
diff --git a/gspell/gspellregion.h b/gspell/gspellregion.h
new file mode 100644
index 0000000..2ca347e
--- /dev/null
+++ b/gspell/gspellregion.h
@@ -0,0 +1,113 @@
+/* Do not edit: this file is generated from
https://git.gnome.org/browse/gtksourceview/plain/gtksourceview/gtksourceregion.h */
+
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * gspellregion.h - GtkTextMark-based region utility
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2002 Gustavo Giráldez <gustavo giraldez gmx net>
+ * Copyright (C) 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __GSPELL_REGION_H__
+#define __GSPELL_REGION_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GSPELL_TYPE_REGION (_gspell_region_get_type ())
+
+G_GNUC_INTERNAL
+G_DECLARE_DERIVABLE_TYPE (GspellRegion, _gspell_region,
+ GSPELL, REGION,
+ GObject)
+
+struct _GspellRegionClass
+{
+ GObjectClass parent_class;
+
+ /* Padding for future expansion */
+ gpointer padding[8];
+};
+
+/**
+ * GspellRegionIter:
+ *
+ * #GspellRegionIter is an opaque datatype; ignore all its fields.
+ * Initialize the iter with _gspell_region_get_start_region_iter().
+ *
+ * Since: 3.22
+ */
+typedef struct _GspellRegionIter GspellRegionIter;
+struct _GspellRegionIter
+{
+ /*< private >*/
+ gpointer dummy1;
+ guint32 dummy2;
+ gpointer dummy3;
+};
+
+G_GNUC_INTERNAL
+GspellRegion * _gspell_region_new (GtkTextBuffer *buffer);
+
+G_GNUC_INTERNAL
+GtkTextBuffer * _gspell_region_get_buffer (GspellRegion *region);
+
+G_GNUC_INTERNAL
+void _gspell_region_add (GspellRegion *region,
+ const GtkTextIter *_start,
+ const GtkTextIter *_end);
+
+G_GNUC_INTERNAL
+void _gspell_region_subtract (GspellRegion *region,
+ const GtkTextIter *_start,
+ const GtkTextIter *_end);
+
+G_GNUC_INTERNAL
+GspellRegion * _gspell_region_intersect (GspellRegion *region,
+ const GtkTextIter *_start,
+ const GtkTextIter *_end);
+
+G_GNUC_INTERNAL
+gboolean _gspell_region_is_empty (GspellRegion *region);
+
+G_GNUC_INTERNAL
+gboolean _gspell_region_get_bounds (GspellRegion *region,
+ GtkTextIter *start,
+ GtkTextIter *end);
+
+G_GNUC_INTERNAL
+void _gspell_region_get_start_region_iter (GspellRegion *region,
+ GspellRegionIter *iter);
+
+G_GNUC_INTERNAL
+gboolean _gspell_region_iter_is_end (GspellRegionIter *iter);
+
+G_GNUC_INTERNAL
+gboolean _gspell_region_iter_next (GspellRegionIter *iter);
+
+G_GNUC_INTERNAL
+gboolean _gspell_region_iter_get_subregion (GspellRegionIter *iter,
+ GtkTextIter *start,
+ GtkTextIter *end);
+
+G_GNUC_INTERNAL
+gchar * _gspell_region_to_string (GspellRegion *region);
+
+G_END_DECLS
+
+#endif /* __GSPELL_REGION_H__ */
diff --git a/gspell/update-sourceregion.sh b/gspell/update-sourceregion.sh
new file mode 100755
index 0000000..41bc9ea
--- /dev/null
+++ b/gspell/update-sourceregion.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+# Fetch the GtkSourceRegion utility files from GtkSourceView
+# but rename the symbols to avoid possible symbol clashes
+# if both GtkSourceView and gspell are used in the same application
+# with different versons of GtkSourceRegion.
+# G_GNUC_INTERNAL should protect us, but it could be a no-op with
+# some compilers.
+
+GSVURL=https://git.gnome.org/browse/gtksourceview/plain/gtksourceview
+
+update_file () {
+ _source="${GSVURL}/$1"
+ _dest="$2"
+
+ echo "/* Do not edit: this file is generated from ${_source} */" > "${_dest}"
+ echo >> "${_dest}"
+
+ # gtksourceversion.h is only needed for GTK_SOURCE_AVAILABLE* that we are
+ # removing. We may need to define our own INTERNAL macro for MSVC support.
+ curl "${_source}" | sed \
+ -e '/gtksourceversion.h/d' \
+ -e 's/GTK_SOURCE_AVAILABLE_IN_3_22/G_GNUC_INTERNAL/g' \
+ -e 's/gtksourceregion/gspellregion/g' \
+ -e 's/GTK_SOURCE/GSPELL/g' \
+ -e 's/GtkSourceRegion/GspellRegion/g' \
+ -e 's/gtk_source_region/_gspell_region/g' >> "${_dest}"
+}
+
+update_file "gtksourceregion.c" "gspellregion.c"
+update_file "gtksourceregion.h" "gspellregion.h"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]