summaryrefslogtreecommitdiff
path: root/gtk/gtktextbufferserialize.c
diff options
context:
space:
mode:
authorMichael Natterer <mitch@imendio.com>2006-08-28 16:14:42 +0000
committerMichael Natterer <mitch@src.gnome.org>2006-08-28 16:14:42 +0000
commit0fa6144940197ff150e232a53c2da515296e12b0 (patch)
treeda6f63e9be0c6925e3515d3f1c0e364422ee7c39 /gtk/gtktextbufferserialize.c
parent21ac0b0b4045ebedfcf1c6a8dc527a3f5d20c372 (diff)
downloadgtk+-0fa6144940197ff150e232a53c2da515296e12b0.tar.gz
don't write out </apply_tag> for tags that have already been closed by the
2006-08-28 Michael Natterer <mitch@imendio.com> * gtk/gtktextbufferserialize.c (serialize_text): don't write out </apply_tag> for tags that have already been closed by the logic which turns overlapping spans into XML-able trees. Fixes broken XML when there are overlapping tags in the buffer. Also free two leaked GLists and did some cleanup. * tests/Makefile.am * tests/testrichtext.c: new test which creates randomly tagged GtkTextBuffers and serializes/deserializes them.
Diffstat (limited to 'gtk/gtktextbufferserialize.c')
-rw-r--r--gtk/gtktextbufferserialize.c51
1 files changed, 28 insertions, 23 deletions
diff --git a/gtk/gtktextbufferserialize.c b/gtk/gtktextbufferserialize.c
index 66eb18d63e..cacf6c61d1 100644
--- a/gtk/gtktextbufferserialize.c
+++ b/gtk/gtktextbufferserialize.c
@@ -434,14 +434,13 @@ serialize_text (GtkTextBuffer *buffer,
{
GtkTextIter iter, old_iter;
GSList *tag_list, *new_tag_list;
- GQueue *active_tags;
- int i;
+ GSList *active_tags;
g_string_append (context->text_str, "<text>");
iter = context->start;
tag_list = NULL;
- active_tags = g_queue_new ();
+ active_tags = NULL;
do
{
@@ -453,29 +452,33 @@ serialize_text (GtkTextBuffer *buffer,
find_list_delta (tag_list, new_tag_list, &added, &removed);
/* Handle removed tags */
- tmp = removed;
- while (tmp)
+ for (tmp = removed; tmp; tmp = tmp->next)
{
GtkTextTag *tag = tmp->data;
- g_string_append (context->text_str, "</apply_tag>");
-
- /* We might need to drop some of the tags and re-add them afterwards */
- while (g_queue_peek_head (active_tags) != tag &&
- !g_queue_is_empty (active_tags))
- {
- added = g_list_prepend (added, g_queue_pop_head (active_tags));
- g_string_append_printf (context->text_str, "</apply_tag>");
- }
+ /* Only close the tag if we didn't close it before (by using
+ * the stack logic in the while() loop below)
+ */
+ if (g_slist_find (active_tags, tag))
+ {
+ g_string_append (context->text_str, "</apply_tag>");
- g_queue_pop_head (active_tags);
+ /* Drop all tags that were opened after this one (which are
+ * above this on in the stack)
+ */
+ while (active_tags->data != tag)
+ {
+ added = g_list_prepend (added, active_tags->data);
+ active_tags = g_slist_remove (active_tags, active_tags->data);
+ g_string_append_printf (context->text_str, "</apply_tag>");
+ }
- tmp = tmp->next;
+ active_tags = g_slist_remove (active_tags, active_tags->data);
+ }
}
/* Handle added tags */
- tmp = added;
- while (tmp)
+ for (tmp = added; tmp; tmp = tmp->next)
{
GtkTextTag *tag = tmp->data;
gchar *tag_name;
@@ -505,14 +508,16 @@ serialize_text (GtkTextBuffer *buffer,
g_string_append_printf (context->text_str, "<apply_tag id=\"%d\">", GPOINTER_TO_INT (tag_id));
}
- g_queue_push_head (active_tags, tag);
- tmp = tmp->next;
+ active_tags = g_slist_prepend (active_tags, tag);
}
g_slist_free (tag_list);
tag_list = new_tag_list;
+ g_list_free (added);
+ g_list_free (removed);
+
old_iter = iter;
/* Now try to go to either the next tag toggle, or if a pixbuf appears */
@@ -570,10 +575,10 @@ serialize_text (GtkTextBuffer *buffer,
while (!gtk_text_iter_equal (&iter, &context->end));
/* Close any open tags */
- for (i = 0; i < g_queue_get_length (active_tags); i++) {
+ for (tag_list = active_tags; tag_list; tag_list = tag_list->next)
g_string_append (context->text_str, "</apply_tag>");
- }
- g_queue_free (active_tags);
+
+ g_slist_free (active_tags);
g_string_append (context->text_str, "</text>\n</text_view_markup>\n");
}