summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-04-06 21:46:12 -0400
committerMatthias Clasen <mclasen@redhat.com>2020-04-06 22:59:45 -0400
commit3371e3aa49ec6fd3cca4775cb6cceef4173cf104 (patch)
treeb895e376e551ad1e9b4e5ea12ea817cab38bb511
parentbaeae71d12d36c20f6dbe7d780bf5a8c55f4832a (diff)
downloadgtk+-3371e3aa49ec6fd3cca4775cb6cceef4173cf104.tar.gz
Move label attribute parser code
We want to reuse the parser for <attributes> in several widgets, so move it to a shared place.
-rw-r--r--gtk/gtklabel.c316
-rw-r--r--gtk/gtkpango.c294
-rw-r--r--gtk/gtkpango.h22
3 files changed, 323 insertions, 309 deletions
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index 2bba929146..42ccc00b3f 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -1360,310 +1360,10 @@ gtk_label_buildable_interface_init (GtkBuildableIface *iface)
iface->custom_finished = gtk_label_buildable_custom_finished;
}
-typedef struct {
- GtkBuilder *builder;
- GObject *object;
- PangoAttrList *attrs;
-} PangoParserData;
-
-static PangoAttribute *
-attribute_from_text (GtkBuilder *builder,
- const gchar *name,
- const gchar *value,
- GError **error)
-{
- PangoAttribute *attribute = NULL;
- PangoAttrType type;
- PangoLanguage *language;
- PangoFontDescription *font_desc;
- GdkRGBA *color;
- GValue val = G_VALUE_INIT;
-
- if (!gtk_builder_value_from_string_type (builder, PANGO_TYPE_ATTR_TYPE, name, &val, error))
- return NULL;
-
- type = g_value_get_enum (&val);
- g_value_unset (&val);
-
- switch (type)
- {
- /* PangoAttrLanguage */
- case PANGO_ATTR_LANGUAGE:
- if ((language = pango_language_from_string (value)))
- {
- attribute = pango_attr_language_new (language);
- g_value_init (&val, G_TYPE_INT);
- }
- break;
- /* PangoAttrInt */
- case PANGO_ATTR_STYLE:
- if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_STYLE, value, &val, error))
- attribute = pango_attr_style_new (g_value_get_enum (&val));
- break;
- case PANGO_ATTR_WEIGHT:
- if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_WEIGHT, value, &val, error))
- attribute = pango_attr_weight_new (g_value_get_enum (&val));
- break;
- case PANGO_ATTR_VARIANT:
- if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_VARIANT, value, &val, error))
- attribute = pango_attr_variant_new (g_value_get_enum (&val));
- break;
- case PANGO_ATTR_STRETCH:
- if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_STRETCH, value, &val, error))
- attribute = pango_attr_stretch_new (g_value_get_enum (&val));
- break;
- case PANGO_ATTR_UNDERLINE:
- if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_UNDERLINE, value, &val, NULL))
- attribute = pango_attr_underline_new (g_value_get_enum (&val));
- else
- {
- /* XXX: allow boolean for backwards compat, so ignore error */
- /* Deprecate this somehow */
- g_value_unset (&val);
- if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
- attribute = pango_attr_underline_new (g_value_get_boolean (&val));
- }
- break;
- case PANGO_ATTR_STRIKETHROUGH:
- if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
- attribute = pango_attr_strikethrough_new (g_value_get_boolean (&val));
- break;
- case PANGO_ATTR_GRAVITY:
- if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_GRAVITY, value, &val, error))
- attribute = pango_attr_gravity_new (g_value_get_enum (&val));
- break;
- case PANGO_ATTR_GRAVITY_HINT:
- if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_GRAVITY_HINT, value, &val, error))
- attribute = pango_attr_gravity_hint_new (g_value_get_enum (&val));
- break;
- /* PangoAttrString */
- case PANGO_ATTR_FAMILY:
- attribute = pango_attr_family_new (value);
- g_value_init (&val, G_TYPE_INT);
- break;
-
- /* PangoAttrSize */
- case PANGO_ATTR_SIZE:
- if (gtk_builder_value_from_string_type (builder, G_TYPE_INT, value, &val, error))
- attribute = pango_attr_size_new (g_value_get_int (&val));
- break;
- case PANGO_ATTR_ABSOLUTE_SIZE:
- if (gtk_builder_value_from_string_type (builder, G_TYPE_INT, value, &val, error))
- attribute = pango_attr_size_new_absolute (g_value_get_int (&val));
- break;
-
- /* PangoAttrFontDesc */
- case PANGO_ATTR_FONT_DESC:
- if ((font_desc = pango_font_description_from_string (value)))
- {
- attribute = pango_attr_font_desc_new (font_desc);
- pango_font_description_free (font_desc);
- g_value_init (&val, G_TYPE_INT);
- }
- break;
- /* PangoAttrColor */
- case PANGO_ATTR_FOREGROUND:
- if (gtk_builder_value_from_string_type (builder, GDK_TYPE_RGBA, value, &val, error))
- {
- color = g_value_get_boxed (&val);
- attribute = pango_attr_foreground_new (color->red * 65535,
- color->green * 65535,
- color->blue * 65535);
- }
- break;
- case PANGO_ATTR_BACKGROUND:
- if (gtk_builder_value_from_string_type (builder, GDK_TYPE_RGBA, value, &val, error))
- {
- color = g_value_get_boxed (&val);
- attribute = pango_attr_background_new (color->red * 65535,
- color->green * 65535,
- color->blue * 65535);
- }
- break;
- case PANGO_ATTR_UNDERLINE_COLOR:
- if (gtk_builder_value_from_string_type (builder, GDK_TYPE_RGBA, value, &val, error))
- {
- color = g_value_get_boxed (&val);
- attribute = pango_attr_underline_color_new (color->red * 65535,
- color->green * 65535,
- color->blue * 65535);
- }
- break;
- case PANGO_ATTR_STRIKETHROUGH_COLOR:
- if (gtk_builder_value_from_string_type (builder, GDK_TYPE_RGBA, value, &val, error))
- {
- color = g_value_get_boxed (&val);
- attribute = pango_attr_strikethrough_color_new (color->red * 65535,
- color->green * 65535,
- color->blue * 65535);
- }
- break;
- /* PangoAttrShape */
- case PANGO_ATTR_SHAPE:
- /* Unsupported for now */
- break;
- /* PangoAttrFloat */
- case PANGO_ATTR_SCALE:
- if (gtk_builder_value_from_string_type (builder, G_TYPE_DOUBLE, value, &val, error))
- attribute = pango_attr_scale_new (g_value_get_double (&val));
- break;
- case PANGO_ATTR_LETTER_SPACING:
- if (gtk_builder_value_from_string_type (builder, G_TYPE_INT, value, &val, error))
- attribute = pango_attr_letter_spacing_new (g_value_get_int (&val));
- break;
- case PANGO_ATTR_RISE:
- if (gtk_builder_value_from_string_type (builder, G_TYPE_INT, value, &val, error))
- attribute = pango_attr_rise_new (g_value_get_int (&val));
- break;
- case PANGO_ATTR_FALLBACK:
- if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
- attribute = pango_attr_fallback_new (g_value_get_boolean (&val));
- break;
- case PANGO_ATTR_FONT_FEATURES:
- attribute = pango_attr_font_features_new (value);
- break;
- case PANGO_ATTR_FOREGROUND_ALPHA:
- if (gtk_builder_value_from_string_type (builder, G_TYPE_INT, value, &val, error))
- attribute = pango_attr_foreground_alpha_new ((guint16)g_value_get_int (&val));
- break;
- case PANGO_ATTR_BACKGROUND_ALPHA:
- if (gtk_builder_value_from_string_type (builder, G_TYPE_INT, value, &val, error))
- attribute = pango_attr_background_alpha_new ((guint16)g_value_get_int (&val));
- break;
-#if PANGO_VERSION_CHECK(1,44,0)
- case PANGO_ATTR_ALLOW_BREAKS:
- if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
- attribute = pango_attr_allow_breaks_new (g_value_get_boolean (&val));
- break;
- case PANGO_ATTR_SHOW:
- if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_SHOW_FLAGS, value, &val, error))
- attribute = pango_attr_show_new (g_value_get_flags (&val));
- break;
- case PANGO_ATTR_INSERT_HYPHENS:
- if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
- attribute = pango_attr_insert_hyphens_new (g_value_get_boolean (&val));
- break;
-#endif
-#if PANGO_VERSION_CHECK(1,45,0)
- case PANGO_ATTR_OVERLINE:
- if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_OVERLINE, value, &val, NULL))
- attribute = pango_attr_overline_new (g_value_get_enum (&val));
- break;
- case PANGO_ATTR_OVERLINE_COLOR:
- if (gtk_builder_value_from_string_type (builder, GDK_TYPE_RGBA, value, &val, error))
- {
- color = g_value_get_boxed (&val);
- attribute = pango_attr_overline_color_new (color->red * 65535,
- color->green * 65535,
- color->blue * 65535);
- }
- break;
-#endif
- case PANGO_ATTR_INVALID:
- default:
- break;
- }
-
- g_value_unset (&val);
-
- return attribute;
-}
-
-
-static void
-pango_start_element (GtkBuildableParseContext *context,
- const gchar *element_name,
- const gchar **names,
- const gchar **values,
- gpointer user_data,
- GError **error)
-{
- PangoParserData *data = (PangoParserData*)user_data;
-
- if (strcmp (element_name, "attribute") == 0)
- {
- PangoAttribute *attr = NULL;
- const gchar *name = NULL;
- const gchar *value = NULL;
- const gchar *start = NULL;
- const gchar *end = NULL;
- guint start_val = 0;
- guint end_val = G_MAXUINT;
- GValue val = G_VALUE_INIT;
-
- if (!_gtk_builder_check_parent (data->builder, context, "attributes", error))
- return;
-
- if (!g_markup_collect_attributes (element_name, names, values, error,
- G_MARKUP_COLLECT_STRING, "name", &name,
- G_MARKUP_COLLECT_STRING, "value", &value,
- G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "start", &start,
- G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "end", &end,
- G_MARKUP_COLLECT_INVALID))
- {
- _gtk_builder_prefix_error (data->builder, context, error);
- return;
- }
-
- if (start)
- {
- if (!gtk_builder_value_from_string_type (data->builder, G_TYPE_UINT, start, &val, error))
- {
- _gtk_builder_prefix_error (data->builder, context, error);
- return;
- }
- start_val = g_value_get_uint (&val);
- g_value_unset (&val);
- }
-
- if (end)
- {
- if (!gtk_builder_value_from_string_type (data->builder, G_TYPE_UINT, end, &val, error))
- {
- _gtk_builder_prefix_error (data->builder, context, error);
- return;
- }
- end_val = g_value_get_uint (&val);
- g_value_unset (&val);
- }
-
- attr = attribute_from_text (data->builder, name, value, error);
- if (!attr)
- {
- _gtk_builder_prefix_error (data->builder, context, error);
- return;
- }
-
- attr->start_index = start_val;
- attr->end_index = end_val;
-
- if (!data->attrs)
- data->attrs = pango_attr_list_new ();
-
- pango_attr_list_insert (data->attrs, attr);
- }
- else if (strcmp (element_name, "attributes") == 0)
- {
- if (!_gtk_builder_check_parent (data->builder, context, "object", error))
- return;
-
- if (!g_markup_collect_attributes (element_name, names, values, error,
- G_MARKUP_COLLECT_INVALID, NULL, NULL,
- G_MARKUP_COLLECT_INVALID))
- _gtk_builder_prefix_error (data->builder, context, error);
- }
- else
- {
- _gtk_builder_error_unhandled_tag (data->builder, context,
- "GtkContainer", element_name,
- error);
- }
-}
-
static const GtkBuildableParser pango_parser =
- {
- pango_start_element,
- };
+{
+ gtk_pango_attribute_start_element,
+};
static gboolean
gtk_label_buildable_custom_tag_start (GtkBuildable *buildable,
@@ -1679,9 +1379,9 @@ gtk_label_buildable_custom_tag_start (GtkBuildable *buildable,
if (strcmp (tagname, "attributes") == 0)
{
- PangoParserData *parser_data;
+ GtkPangoAttributeParserData *parser_data;
- parser_data = g_slice_new0 (PangoParserData);
+ parser_data = g_slice_new0 (GtkPangoAttributeParserData);
parser_data->builder = g_object_ref (builder);
parser_data->object = (GObject *) g_object_ref (buildable);
*parser = pango_parser;
@@ -1698,15 +1398,13 @@ gtk_label_buildable_custom_finished (GtkBuildable *buildable,
const gchar *tagname,
gpointer user_data)
{
- PangoParserData *data;
+ GtkPangoAttributeParserData *data = user_data;
buildable_parent_iface->custom_finished (buildable, builder, child,
tagname, user_data);
if (strcmp (tagname, "attributes") == 0)
{
- data = (PangoParserData*)user_data;
-
if (data->attrs)
{
gtk_label_set_attributes (GTK_LABEL (buildable), data->attrs);
@@ -1715,7 +1413,7 @@ gtk_label_buildable_custom_finished (GtkBuildable *buildable,
g_object_unref (data->object);
g_object_unref (data->builder);
- g_slice_free (PangoParserData, data);
+ g_slice_free (GtkPangoAttributeParserData, data);
}
}
diff --git a/gtk/gtkpango.c b/gtk/gtkpango.c
index 1f6e70954a..2ebb3c5d44 100644
--- a/gtk/gtkpango.c
+++ b/gtk/gtkpango.c
@@ -26,6 +26,7 @@
#include "gtkpango.h"
#include <pango/pangocairo.h>
#include "gtkintl.h"
+#include "gtkbuilderprivate.h"
static AtkAttributeSet *
add_attribute (AtkAttributeSet *attributes,
@@ -1075,3 +1076,296 @@ _gtk_pango_attr_list_merge (PangoAttrList *into,
return into;
}
+
+static PangoAttribute *
+attribute_from_text (GtkBuilder *builder,
+ const char *name,
+ const char *value,
+ GError **error)
+{
+ PangoAttribute *attribute = NULL;
+ PangoAttrType type;
+ PangoLanguage *language;
+ PangoFontDescription *font_desc;
+ GdkRGBA *color;
+ GValue val = G_VALUE_INIT;
+
+ if (!gtk_builder_value_from_string_type (builder, PANGO_TYPE_ATTR_TYPE, name, &val, error))
+ return NULL;
+
+ type = g_value_get_enum (&val);
+ g_value_unset (&val);
+
+ switch (type)
+ {
+ /* PangoAttrLanguage */
+ case PANGO_ATTR_LANGUAGE:
+ if ((language = pango_language_from_string (value)))
+ {
+ attribute = pango_attr_language_new (language);
+ g_value_init (&val, G_TYPE_INT);
+ }
+ break;
+ /* PangoAttrInt */
+ case PANGO_ATTR_STYLE:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_STYLE, value, &val, error))
+ attribute = pango_attr_style_new (g_value_get_enum (&val));
+ break;
+ case PANGO_ATTR_WEIGHT:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_WEIGHT, value, &val, error))
+ attribute = pango_attr_weight_new (g_value_get_enum (&val));
+ break;
+ case PANGO_ATTR_VARIANT:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_VARIANT, value, &val, error))
+ attribute = pango_attr_variant_new (g_value_get_enum (&val));
+ break;
+ case PANGO_ATTR_STRETCH:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_STRETCH, value, &val, error))
+ attribute = pango_attr_stretch_new (g_value_get_enum (&val));
+ break;
+ case PANGO_ATTR_UNDERLINE:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_UNDERLINE, value, &val, NULL))
+ attribute = pango_attr_underline_new (g_value_get_enum (&val));
+ else
+ {
+ /* XXX: allow boolean for backwards compat, so ignore error */
+ /* Deprecate this somehow */
+ g_value_unset (&val);
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
+ attribute = pango_attr_underline_new (g_value_get_boolean (&val));
+ }
+ break;
+ case PANGO_ATTR_STRIKETHROUGH:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
+ attribute = pango_attr_strikethrough_new (g_value_get_boolean (&val));
+ break;
+ case PANGO_ATTR_GRAVITY:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_GRAVITY, value, &val, error))
+ attribute = pango_attr_gravity_new (g_value_get_enum (&val));
+ break;
+ case PANGO_ATTR_GRAVITY_HINT:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_GRAVITY_HINT, value, &val, error))
+ attribute = pango_attr_gravity_hint_new (g_value_get_enum (&val));
+ break;
+ /* PangoAttrString */
+ case PANGO_ATTR_FAMILY:
+ attribute = pango_attr_family_new (value);
+ g_value_init (&val, G_TYPE_INT);
+ break;
+
+ /* PangoAttrSize */
+ case PANGO_ATTR_SIZE:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_INT, value, &val, error))
+ attribute = pango_attr_size_new (g_value_get_int (&val));
+ break;
+ case PANGO_ATTR_ABSOLUTE_SIZE:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_INT, value, &val, error))
+ attribute = pango_attr_size_new_absolute (g_value_get_int (&val));
+ break;
+
+ /* PangoAttrFontDesc */
+ case PANGO_ATTR_FONT_DESC:
+ if ((font_desc = pango_font_description_from_string (value)))
+ {
+ attribute = pango_attr_font_desc_new (font_desc);
+ pango_font_description_free (font_desc);
+ g_value_init (&val, G_TYPE_INT);
+ }
+ break;
+ /* PangoAttrColor */
+ case PANGO_ATTR_FOREGROUND:
+ if (gtk_builder_value_from_string_type (builder, GDK_TYPE_RGBA, value, &val, error))
+ {
+ color = g_value_get_boxed (&val);
+ attribute = pango_attr_foreground_new (color->red * 65535,
+ color->green * 65535,
+ color->blue * 65535);
+ }
+ break;
+ case PANGO_ATTR_BACKGROUND:
+ if (gtk_builder_value_from_string_type (builder, GDK_TYPE_RGBA, value, &val, error))
+ {
+ color = g_value_get_boxed (&val);
+ attribute = pango_attr_background_new (color->red * 65535,
+ color->green * 65535,
+ color->blue * 65535);
+ }
+ break;
+ case PANGO_ATTR_UNDERLINE_COLOR:
+ if (gtk_builder_value_from_string_type (builder, GDK_TYPE_RGBA, value, &val, error))
+ {
+ color = g_value_get_boxed (&val);
+ attribute = pango_attr_underline_color_new (color->red * 65535,
+ color->green * 65535,
+ color->blue * 65535);
+ }
+ break;
+ case PANGO_ATTR_STRIKETHROUGH_COLOR:
+ if (gtk_builder_value_from_string_type (builder, GDK_TYPE_RGBA, value, &val, error))
+ {
+ color = g_value_get_boxed (&val);
+ attribute = pango_attr_strikethrough_color_new (color->red * 65535,
+ color->green * 65535,
+ color->blue * 65535);
+ }
+ break;
+ /* PangoAttrShape */
+ case PANGO_ATTR_SHAPE:
+ /* Unsupported for now */
+ break;
+ /* PangoAttrFloat */
+ case PANGO_ATTR_SCALE:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_DOUBLE, value, &val, error))
+ attribute = pango_attr_scale_new (g_value_get_double (&val));
+ break;
+ case PANGO_ATTR_LETTER_SPACING:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_INT, value, &val, error))
+ attribute = pango_attr_letter_spacing_new (g_value_get_int (&val));
+ break;
+ case PANGO_ATTR_RISE:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_INT, value, &val, error))
+ attribute = pango_attr_rise_new (g_value_get_int (&val));
+ break;
+ case PANGO_ATTR_FALLBACK:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
+ attribute = pango_attr_fallback_new (g_value_get_boolean (&val));
+ break;
+ case PANGO_ATTR_FONT_FEATURES:
+ attribute = pango_attr_font_features_new (value);
+ break;
+ case PANGO_ATTR_FOREGROUND_ALPHA:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_INT, value, &val, error))
+ attribute = pango_attr_foreground_alpha_new ((guint16)g_value_get_int (&val));
+ break;
+ case PANGO_ATTR_BACKGROUND_ALPHA:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_INT, value, &val, error))
+ attribute = pango_attr_background_alpha_new ((guint16)g_value_get_int (&val));
+ break;
+#if PANGO_VERSION_CHECK(1,44,0)
+ case PANGO_ATTR_ALLOW_BREAKS:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
+ attribute = pango_attr_allow_breaks_new (g_value_get_boolean (&val));
+ break;
+ case PANGO_ATTR_SHOW:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_SHOW_FLAGS, value, &val, error))
+ attribute = pango_attr_show_new (g_value_get_flags (&val));
+ break;
+ case PANGO_ATTR_INSERT_HYPHENS:
+ if (gtk_builder_value_from_string_type (builder, G_TYPE_BOOLEAN, value, &val, error))
+ attribute = pango_attr_insert_hyphens_new (g_value_get_boolean (&val));
+ break;
+#endif
+#if PANGO_VERSION_CHECK(1,45,0)
+ case PANGO_ATTR_OVERLINE:
+ if (gtk_builder_value_from_string_type (builder, PANGO_TYPE_OVERLINE, value, &val, NULL))
+ attribute = pango_attr_overline_new (g_value_get_enum (&val));
+ break;
+ case PANGO_ATTR_OVERLINE_COLOR:
+ if (gtk_builder_value_from_string_type (builder, GDK_TYPE_RGBA, value, &val, error))
+ {
+ color = g_value_get_boxed (&val);
+ attribute = pango_attr_overline_color_new (color->red * 65535,
+ color->green * 65535,
+ color->blue * 65535);
+ }
+ break;
+#endif
+ case PANGO_ATTR_INVALID:
+ default:
+ break;
+ }
+
+ g_value_unset (&val);
+
+ return attribute;
+}
+
+void
+gtk_pango_attribute_start_element (GtkBuildableParseContext *context,
+ const char *element_name,
+ const char **names,
+ const char **values,
+ gpointer user_data,
+ GError **error)
+{
+ GtkPangoAttributeParserData *data = user_data;
+
+ if (strcmp (element_name, "attribute") == 0)
+ {
+ PangoAttribute *attr = NULL;
+ const char *name = NULL;
+ const char *value = NULL;
+ const char *start = NULL;
+ const char *end = NULL;
+ guint start_val = 0;
+ guint end_val = G_MAXUINT;
+ GValue val = G_VALUE_INIT;
+
+ if (!_gtk_builder_check_parent (data->builder, context, "attributes", error))
+ return;
+
+ if (!g_markup_collect_attributes (element_name, names, values, error,
+ G_MARKUP_COLLECT_STRING, "name", &name,
+ G_MARKUP_COLLECT_STRING, "value", &value,
+ G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "start", &start,
+ G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "end", &end,
+ G_MARKUP_COLLECT_INVALID))
+ {
+ _gtk_builder_prefix_error (data->builder, context, error);
+ return;
+ }
+
+ if (start)
+ {
+ if (!gtk_builder_value_from_string_type (data->builder, G_TYPE_UINT, start, &val, error))
+ {
+ _gtk_builder_prefix_error (data->builder, context, error);
+ return;
+ }
+ start_val = g_value_get_uint (&val);
+ g_value_unset (&val);
+ }
+
+ if (end)
+ {
+ if (!gtk_builder_value_from_string_type (data->builder, G_TYPE_UINT, end, &val, error))
+ {
+ _gtk_builder_prefix_error (data->builder, context, error);
+ return;
+ }
+ end_val = g_value_get_uint (&val);
+ g_value_unset (&val);
+ }
+
+ attr = attribute_from_text (data->builder, name, value, error);
+ if (!attr)
+ {
+ _gtk_builder_prefix_error (data->builder, context, error);
+ return;
+ }
+
+ attr->start_index = start_val;
+ attr->end_index = end_val;
+
+ if (!data->attrs)
+ data->attrs = pango_attr_list_new ();
+
+ pango_attr_list_insert (data->attrs, attr);
+ }
+ else if (strcmp (element_name, "attributes") == 0)
+ {
+ if (!_gtk_builder_check_parent (data->builder, context, "object", error))
+ return;
+
+ if (!g_markup_collect_attributes (element_name, names, values, error,
+ G_MARKUP_COLLECT_INVALID, NULL, NULL,
+ G_MARKUP_COLLECT_INVALID))
+ _gtk_builder_prefix_error (data->builder, context, error);
+ }
+ else
+ {
+ _gtk_builder_error_unhandled_tag (data->builder, context,
+ "GtkContainer", element_name,
+ error);
+ }
+}
diff --git a/gtk/gtkpango.h b/gtk/gtkpango.h
index 09c50b8731..4c3e97cba7 100644
--- a/gtk/gtkpango.h
+++ b/gtk/gtkpango.h
@@ -28,6 +28,7 @@
#include <pango/pangocairo.h>
#include <atk/atk.h>
+#include "gtkbuildable.h"
G_BEGIN_DECLS
@@ -59,6 +60,27 @@ gchar *_gtk_pango_get_text_after (PangoLayout *layout,
PangoAttrList *_gtk_pango_attr_list_merge (PangoAttrList *into,
PangoAttrList *from);
+gboolean gtk_buildable_attribute_tag_start (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ GtkBuildableParser *parser,
+ gpointer *data);
+
+typedef struct {
+ GtkBuilder *builder;
+ GObject *object;
+ PangoAttrList *attrs;
+} GtkPangoAttributeParserData;
+
+void
+gtk_pango_attribute_start_element (GtkBuildableParseContext *context,
+ const char *element_name,
+ const char **names,
+ const char **values,
+ gpointer user_data,
+ GError **error);
+
G_END_DECLS
#endif /* __GTK_PANGO_H__ */