diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c index 33d9b4a8c4..4be7731d52 100644 --- a/gtk/gtktextbuffer.c +++ b/gtk/gtktextbuffer.c @@ -1837,7 +1837,7 @@ gtk_text_buffer_insert_with_tags (GtkTextBuffer *buffer, g_return_if_fail (iter != NULL); g_return_if_fail (text != NULL); g_return_if_fail (gtk_text_iter_get_buffer (iter) == buffer); - + start_offset = gtk_text_iter_get_offset (iter); gtk_text_buffer_insert (buffer, iter, text, len); @@ -1859,6 +1859,28 @@ gtk_text_buffer_insert_with_tags (GtkTextBuffer *buffer, va_end (args); } +static void +gtk_text_buffer_insert_with_tagsv (GtkTextBuffer *buffer, + GtkTextIter *iter, + const char *text, + int len, + GtkTextTag **tags, + int n_tags) +{ + int start_offset; + GtkTextIter start; + int i; + + start_offset = gtk_text_iter_get_offset (iter); + + gtk_text_buffer_insert (buffer, iter, text, len); + + gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset); + + for (i = 0; i < n_tags; i++) + gtk_text_buffer_apply_tag (buffer, tags[i], &start, iter); +} + /** * gtk_text_buffer_insert_with_tags_by_name: * @buffer: a #GtkTextBuffer @@ -4379,161 +4401,150 @@ _gtk_text_buffer_spew (GtkTextBuffer *buffer) _gtk_text_btree_spew (get_btree (buffer)); } -static GtkTextTag * -get_tag_for_attributes (PangoAttrIterator *iter) +static void +get_tags_for_attributes (PangoAttrIterator *iter, + GtkTextTagTable *table, + GPtrArray *tags) { PangoAttribute *attr; GtkTextTag *tag; + char name[256]; - tag = gtk_text_tag_new (NULL); +#define STRING_ATTR(pango_attr_name, attr_name) \ + attr = pango_attr_iterator_get (iter, pango_attr_name); \ + if (attr) \ + { \ + const char *string = ((PangoAttrString*)attr)->value; \ + g_snprintf (name, 256, "%s=%s", #attr_name, string); \ + tag = gtk_text_tag_table_lookup (table, name); \ + if (!tag) \ + { \ + tag = gtk_text_tag_new (name); \ + g_object_set (tag, #attr_name, string, NULL); \ + gtk_text_tag_table_add (table, tag); \ + g_object_unref (tag); \ + } \ + g_ptr_array_add (tags, tag); \ + } + +#define INT_ATTR(pango_attr_name, attr_name) \ + attr = pango_attr_iterator_get (iter, pango_attr_name); \ + if (attr) \ + { \ + int value = ((PangoAttrInt*)attr)->value; \ + g_snprintf (name, 256, "%s=%d", #attr_name, value); \ + tag = gtk_text_tag_table_lookup (table, name); \ + if (!tag) \ + { \ + tag = gtk_text_tag_new (name); \ + g_object_set (tag, #attr_name, value, NULL); \ + gtk_text_tag_table_add (table, tag); \ + g_object_unref (tag); \ + } \ + g_ptr_array_add (tags, tag); \ + } + +#define FLOAT_ATTR(pango_attr_name, attr_name) \ + attr = pango_attr_iterator_get (iter, pango_attr_name); \ + if (attr) \ + { \ + float value = ((PangoAttrFloat*)attr)->value; \ + g_snprintf (name, 256, "%s=%g", #attr_name, value); \ + tag = gtk_text_tag_table_lookup (table, name); \ + if (!tag) \ + { \ + tag = gtk_text_tag_new (name); \ + g_object_set (tag, #attr_name, value, NULL); \ + gtk_text_tag_table_add (table, tag); \ + g_object_unref (tag); \ + } \ + g_ptr_array_add (tags, tag); \ + } + +#define RGBA_ATTR(pango_attr_name, attr_name) \ + attr = pango_attr_iterator_get (iter, pango_attr_name); \ + if (attr) \ + { \ + PangoColor *color; \ + GdkRGBA rgba; \ + color = &((PangoAttrColor*)attr)->color; \ + rgba.red = color->red / 65535.; \ + rgba.green = color->green / 65535.; \ + rgba.blue = color->blue / 65535.; \ + rgba.alpha = 1.; \ + char *str = gdk_rgba_to_string (&rgba); \ + g_snprintf (name, 256, "%s=%s", #attr_name, str); \ + g_free (str); \ + tag = gtk_text_tag_table_lookup (table, name); \ + if (!tag) \ + { \ + tag = gtk_text_tag_new (name); \ + g_object_set (tag, #attr_name, &rgba, NULL); \ + gtk_text_tag_table_add (table, tag); \ + g_object_unref (tag); \ + } \ + g_ptr_array_add (tags, tag); \ + } + + attr = pango_attr_iterator_get (iter, PANGO_ATTR_BACKGROUND); attr = pango_attr_iterator_get (iter, PANGO_ATTR_LANGUAGE); if (attr) - g_object_set (tag, "language", pango_language_to_string (((PangoAttrLanguage*)attr)->value), NULL); + { + const char *language = pango_language_to_string (((PangoAttrLanguage*)attr)->value); + g_snprintf (name, 256, "language=%s", language); + tag = gtk_text_tag_table_lookup (table, name); + if (!tag) + { + tag = gtk_text_tag_new (name); + g_object_set (tag, "language", language, NULL); + gtk_text_tag_table_add (table, tag); + g_object_unref (tag); + } + g_ptr_array_add (tags, tag); + } - attr = pango_attr_iterator_get (iter, PANGO_ATTR_FAMILY); - if (attr) - g_object_set (tag, "family", ((PangoAttrString*)attr)->value, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_STYLE); - if (attr) - g_object_set (tag, "style", ((PangoAttrInt*)attr)->value, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_WEIGHT); - if (attr) - g_object_set (tag, "weight", ((PangoAttrInt*)attr)->value, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_VARIANT); - if (attr) - g_object_set (tag, "variant", ((PangoAttrInt*)attr)->value, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_STRETCH); - if (attr) - g_object_set (tag, "stretch", ((PangoAttrInt*)attr)->value, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_SIZE); - if (attr) - g_object_set (tag, "size", ((PangoAttrInt*)attr)->value, NULL); + STRING_ATTR(PANGO_ATTR_FAMILY, family) + INT_ATTR(PANGO_ATTR_STYLE, style) + INT_ATTR(PANGO_ATTR_WEIGHT, weight) + INT_ATTR(PANGO_ATTR_VARIANT, variant) + INT_ATTR(PANGO_ATTR_STRETCH, stretch) + INT_ATTR(PANGO_ATTR_SIZE, size) attr = pango_attr_iterator_get (iter, PANGO_ATTR_FONT_DESC); - if (attr) - g_object_set (tag, "font-desc", ((PangoAttrFontDesc*)attr)->desc, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_FOREGROUND); if (attr) { - PangoColor *color; - GdkRGBA rgba; - - color = &((PangoAttrColor*)attr)->color; - rgba.red = color->red / 65535.; - rgba.green = color->green / 65535.; - rgba.blue = color->blue / 65535.; - rgba.alpha = 1.; - g_object_set (tag, "foreground-rgba", &rgba, NULL); - }; - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_BACKGROUND); - if (attr) - { - PangoColor *color; - GdkRGBA rgba; - - color = &((PangoAttrColor*)attr)->color; - rgba.red = color->red / 65535.; - rgba.green = color->green / 65535.; - rgba.blue = color->blue / 65535.; - rgba.alpha = 1.; - g_object_set (tag, "background-rgba", &rgba, NULL); - }; - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_UNDERLINE); - if (attr) - g_object_set (tag, "underline", ((PangoAttrInt*)attr)->value, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_UNDERLINE_COLOR); - if (attr) - { - PangoColor *color; - GdkRGBA rgba; - - color = &((PangoAttrColor*)attr)->color; - rgba.red = color->red / 65535.; - rgba.green = color->green / 65535.; - rgba.blue = color->blue / 65535.; - rgba.alpha = 1.; - g_object_set (tag, "underline-rgba", &rgba, NULL); + PangoFontDescription *desc = ((PangoAttrFontDesc*)attr)->desc; + char *str = pango_font_description_to_string (desc); + g_snprintf (name, 256, "font-desc=%s", str); + g_free (str); + tag = gtk_text_tag_table_lookup (table, name); + if (!tag) + { + tag = gtk_text_tag_new (name); + g_object_set (tag, "font-desc", desc, NULL); + gtk_text_tag_table_add (table, tag); + g_object_unref (tag); + } + g_ptr_array_add (tags, tag); } - attr = pango_attr_iterator_get (iter, PANGO_ATTR_OVERLINE); - if (attr) - g_object_set (tag, "overline", ((PangoAttrInt*)attr)->value, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_OVERLINE_COLOR); - if (attr) - { - PangoColor *color; - GdkRGBA rgba; - - color = &((PangoAttrColor*)attr)->color; - rgba.red = color->red / 65535.; - rgba.green = color->green / 65535.; - rgba.blue = color->blue / 65535.; - rgba.alpha = 1.; - g_object_set (tag, "overline-rgba", &rgba, NULL); - } - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_STRIKETHROUGH); - if (attr) - g_object_set (tag, "strikethrough", (gboolean) (((PangoAttrInt*)attr)->value != 0), NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_STRIKETHROUGH_COLOR); - if (attr) - { - PangoColor *color; - GdkRGBA rgba; - - color = &((PangoAttrColor*)attr)->color; - rgba.red = color->red / 65535.; - rgba.green = color->green / 65535.; - rgba.blue = color->blue / 65535.; - rgba.alpha = 1.; - g_object_set (tag, "strikethrough-rgba", &rgba, NULL); - } - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_RISE); - if (attr) - g_object_set (tag, "rise", ((PangoAttrInt*)attr)->value, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_SCALE); - if (attr) - g_object_set (tag, "scale", ((PangoAttrFloat*)attr)->value, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_FALLBACK); - if (attr) - g_object_set (tag, "fallback", (gboolean) (((PangoAttrInt*)attr)->value != 0), NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_LETTER_SPACING); - if (attr) - g_object_set (tag, "letter-spacing", ((PangoAttrInt*)attr)->value, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_FONT_FEATURES); - if (attr) - g_object_set (tag, "font-features", ((PangoAttrString*)attr)->value, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_ALLOW_BREAKS); - if (attr) - g_object_set (tag, "allow-breaks", ((PangoAttrInt*)attr)->value, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_SHOW); - if (attr) - g_object_set (tag, "show-spaces", ((PangoAttrInt*)attr)->value, NULL); - - attr = pango_attr_iterator_get (iter, PANGO_ATTR_INSERT_HYPHENS); - if (attr) - g_object_set (tag, "insert-hyphens", ((PangoAttrInt*)attr)->value, NULL); - - return tag; + RGBA_ATTR(PANGO_ATTR_FOREGROUND, foreground_rgba) + RGBA_ATTR(PANGO_ATTR_BACKGROUND, background_rgba) + INT_ATTR(PANGO_ATTR_UNDERLINE, underline) + RGBA_ATTR(PANGO_ATTR_UNDERLINE_COLOR, underline_rgba) + INT_ATTR(PANGO_ATTR_OVERLINE, overline) + RGBA_ATTR(PANGO_ATTR_OVERLINE_COLOR, overline_rgba) + INT_ATTR(PANGO_ATTR_STRIKETHROUGH, strikethrough) + RGBA_ATTR(PANGO_ATTR_STRIKETHROUGH_COLOR, strikethrough_rgba) + INT_ATTR(PANGO_ATTR_RISE, rise) + FLOAT_ATTR(PANGO_ATTR_SCALE, scale) + INT_ATTR(PANGO_ATTR_FALLBACK, fallback) + INT_ATTR(PANGO_ATTR_LETTER_SPACING, letter_spacing) + STRING_ATTR(PANGO_ATTR_FONT_FEATURES, font_features) + INT_ATTR(PANGO_ATTR_ALLOW_BREAKS, allow_breaks) + INT_ATTR(PANGO_ATTR_SHOW, show_spaces) + INT_ATTR(PANGO_ATTR_INSERT_HYPHENS, insert_hyphens) } static void @@ -4544,7 +4555,8 @@ gtk_text_buffer_insert_with_attributes (GtkTextBuffer *buffer, { GtkTextMark *mark; PangoAttrIterator *attr; - GtkTextTagTable *tags; + GtkTextTagTable *table; + GPtrArray *tags; g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer)); @@ -4557,11 +4569,11 @@ gtk_text_buffer_insert_with_attributes (GtkTextBuffer *buffer, /* create mark with right gravity */ mark = gtk_text_buffer_create_mark (buffer, NULL, iter, FALSE); attr = pango_attr_list_get_iterator (attributes); - tags = gtk_text_buffer_get_tag_table (buffer); + table = gtk_text_buffer_get_tag_table (buffer); + tags = g_ptr_array_new (); do { - GtkTextTag *tag; int start, end; pango_attr_iterator_range (attr, &start, &end); @@ -4569,20 +4581,24 @@ gtk_text_buffer_insert_with_attributes (GtkTextBuffer *buffer, if (end == G_MAXINT) /* last chunk */ end = start - 1; /* resulting in -1 to be passed to _insert */ - tag = get_tag_for_attributes (attr); - gtk_text_tag_table_add (tags, tag); + get_tags_for_attributes (attr, table, tags); - gtk_text_buffer_insert_with_tags (buffer, iter, text + start, end - start, tag, NULL); + gtk_text_buffer_insert_with_tagsv (buffer, + iter, + text + start, end - start, + (GtkTextTag **)tags->pdata, tags->len); + + g_ptr_array_set_size (tags, 0); gtk_text_buffer_get_iter_at_mark (buffer, iter, mark); - - g_object_unref (tag); } while (pango_attr_iterator_next (attr)); - + + g_ptr_array_unref (tags); + gtk_text_buffer_delete_mark (buffer, mark); pango_attr_iterator_destroy (attr); -} +} /** * gtk_text_buffer_insert_markup: @@ -4616,8 +4632,9 @@ gtk_text_buffer_insert_markup (GtkTextBuffer *buffer, gtk_text_buffer_insert_with_attributes (buffer, iter, text, attributes); + g_print ("created %d tags\n", gtk_text_tag_table_get_size (gtk_text_buffer_get_tag_table (buffer))); pango_attr_list_unref (attributes); - g_free (text); + g_free (text); } static void