[gtk/attribute-parsing: 1/2] Move label attribute parser code



commit dc2f65dd2bbdce9f2bd2779072e6aaa4da771068
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Apr 6 21:46:12 2020 -0400

    Move label attribute parser code
    
    We want to reuse the parser for <attributes> in several
    widgets, so move it to a shared place.

 gtk/gtklabel.c | 316 ++-------------------------------------------------------
 gtk/gtkpango.c | 293 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkpango.h |  22 ++++
 3 files changed, 322 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..d89a3cea16 100644
--- a/gtk/gtkpango.c
+++ b/gtk/gtkpango.c
@@ -1075,3 +1075,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__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]