Extending pango markup



Hi!

Ever since I decided I'd use a markup tag in my widgets[1] for
activatable text and embedding icons, I've been suffering from my
crappy C-string foo. I just don't seem to get it right with C, but the
reason for that could be motivational too ;)

The idea is to take a string with markup and replace the tags with
attributes (both standard pango and custom attributes), but my code is
currently far from robust.

The other problem with parsing the tags is that it gets very tricky
since you need to do it before parsing the string with pango (since
it'll choke on the custom tags) and thus you need to keep track of the
attribute indexes by hand so that you know where to apply them after
the markup tags are gone.

This made me really want to have the possibility to extend the pango
markup language so that I could register my tags there with a handler
and have it "just work". So I poked at it and found out that extending
pango markup would not be too hard to implement.

The attached patch is a quick stab at it to start the conversation. It
seems to work and was trivial to use (when compared to  the hack I had
to produce earlier :).

What I did was:

 - move the MarkupData and OpenTag to a public header
 - ditto for the TagParseFunc type
 - create a pango_markup_register_tag(tag_name, TagParseFunc) function

So I could simply create a function matching the TagParseFunc
signature  and call the register_tag with the tag name and function.
Internally, the registering happens to a hash table from which the tag
names are looked up if they don't match the builtin ones.

I'm not sure if the MarkupData or OpenTag really offer things that
should be available for applications. If not, they could be wrapped
away with another function which would just offer the attribute list.
But I guess this would depend on the use cases for the extended tags.
For my particular uses, simply adding the attributes is enough.

Overriding the builtin tags should not be allowed in my opinion, nor
would queuing old tag handlers really be useful (as the scope is just
the application anyway).

Thoughts? Obvious downsides? Am I on crack? Is it Good crack?-)

[1] http://iki.fi/zuh/scw

--
Kalle Vahlman, zuh iki fi
Powered by http://movial.fi
Interesting stuff at http://syslog.movial.fi
diff -uNr pango-1.12.0/pango/pango-markup.c pango-1.12.0-mod/pango/pango-markup.c
--- pango-1.12.0/pango/pango-markup.c	2006-01-29 23:40:11.000000000 +0200
+++ pango-1.12.0-mod/pango/pango-markup.c	2006-04-05 23:21:26.000000000 +0300
@@ -24,9 +24,12 @@
 #include <stdlib.h>
 #include <errno.h>
 
+#include <glib.h>
+
 #include <pango/pango-attributes.h>
 #include <pango/pango-font.h>
 #include <pango/pango-utils.h>
+#include <pango/pango-markup.h>
 
 /* FIXME */
 #define _(x) x
@@ -43,49 +46,10 @@
   XXLarge = 3
 } SizeLevel;
 
-typedef struct _MarkupData MarkupData;
-
-struct _MarkupData
-{
-  PangoAttrList *attr_list;
-  GString *text;
-  GSList *tag_stack;
-  gsize index;
-  GSList *to_apply;
-  gunichar accel_marker;
-  gunichar accel_char;
-};
-
-typedef struct _OpenTag OpenTag;
-
-struct _OpenTag
-{
-  GSList *attrs;
-  gsize start_index;
-  /* Current total scale level; reset whenever
-   * an absolute size is set.
-   * Each "larger" ups it 1, each "smaller" decrements it 1
-   */
-  gint scale_level;
-  /* Our impact on scale_level, so we know whether we
-   * need to create an attribute ourselves on close
-   */
-  gint scale_level_delta;
-  /* Base scale factor currently in effect
-   * or size that this tag
-   * forces, or parent's scale factor or size.
-   */
-  double base_scale_factor;
-  int base_font_size;
-  guint has_base_font_size : 1;
-};
+GHashTable *tag_hash;
 
-typedef gboolean (*TagParseFunc) (MarkupData            *md,
-                                  OpenTag               *tag,
-                                  const gchar          **names,
-                                  const gchar          **values,
-                                  GMarkupParseContext   *context,
-                                  GError               **error);
+void pango_markup_register_tag (const gchar *tag_name,
+                                TagParseFunc parse_function);
 
 static gboolean b_parse_func        (MarkupData           *md,
                                      OpenTag              *tag,
@@ -370,6 +334,11 @@
       if (strcmp ("u", element_name) == 0)
         parse_func = u_parse_func;
       break;
+    default:
+      if (tag_hash != NULL)
+        {
+          parse_func = g_hash_table_lookup (tag_hash, element_name);
+        }
     }
 
   if (parse_func == NULL)
@@ -1456,3 +1425,17 @@
 
   return TRUE;
 }
+
+void pango_markup_register_tag (const gchar *tag_name,
+                                TagParseFunc parse_function)
+{
+  
+  if (tag_hash == NULL)
+    {
+      tag_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                        g_free, NULL);
+    }
+  
+  g_hash_table_insert (tag_hash, g_strdup(tag_name), parse_function);
+  
+}
diff -uNr pango-1.12.0/pango/pango-markup.h pango-1.12.0-mod/pango/pango-markup.h
--- pango-1.12.0/pango/pango-markup.h	1970-01-01 02:00:00.000000000 +0200
+++ pango-1.12.0-mod/pango/pango-markup.h	2006-04-05 23:21:26.000000000 +0300
@@ -0,0 +1,67 @@
+/* Pango
+ * pango-markup.h: Parse markup into attributed text
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+typedef struct _MarkupData MarkupData;
+
+struct _MarkupData
+{
+  PangoAttrList *attr_list;
+  GString *text;
+  GSList *tag_stack;
+  gsize index;
+  GSList *to_apply;
+  gunichar accel_marker;
+  gunichar accel_char;
+};
+
+typedef struct _OpenTag OpenTag;
+
+struct _OpenTag
+{
+  GSList *attrs;
+  gsize start_index;
+  /* Current total scale level; reset whenever
+   * an absolute size is set.
+   * Each "larger" ups it 1, each "smaller" decrements it 1
+   */
+  gint scale_level;
+  /* Our impact on scale_level, so we know whether we
+   * need to create an attribute ourselves on close
+   */
+  gint scale_level_delta;
+  /* Base scale factor currently in effect
+   * or size that this tag
+   * forces, or parent's scale factor or size.
+   */
+  double base_scale_factor;
+  int base_font_size;
+  guint has_base_font_size : 1;
+};
+
+
+typedef gboolean (*TagParseFunc) (MarkupData            *md,
+                                  OpenTag               *tag,
+                                  const gchar          **names,
+                                  const gchar          **values,
+                                  GMarkupParseContext   *context,
+                                  GError               **error);
+
+void pango_markup_register_tag (const gchar *tag_name, TagParseFunc parse_function);
































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