[gtksourceview/wip/chergert/snippets] wip on new chunk design
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/chergert/snippets] wip on new chunk design
- Date: Thu, 23 Jan 2020 01:30:46 +0000 (UTC)
commit 430b3f3c3e60e2349ee5e2b01f3ef80f87888546
Author: Christian Hergert <chergert redhat com>
Date: Wed Jan 22 17:30:44 2020 -0800
wip on new chunk design
gtksourceview/gtksourcesnippet.c | 483 ++++++++++----------------
gtksourceview/gtksourcesnippetchunk-private.h | 6 +
gtksourceview/gtksourcesnippetchunk.c | 81 +++++
3 files changed, 264 insertions(+), 306 deletions(-)
---
diff --git a/gtksourceview/gtksourcesnippet.c b/gtksourceview/gtksourcesnippet.c
index 1885537c..ae190faa 100644
--- a/gtksourceview/gtksourcesnippet.c
+++ b/gtksourceview/gtksourcesnippet.c
@@ -33,7 +33,7 @@ struct _GtkSourceSnippet
GtkSourceSnippetContext *context;
GtkTextBuffer *buffer;
GPtrArray *chunks;
- GArray *runs;
+ GtkSourceSnippetChunk *current_chunk;
GtkTextMark *mark_begin;
GtkTextMark *mark_end;
@@ -43,7 +43,6 @@ struct _GtkSourceSnippet
gint focus_position;
gint max_focus_position;
- gint current_chunk;
guint inserted : 1;
};
@@ -64,6 +63,39 @@ enum {
static GParamSpec *properties [N_PROPS];
+static GtkSourceSnippetChunk *
+get_chunk_at_iter (GtkSourceSnippet *self,
+ GtkTextIter *iter)
+{
+ GtkSourceSnippetChunk *chunk;
+
+ g_assert (GTK_SOURCE_IS_SNIPPET (self));
+ g_assert (iter != NULL);
+
+ /* If our current chunk (as known from focus tracking) contains
+ * the iter that is requested, then we will use that. Otherwise,
+ * we'll scan the chunks (starting from 0) to see which one matches
+ * the requested location.
+ */
+ if (self->current_chunk != NULL &&
+ _gtk_source_snippet_chunk_contains (self->current_chunk, iter))
+ {
+ return self->current_chunk;
+ }
+
+ for (guint i = 0; i < self->chunks->len; i++)
+ {
+ chunk = g_ptr_array_index (self->chunks, i);
+
+ if (_gtk_source_snippet_chunk_contains (chunk, iter))
+ {
+ return chunk;
+ }
+ }
+
+ g_return_val_if_reached (NULL);
+}
+
/**
* gtk_source_snippet_new:
* @trigger: (nullable): the trigger word
@@ -316,69 +348,16 @@ gtk_source_snippet_set_description (GtkSourceSnippet *self,
}
}
-static gint
-gtk_source_snippet_get_offset (GtkSourceSnippet *self,
- GtkTextIter *iter)
-{
- GtkTextIter begin;
- gint ret;
-
- g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET (self), 0);
- g_return_val_if_fail (iter, 0);
-
- gtk_text_buffer_get_iter_at_mark (self->buffer, &begin, self->mark_begin);
- ret = gtk_text_iter_get_offset (iter) - gtk_text_iter_get_offset (&begin);
- ret = MAX (0, ret);
-
- return ret;
-}
-
-static gint
-gtk_source_snippet_get_index (GtkSourceSnippet *self,
- GtkTextIter *iter)
-{
- gint offset;
-
- g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET (self), 0);
- g_return_val_if_fail (iter, 0);
-
- offset = gtk_source_snippet_get_offset (self, iter);
-
- for (guint i = 0; i < self->runs->len; i++)
- {
- gint run = g_array_index (self->runs, gint, i);
-
- offset -= run;
-
- if (offset <= 0)
- {
- /*
- * NOTE:
- *
- * This is the central part of the hack by using offsets
- * instead of textmarks (which gives us lots of gravity grief).
- * We guess which snippet it is based on the current chunk.
- */
- if (self->current_chunk > -1 && (i + 1) == (guint)self->current_chunk)
- return i + 1;
- else
- return i;
- }
- }
-
- return (self->runs->len - 1);
-}
-
static gboolean
-gtk_source_snippet_within_bounds (GtkSourceSnippet *self,
- GtkTextIter *iter)
+gtk_source_snippet_contains (GtkSourceSnippet *self,
+ GtkTextIter *iter)
{
GtkTextIter begin;
GtkTextIter end;
gboolean ret;
- g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET (self), FALSE);
- g_return_val_if_fail (iter, FALSE);
+ g_assert (GTK_SOURCE_IS_SNIPPET (self));
+ g_assert (iter != NULL);
gtk_text_buffer_get_iter_at_mark (self->buffer, &begin, self->mark_begin);
gtk_text_buffer_get_iter_at_mark (self->buffer, &end, self->mark_end);
@@ -400,93 +379,47 @@ _gtk_source_snippet_insert_set (GtkSourceSnippet *self,
gtk_text_buffer_get_iter_at_mark (self->buffer, &iter, mark);
- if (!gtk_source_snippet_within_bounds (self, &iter))
+ if (!gtk_source_snippet_contains (self, &iter))
{
+ self->current_chunk = NULL;
return FALSE;
}
-
- self->current_chunk = gtk_source_snippet_get_index (self, &iter);
-
- return TRUE;
-}
-
-static void
-gtk_source_snippet_get_nth_chunk_range (GtkSourceSnippet *self,
- gint nth,
- GtkTextIter *begin,
- GtkTextIter *end)
-{
- gint run;
-
- g_return_if_fail (GTK_SOURCE_IS_SNIPPET (self));
- g_return_if_fail (nth >= 0);
- g_return_if_fail (begin);
- g_return_if_fail (end);
-
- gtk_text_buffer_get_iter_at_mark (self->buffer, begin, self->mark_begin);
-
- for (guint i = 0; i < nth; i++)
+ else
{
- run = g_array_index (self->runs, gint, i);
- gtk_text_iter_forward_chars (begin, run);
+ self->current_chunk = get_chunk_at_iter (self, &iter);
+ return TRUE;
}
-
- gtk_text_iter_assign (end, begin);
- run = g_array_index (self->runs, gint, nth);
- gtk_text_iter_forward_chars (end, run);
}
static void
-gtk_source_snippet_get_chunk_range (GtkSourceSnippet *self,
- GtkSourceSnippetChunk *chunk,
- GtkTextIter *begin,
- GtkTextIter *end)
+gtk_source_snippet_select_chunk (GtkSourceSnippet *self,
+ GtkSourceSnippetChunk *chunk)
{
+ GtkTextIter begin;
+ GtkTextIter end;
g_return_if_fail (GTK_SOURCE_IS_SNIPPET (self));
g_return_if_fail (GTK_SOURCE_IS_SNIPPET_CHUNK (chunk));
- for (guint i = 0; i < self->chunks->len; i++)
+ if (self->current_chunk == chunk)
{
- GtkSourceSnippetChunk *item;
-
- item = g_ptr_array_index (self->chunks, i);
-
- if (item == chunk)
- {
- gtk_source_snippet_get_nth_chunk_range (self, i, begin, end);
- return;
- }
+ return;
}
- g_warn_if_reached ();
-}
-
-static void
-gtk_source_snippet_select_chunk (GtkSourceSnippet *self,
- gint nth)
-{
- GtkTextIter begin;
- GtkTextIter end;
-
- g_return_if_fail (GTK_SOURCE_IS_SNIPPET (self));
- g_return_if_fail (nth >= 0);
- g_return_if_fail ((guint)nth < self->runs->len);
-
- gtk_source_snippet_get_nth_chunk_range (self, nth, &begin, &end);
+ _gtk_source_snippet_chunk_get_bounds (chunk, &begin, &end);
gtk_text_iter_order (&begin, &end);
- g_debug ("Selecting chunk %d with range %d:%d to %d:%d (offset %d+%d)",
- nth,
- gtk_text_iter_get_line (&begin) + 1,
- gtk_text_iter_get_line_offset (&begin) + 1,
- gtk_text_iter_get_line (&end) + 1,
- gtk_text_iter_get_line_offset (&end) + 1,
- gtk_text_iter_get_offset (&begin),
- gtk_text_iter_get_offset (&end) - gtk_text_iter_get_offset (&begin));
+ g_debug ("Selecting chunk with range %d:%d to %d:%d (offset %d+%d)",
+ gtk_text_iter_get_line (&begin) + 1,
+ gtk_text_iter_get_line_offset (&begin) + 1,
+ gtk_text_iter_get_line (&end) + 1,
+ gtk_text_iter_get_line_offset (&end) + 1,
+ gtk_text_iter_get_offset (&begin),
+ gtk_text_iter_get_offset (&end) - gtk_text_iter_get_offset (&begin));
+
+ self->current_chunk = chunk;
gtk_text_buffer_select_range (self->buffer, &begin, &end);
- self->current_chunk = nth;
#ifndef G_DISABLE_ASSERT
{
@@ -521,7 +454,7 @@ _gtk_source_snippet_move_next (GtkSourceSnippet *self)
if (gtk_source_snippet_chunk_get_focus_position (chunk) == self->focus_position)
{
- gtk_source_snippet_select_chunk (self, i);
+ gtk_source_snippet_select_chunk (self, chunk);
return TRUE;
}
}
@@ -532,16 +465,16 @@ _gtk_source_snippet_move_next (GtkSourceSnippet *self)
if (gtk_source_snippet_chunk_get_focus_position (chunk) == 0)
{
- gtk_source_snippet_select_chunk (self, i);
+ gtk_source_snippet_select_chunk (self, chunk);
return FALSE;
}
}
g_debug ("No more tab stops, moving to end of snippet");
+ self->current_chunk = NULL;
gtk_text_buffer_get_iter_at_mark (self->buffer, &iter, self->mark_end);
gtk_text_buffer_select_range (self->buffer, &iter, &iter);
- self->current_chunk = self->chunks->len - 1;
return FALSE;
}
@@ -574,7 +507,7 @@ _gtk_source_snippet_move_previous (GtkSourceSnippet *self)
if (gtk_source_snippet_chunk_get_focus_position (chunk) == self->focus_position)
{
- gtk_source_snippet_select_chunk (self, i);
+ gtk_source_snippet_select_chunk (self, chunk);
return TRUE;
}
}
@@ -672,7 +605,7 @@ gtk_source_snippet_update_tags (GtkSourceSnippet *self)
GtkTextIter begin;
GtkTextIter end;
- gtk_source_snippet_get_chunk_range (self, chunk, &begin, &end);
+ _gtk_source_snippet_chunk_get_bounds (chunk, &begin, &end);
gtk_text_buffer_apply_tag (buffer, tag, &begin, &end);
}
}
@@ -723,10 +656,6 @@ _gtk_source_snippet_begin (GtkSourceSnippet *self,
if (text != NULL)
{
- gint len;
-
- len = g_utf8_strlen (text, -1);
- g_array_append_val (self->runs, len);
gtk_text_buffer_insert (buffer, iter, text, -1);
}
@@ -774,69 +703,40 @@ gtk_source_snippet_add_chunk (GtkSourceSnippet *self,
self->max_focus_position = MAX (self->max_focus_position, focus_position);
}
-static gchar *
-gtk_source_snippet_get_nth_text (GtkSourceSnippet *self,
- gint nth)
-{
- GtkTextIter iter;
- GtkTextIter end;
-
- g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET (self), NULL);
- g_return_val_if_fail (nth >= 0, NULL);
-
- gtk_text_buffer_get_iter_at_mark (self->buffer, &iter, self->mark_begin);
-
- for (gint i = 0; i < nth; i++)
- {
- gtk_text_iter_forward_chars (&iter, g_array_index (self->runs, gint, i));
- }
-
- gtk_text_iter_assign (&end, &iter);
- gtk_text_iter_forward_chars (&end, g_array_index (self->runs, gint, nth));
-
- return gtk_text_buffer_get_text (self->buffer, &iter, &end, TRUE);
-}
-
static void
-gtk_source_snippet_replace_chunk_text (GtkSourceSnippet *self,
- gint nth,
- const gchar *text)
+gtk_source_snippet_replace_chunk_text (GtkSourceSnippet *self,
+ GtkSourceSnippetChunk *chunk,
+ const gchar *text)
{
GtkTextIter begin;
GtkTextIter end;
- gint diff = 0;
+ gint diff;
- g_return_if_fail (GTK_SOURCE_IS_SNIPPET (self));
- g_return_if_fail (nth >= 0);
- g_return_if_fail (text);
+ g_assert (GTK_SOURCE_IS_SNIPPET (self));
+ g_assert (GTK_SOURCE_IS_SNIPPET_CHUNK (chunk));
/*
* This replaces the text for the snippet. We insert new text before
* we delete the old text to ensure things are more stable as we
* manipulate the runs. Avoiding zero-length runs, even temporarily
- * can be helpful.
+ * can be helpful to reduce chances for textmark gravity overlapping
+ * other marks.
*/
- gtk_source_snippet_get_nth_chunk_range (self, nth, &begin, &end);
+ _gtk_source_snippet_chunk_get_bounds (chunk, &begin, &end);
- if (!gtk_text_iter_equal (&begin, &end))
+ gtk_text_iter_order (&begin, &end);
+ diff = gtk_text_iter_get_offset (&end) - gtk_text_iter_get_offset (&begin);
+
+ if (text != NULL)
{
- gtk_text_iter_order (&begin, &end);
- diff = gtk_text_iter_get_offset (&end) - gtk_text_iter_get_offset (&begin);
+ gtk_text_buffer_insert (self->buffer, &begin, text, -1);
}
- g_array_index (self->runs, gint, nth) += g_utf8_strlen (text, -1);
- gtk_text_buffer_insert (self->buffer, &begin, text, -1);
-
- /* At this point, begin should be updated to the end of where we inserted
- * our new text. If `diff` is non-zero, then we need to remove those
- * characters immediately after `begin`.
- */
- if (diff != 0)
+ if (diff > 0)
{
end = begin;
gtk_text_iter_forward_chars (&end, diff);
- g_array_index (self->runs, gint, nth) -= diff;
gtk_text_buffer_delete (self->buffer, &begin, &end);
}
}
@@ -849,21 +749,95 @@ gtk_source_snippet_rewrite_updated_chunks (GtkSourceSnippet *self)
for (guint i = 0; i < self->chunks->len; i++)
{
GtkSourceSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
+ GtkTextIter begin;
+ GtkTextIter end;
const gchar *text;
gchar *real_text;
+ _gtk_source_snippet_chunk_get_bounds (chunk, &begin, &end);
+
text = gtk_source_snippet_chunk_get_text (chunk);
- real_text = gtk_source_snippet_get_nth_text (self, i);
+ real_text = gtk_text_iter_get_slice (&begin, &end);
if (g_strcmp0 (text, real_text) != 0)
{
- gtk_source_snippet_replace_chunk_text (self, i, text);
+ gtk_source_snippet_replace_chunk_text (self, chunk, text);
}
g_free (real_text);
}
}
+static void
+gtk_source_snippet_update_marks (GtkSourceSnippet *snippet)
+{
+ GtkTextBuffer *buffer;
+ GtkTextMark *last_end = NULL;
+
+ g_assert (GTK_SOURCE_IS_SNIPPET (snippet));
+
+ buffer = GTK_TEXT_BUFFER (snippet->buffer);
+
+ for (guint i = 0; i < snippet->chunks->len; i++)
+ {
+ GtkSourceSnippetChunk *chunk;
+ GtkTextMark *begin_mark;
+ GtkTextMark *end_mark;
+ GtkTextIter begin;
+ GtkTextIter end;
+ GtkTextIter last;
+
+ chunk = g_ptr_array_index (snippet->chunks, i);
+ begin_mark = _gtk_source_snippet_chunk_get_begin_mark (chunk);
+ end_mark = _gtk_source_snippet_chunk_get_end_mark (chunk);
+
+ if (last_end == NULL)
+ {
+ last_end = end_mark;
+ continue;
+ }
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &begin, begin_mark);
+ gtk_text_buffer_get_iter_at_mark (buffer, &last, last_end);
+
+ /* If the begin of this chunk has come before the end
+ * of the last chunk, then that mights we are empty and
+ * the right gravity of the begin mark was greedily taken
+ * when inserting into a previous mark. This can happen
+ * when you (often intermittently) have empty chunks.
+ *
+ * For example, imagine 4 empty chunks:
+ *
+ * [][][][]
+ *
+ * Except in reality to GtkTextBuffer, that's more like:
+ *
+ * [[[[]]]]
+ *
+ * When the user types 't' into the first chunk we'll end up
+ * with something like this:
+ *
+ * [[[[t]]]]
+ *
+ * and we need to modify things to look like this:
+ *
+ * [t][[[]]]
+ */
+
+ if (gtk_text_iter_compare (&last, &begin) > 0)
+ {
+ gtk_text_buffer_move_mark (buffer, begin_mark, &last);
+ }
+
+ if (gtk_text_iter_compare (&begin, &end) > 0)
+ {
+ gtk_text_buffer_move_mark (buffer, end_mark, &begin);
+ }
+
+ last_end = end_mark;
+ }
+}
+
void
_gtk_source_snippet_before_insert_text (GtkSourceSnippet *self,
GtkTextBuffer *buffer,
@@ -871,24 +845,11 @@ _gtk_source_snippet_before_insert_text (GtkSourceSnippet *self,
const gchar *text,
gint len)
{
- gint utf8_len;
- gint n;
-
g_return_if_fail (GTK_SOURCE_IS_SNIPPET (self));
- g_return_if_fail (self->current_chunk >= 0);
+ g_return_if_fail (self->current_chunk != NULL);
g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
- g_return_if_fail (iter);
+ g_return_if_fail (iter != NULL);
- n = gtk_source_snippet_get_index (self, iter);
- utf8_len = g_utf8_strlen (text, len);
- g_array_index (self->runs, gint, n) += utf8_len;
-
-#if 0
- g_print ("I: ");
- for (n = 0; n < self->runs->len; n++)
- g_print ("%d ", g_array_index (self->runs, gint, n));
- g_print ("\n");
-#endif
}
void
@@ -899,31 +860,30 @@ _gtk_source_snippet_after_insert_text (GtkSourceSnippet *self,
gint len)
{
GtkSourceSnippetChunk *chunk;
- GtkTextMark *here;
- gchar *new_text;
- gint n;
+ GtkTextMark *end_mark;
+ GtkTextIter end;
g_return_if_fail (GTK_SOURCE_IS_SNIPPET (self));
- g_return_if_fail (self->current_chunk >= 0);
+ g_return_if_fail (self->current_chunk != NULL);
g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
- g_return_if_fail (iter);
+ g_return_if_fail (iter != NULL);
- n = gtk_source_snippet_get_index (self, iter);
- chunk = g_ptr_array_index (self->chunks, n);
- new_text = gtk_source_snippet_get_nth_text (self, n);
- gtk_source_snippet_chunk_set_text (chunk, new_text);
- gtk_source_snippet_chunk_set_text_set (chunk, TRUE);
- g_free (new_text);
+ chunk = get_chunk_at_iter (self, iter);
- here = gtk_text_buffer_create_mark (buffer, NULL, iter, TRUE);
+ end_mark = _gtk_source_snippet_chunk_get_end_mark (chunk);
+ gtk_text_buffer_get_iter_at_mark (buffer, &end, end_mark);
+ if (gtk_text_iter_compare (iter, &end) > 0)
+ {
+ gtk_text_buffer_move_mark (buffer, end_mark, iter);
+ }
+
+ _gtk_source_snippet_chunk_save_text (chunk);
+
+ gtk_source_snippet_update_marks (self);
gtk_source_snippet_update_context (self);
gtk_source_snippet_update_context (self);
gtk_source_snippet_rewrite_updated_chunks (self);
-
- gtk_text_buffer_get_iter_at_mark (buffer, iter, here);
- gtk_text_buffer_delete_mark (buffer, here);
-
gtk_source_snippet_update_tags (self);
}
@@ -933,76 +893,12 @@ _gtk_source_snippet_before_delete_range (GtkSourceSnippet *self,
GtkTextIter *begin,
GtkTextIter *end)
{
- gint *run;
- gint len;
- gint n;
- gint lower_bound = -1;
- gint upper_bound = -1;
g_return_if_fail (GTK_SOURCE_IS_SNIPPET (self));
g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
- g_return_if_fail (begin);
- g_return_if_fail (end);
-
- len = gtk_text_iter_get_offset (end) - gtk_text_iter_get_offset (begin);
- n = gtk_source_snippet_get_index (self, begin);
-
- if (n < 0)
- {
- return;
- }
-
- self->current_chunk = n;
-
- while (len != 0 && (guint)n < self->runs->len)
- {
- if (lower_bound == -1 || n < lower_bound)
- {
- lower_bound = n;
- }
-
- if (n > upper_bound)
- {
- upper_bound = n;
- }
-
- run = &g_array_index (self->runs, gint, n);
-
- if (len > *run)
- {
- len -= *run;
- *run = 0;
- n++;
- continue;
- }
-
- *run -= len;
-
- break;
- }
-
- if (lower_bound == -1 || upper_bound == -1)
- {
- return;
- }
+ g_return_if_fail (begin != NULL);
+ g_return_if_fail (end != NULL);
- for (gint i = lower_bound; i <= upper_bound; i++)
- {
- GtkSourceSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
- gchar *new_text;
-
- new_text = gtk_source_snippet_get_nth_text (self, i);
- gtk_source_snippet_chunk_set_text (chunk, new_text);
- gtk_source_snippet_chunk_set_text_set (chunk, TRUE);
- g_free (new_text);
- }
-
-#if 0
- g_print ("D: ");
- for (n = 0; n < self->runs->len; n++)
- g_print ("%d ", g_array_index (self->runs, gint, n));
- g_print ("\n");
-#endif
}
void
@@ -1011,23 +907,14 @@ _gtk_source_snippet_after_delete_range (GtkSourceSnippet *self,
GtkTextIter *begin,
GtkTextIter *end)
{
- GtkTextMark *here;
-
g_return_if_fail (GTK_SOURCE_IS_SNIPPET (self));
g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
g_return_if_fail (begin);
g_return_if_fail (end);
- here = gtk_text_buffer_create_mark (buffer, NULL, begin, TRUE);
-
gtk_source_snippet_update_context (self);
gtk_source_snippet_update_context (self);
gtk_source_snippet_rewrite_updated_chunks (self);
-
- gtk_text_buffer_get_iter_at_mark (buffer, begin, here);
- gtk_text_buffer_get_iter_at_mark (buffer, end, here);
- gtk_text_buffer_delete_mark (buffer, here);
-
gtk_source_snippet_update_tags (self);
}
@@ -1095,7 +982,6 @@ gtk_source_snippet_dispose (GObject *object)
g_clear_object (&self->mark_end);
}
- g_clear_pointer (&self->runs, g_array_unref);
g_clear_pointer (&self->chunks, g_ptr_array_unref);
g_clear_object (&self->buffer);
@@ -1267,7 +1153,6 @@ gtk_source_snippet_init (GtkSourceSnippet *self)
{
self->max_focus_position = -1;
self->chunks = g_ptr_array_new_with_free_func (g_object_unref);
- self->runs = g_array_new (FALSE, FALSE, sizeof (gint));
}
gchar *
@@ -1293,27 +1178,13 @@ void
_gtk_source_snippet_replace_current_chunk_text (GtkSourceSnippet *self,
const gchar *new_text)
{
- GtkSourceSnippetChunk *chunk;
- gint utf8_len;
-
g_return_if_fail (GTK_SOURCE_IS_SNIPPET (self));
- g_return_if_fail (self->chunks != NULL);
- if (self->current_chunk < 0 || self->current_chunk >= self->chunks->len)
+ if (self->current_chunk != NULL)
{
- return;
+ gtk_source_snippet_chunk_set_text (self->current_chunk, new_text);
+ gtk_source_snippet_chunk_set_text_set (self->current_chunk, TRUE);
}
-
- chunk = g_ptr_array_index (self->chunks, self->current_chunk);
-
- gtk_source_snippet_chunk_set_text (chunk, new_text);
- gtk_source_snippet_chunk_set_text_set (chunk, TRUE);
-
- g_assert (self->current_chunk >= 0);
- g_assert (self->current_chunk < self->runs->len);
-
- utf8_len = g_utf8_strlen (new_text, -1);
- g_array_index (self->runs, gint, self->current_chunk) = utf8_len;
}
void
diff --git a/gtksourceview/gtksourcesnippetchunk-private.h b/gtksourceview/gtksourcesnippetchunk-private.h
index f5f9aa29..904302c0 100644
--- a/gtksourceview/gtksourcesnippetchunk-private.h
+++ b/gtksourceview/gtksourcesnippetchunk-private.h
@@ -29,5 +29,11 @@ void _gtk_source_snippet_chunk_set_begin_mark (GtkSourceSnippetChunk *ch
GtkTextMark *_gtk_source_snippet_chunk_get_end_mark (GtkSourceSnippetChunk *chunk);
void _gtk_source_snippet_chunk_set_end_mark (GtkSourceSnippetChunk *chunk,
GtkTextMark *end_mark);
+void _gtk_source_snippet_chunk_save_text (GtkSourceSnippetChunk *chunk);
+gboolean _gtk_source_snippet_chunk_contains (GtkSourceSnippetChunk *chunk,
+ const GtkTextIter *iter);
+void _gtk_source_snippet_chunk_get_bounds (GtkSourceSnippetChunk *chunk,
+ GtkTextIter *begin,
+ GtkTextIter *end);
G_END_DECLS
diff --git a/gtksourceview/gtksourcesnippetchunk.c b/gtksourceview/gtksourcesnippetchunk.c
index 96f0bfdd..79f45208 100644
--- a/gtksourceview/gtksourcesnippetchunk.c
+++ b/gtksourceview/gtksourcesnippetchunk.c
@@ -257,11 +257,25 @@ gtk_source_snippet_chunk_set_text_set (GtkSourceSnippetChunk *chunk,
}
}
+static void
+delete_and_unref_mark (GtkTextMark *mark)
+{
+ g_assert (!mark || GTK_IS_TEXT_MARK (mark));
+
+ if (mark != NULL)
+ {
+ gtk_text_buffer_delete_mark (gtk_text_mark_get_buffer (mark), mark);
+ g_object_unref (mark);
+ }
+}
+
static void
gtk_source_snippet_chunk_finalize (GObject *object)
{
GtkSourceSnippetChunk *chunk = (GtkSourceSnippetChunk *)object;
+ g_clear_pointer (&chunk->begin_mark, delete_and_unref_mark);
+ g_clear_pointer (&chunk->end_mark, delete_and_unref_mark);
g_clear_pointer (&chunk->spec, g_free);
g_clear_pointer (&chunk->text, g_free);
g_clear_object (&chunk->context);
@@ -440,3 +454,70 @@ _gtk_source_snippet_chunk_set_end_mark (GtkSourceSnippetChunk *chunk,
g_set_object (&chunk->end_mark, end_mark);
}
+
+void
+_gtk_source_snippet_chunk_get_bounds (GtkSourceSnippetChunk *chunk,
+ GtkTextIter *begin,
+ GtkTextIter *end)
+{
+ GtkTextBuffer *buffer;
+
+ g_return_if_fail (GTK_SOURCE_IS_SNIPPET_CHUNK (chunk));
+ g_return_if_fail (begin != NULL);
+ g_return_if_fail (end != NULL);
+
+ buffer = gtk_text_mark_get_buffer (chunk->begin_mark);
+
+ gtk_text_buffer_get_iter_at_mark (buffer, begin, chunk->begin_mark);
+ gtk_text_buffer_get_iter_at_mark (buffer, end, chunk->end_mark);
+}
+
+void
+_gtk_source_snippet_chunk_save_text (GtkSourceSnippetChunk *chunk)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter begin;
+ GtkTextIter end;
+
+ g_return_if_fail (GTK_SOURCE_IS_SNIPPET_CHUNK (chunk));
+
+ buffer = gtk_text_mark_get_buffer (chunk->begin_mark);
+
+ gtk_text_buffer_get_iter_at_mark (buffer, &begin, chunk->begin_mark);
+ gtk_text_buffer_get_iter_at_mark (buffer, &end, chunk->end_mark);
+
+ g_free (chunk->text);
+ chunk->text = gtk_text_iter_get_slice (&begin, &end);
+ g_object_notify_by_pspec (G_OBJECT (chunk),
+ properties [PROP_TEXT]);
+
+ if (chunk->text_set != TRUE)
+ {
+ chunk->text_set = TRUE;
+ g_object_notify_by_pspec (G_OBJECT (chunk),
+ properties [PROP_TEXT_SET]);
+ }
+}
+
+gboolean
+_gtk_source_snippet_chunk_contains (GtkSourceSnippetChunk *chunk,
+ const GtkTextIter *iter)
+{
+ GtkTextIter begin;
+ GtkTextIter end;
+
+ g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET_CHUNK (chunk), FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ _gtk_source_snippet_chunk_get_bounds (chunk, &begin, &end);
+
+#if 0
+ g_print ("Is %d between %d and %d\n",
+ gtk_text_iter_get_offset (iter),
+ gtk_text_iter_get_offset (&begin),
+ gtk_text_iter_get_offset (&end));
+#endif
+
+ return gtk_text_iter_compare (iter, &begin) >= 0 &&
+ gtk_text_iter_compare (iter, &end) <= 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]