[monet/bberg-playground: 3/4] More code.



commit 47b5f1e4a899f7aeab065597319f066c8fc0e567
Author: Benjamin Berg <benjamin sipsolutions net>
Date:   Sun Aug 16 17:52:43 2009 +0200

    More code.

 monet/Makefile.am     |    2 +
 monet/mn-display.c    |   18 ++--
 monet/mn-display.h    |    2 +-
 monet/mn-stylesheet.c |  286 ++++++++++++++++++++++++++++++++++++++++++++-----
 monet/mn-theme-type.c |  185 +++++++++++++++++++++++++++++++
 monet/mn-theme-type.h |   66 +++++++++++
 monet/monet.h         |    4 +-
 7 files changed, 522 insertions(+), 41 deletions(-)
---
diff --git a/monet/Makefile.am b/monet/Makefile.am
index e8fb251..c65c065 100644
--- a/monet/Makefile.am
+++ b/monet/Makefile.am
@@ -8,6 +8,7 @@ STAMP_FILES = \
 	stamp-mn-enum-types.h
 
 source_h = \
+	mn-theme-type.h \
 	mn-display.h \
 	mn-stylesheet.h \
 	mn-context.h \
@@ -38,6 +39,7 @@ mn-enum-types.c: stamp-mn-enum-types.h mn-enum-types.c.in
 lib_LTLIBRARIES = libmonet.la
 libmonet_la_SOURCES = $(BUILT_SOURCES) \
         $(source_h) \
+        mn-theme-type.c \
 	mn-display.c \
 	mn-stylesheet.c \
 	mn-context.c \
diff --git a/monet/mn-display.c b/monet/mn-display.c
index 47eb48d..d76be90 100644
--- a/monet/mn-display.c
+++ b/monet/mn-display.c
@@ -22,7 +22,7 @@ enum {
 };
 
 MnDisplay*
-mn_display_new (gchar *theme_type)
+mn_display_new (MnThemeType *theme_type)
 {
   g_assert(theme_type != NULL);
 
@@ -93,14 +93,13 @@ mn_display_remove_stylesheet (MnDisplay *display, MnStylesheet *stylesheet)
 
 static void
 mn_display_get_property (GObject *object, guint property_id,
-                              GValue *value, GParamSpec *pspec)
+                         GValue *value, GParamSpec *pspec)
 {
   MnDisplayPrivate *priv = GET_PRIVATE (object);
 
   switch (property_id) {
   case PROP_THEME_TYPE:
-    g_free (priv->theme_type);
-    g_value_set_string (value, priv->theme_type);
+    g_value_set_object (value, priv->theme_type);
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -115,7 +114,9 @@ mn_display_set_property (GObject *object, guint property_id,
 
   switch (property_id) {
   case PROP_THEME_TYPE:
-    priv->theme_type = g_value_dup_string (value);
+    if (priv->theme_type != NULL)
+      g_object_unref (G_OBJECT (priv->theme_type));
+    priv->theme_type = g_value_dup_object (value);
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -147,10 +148,10 @@ mn_display_class_init (MnDisplayClass *klass)
   object_class->finalize = mn_display_finalize;
 
   g_object_class_install_property(object_class, PROP_THEME_TYPE,
-                                  g_param_spec_string ("theme-type",
+                                  g_param_spec_object ("theme-type",
                                                        "Theme Type",
                                                        "The type of theme that monet is handling.",
-                                                       NULL,
+                                                       MN_TYPE_THEME_TYPE,
                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 }
 
@@ -159,7 +160,8 @@ mn_display_init (MnDisplay *self)
 {
   MnDisplayPrivate *priv = GET_PRIVATE (self);
 
-  priv->theme_type = NULL;
+  if (priv->theme_type != NULL)
+    g_object_unref (G_OBJECT (priv->theme_type));
   priv->stylesheets = NULL;
 }
 
diff --git a/monet/mn-display.h b/monet/mn-display.h
index 156be20..79f87b5 100644
--- a/monet/mn-display.h
+++ b/monet/mn-display.h
@@ -33,7 +33,7 @@ typedef struct {
 
 GType mn_display_get_type (void);
 
-MnDisplay* mn_display_new (gchar *theme_type);
+MnDisplay* mn_display_new (MnThemeType *theme_type);
 
 const gchar* mn_display_get_theme_type (MnDisplay* display);
 
diff --git a/monet/mn-stylesheet.c b/monet/mn-stylesheet.c
index d575c13..04a90f8 100644
--- a/monet/mn-stylesheet.c
+++ b/monet/mn-stylesheet.c
@@ -10,8 +10,14 @@ G_DEFINE_TYPE (MnStylesheet, mn_stylesheet, G_TYPE_OBJECT)
 typedef struct _MnStylesheetPrivate MnStylesheetPrivate;
 typedef struct _MnStyle MnStyle;
 typedef struct _MnSelector MnSelector;
+typedef struct _MnSelectorItem MnSelectorItem;
 typedef struct _MnProperty MnProperty;
 
+typedef enum {
+  MN_SELECTOR_PARENT,
+  MN_SELECTOR_DIRECT_PARENT
+} MnSelectorType;
+
 struct _MnStylesheetPrivate {
   MnPriority priority;
   gchar *string;
@@ -30,8 +36,16 @@ struct _MnProperty {
 };
 
 struct _MnSelector {
-  gchar *identifier;
-  MnStyle *style;
+  MnStyle        *style;
+  MnSelectorItem *sel;
+};
+
+struct _MnSelectorItem {
+  MnSelectorType   type;
+  gchar           *identifier;
+  gchar          **classes;
+  gchar          **pseudo_classes;
+  MnSelectorItem  *next;
 };
 
 enum {
@@ -78,6 +92,26 @@ mn_stylesheet_style_free (MnStyle *style)
   g_slice_free (MnStyle, style);
 }
 
+static MnSelectorItem*
+mn_stylesheet_selector_item_new ()
+{
+  MnSelectorItem *selitem;
+
+  selitem = g_slice_new0 (MnSelectorItem);
+  selitem->type = MN_SELECTOR_PARENT;
+
+  return selitem;
+}
+
+static void
+mn_stylesheet_selector_item_free (MnSelectorItem *selitem)
+{
+  /* We do not own any of the strings. */
+  g_free (selitem->classes);
+  g_free (selitem->pseudo_classes);
+  g_slice_free (MnSelectorItem, selitem);
+}
+
 static MnSelector*
 mn_stylesheet_selector_new ()
 {
@@ -87,7 +121,17 @@ mn_stylesheet_selector_new ()
 static void
 mn_stylesheet_selector_free (MnSelector *selector)
 {
-  g_free (selector->identifier);
+  MnSelectorItem *sel_item;
+  MnSelectorItem *tmp;
+
+  sel_item = selector->sel;
+  while (sel_item)
+    {
+      tmp = sel_item;
+      sel_item = sel_item->next;
+      mn_stylesheet_selector_item_free (tmp);
+    }
+
   g_slice_free (MnSelector, selector);
 }
 
@@ -127,6 +171,7 @@ scan_complete_block (GScanner *scanner)
   gint brace = 0;
   gint paren = 0;
 
+  /* XXX: This does not search do non-matching brackets correctly. */
   /* Scan until we "ate" a complete block in curly brackets */
   while (!done)
     {
@@ -169,16 +214,18 @@ scan_block_to_semicolon (GScanner *scanner)
 {
   GTokenType token;
   GString *str;
+  gchar *cset_skip_characters = scanner->config->cset_skip_characters;
   gint curly = 0;
   gint brace = 0;
   gint paren = 0;
 
   str = g_string_new ("");
 
-  /* XXX: This does not keep whitespace in the correct format!
-   *      It also does not search do non-matching brackets correctly.
-   */
+  /* XXX: This does not search do non-matching brackets correctly. */
   token = g_scanner_peek_next_token (scanner);
+  /* We skipped any initial whitespace, and now keep going and keep any
+   * whitespace as is. */
+  scanner->config->cset_skip_characters = "";
   while ((token != ';' || curly < 0) && curly >= 0 && brace >= 0 && paren >= 0)
     {
       gchar *tmp;
@@ -190,23 +237,23 @@ scan_block_to_semicolon (GScanner *scanner)
         {
         case G_TOKEN_LEFT_PAREN:
           paren += 1;
-          g_string_append (str, " (");
+          g_string_append_c (str, '(');
           break;
         case G_TOKEN_RIGHT_PAREN:
           paren -= 1;
-          g_string_append (str, " )");
+          g_string_append_c (str, ')');
           break;
         case G_TOKEN_LEFT_BRACE:
           brace += 1;
-          g_string_append (str, " [");
+          g_string_append_c (str, '[');
           break;
         case G_TOKEN_RIGHT_BRACE:
           brace -= 1;
-          g_string_append (str, " ]");
+          g_string_append_c (str, ']');
           break;
         case G_TOKEN_LEFT_CURLY:
           curly += 1;
-          g_string_append (str, " {");
+          g_string_append_c (str, '{');
           break;
         case G_TOKEN_RIGHT_CURLY:
           curly -= 1;
@@ -214,16 +261,15 @@ scan_block_to_semicolon (GScanner *scanner)
             {
               /* Need to read in the token in this case. */
               g_scanner_get_next_token (scanner);
-              g_string_append (str, " }");
+              g_string_append_c (str, '}');
             }
           break;
         case G_TOKEN_IDENTIFIER:
-          g_string_append_c (str, ' ');
           g_string_append (str, scanner->value.v_string);
           break;
         case G_TOKEN_STRING:
           tmp = g_strescape (scanner->value.v_string, NULL);
-          g_string_append (str, " \"");
+          g_string_append (str, "\"");
           g_string_append (str, tmp);
           g_free (tmp);
           g_string_append_c (str, '"');
@@ -247,13 +293,31 @@ scan_block_to_semicolon (GScanner *scanner)
         case '+':
           g_string_append_c (str, '+');
           break;
+        case '/':
+          g_string_append_c (str, '/');
+          break;
+        case '\\':
+          g_string_append_c (str, '\\');
+          break;
+        case '@':
+          g_string_append_c (str, '@');
+          break;
+        case ' ':
+          g_string_append_c (str, ' ');
+          break;
+        case '\t':
+          g_string_append_c (str, '\t');
+          break;
+        case '\n':
+          g_string_append_c (str, '\n');
+          break;
         case G_TOKEN_INT:
-          tmp = g_strdup_printf (" %li", scanner->value.v_int);
+          tmp = g_strdup_printf ("%li", scanner->value.v_int);
           g_string_append (str, tmp);
           g_free (tmp);
           break;
         case G_TOKEN_FLOAT:
-          tmp = g_strdup_printf (" %f", scanner->value.v_float);
+          tmp = g_strdup_printf ("%f", scanner->value.v_float);
           g_string_append (str, tmp);
           g_free (tmp);
           break;
@@ -269,36 +333,201 @@ scan_block_to_semicolon (GScanner *scanner)
   if (token == ';')
     g_scanner_get_next_token (scanner);
 
+  /* Skip whitespace again. */
+  scanner->config->cset_skip_characters = cset_skip_characters;
+
   if (str->len == 0)
     {
       g_string_free (str, TRUE);
       return NULL;
     }
-  g_string_erase (str, 0, 1);
   return g_string_free (str, FALSE);
 }
 
 static GSList*
 mn_stylesheet_parse_selectors (MnStylesheet *stylesheet, GScanner *scanner)
 {
+  gchar *cset_skip_characters = scanner->config->cset_skip_characters;
+  gboolean numbers_2_int = scanner->config->numbers_2_int;
+  gboolean scan_symbols = scanner->config->scan_symbols;
+  gboolean scan_float = scanner->config->scan_float;
   GTokenType token;
+  GSList *selectors = NULL;
+  GSList *item;
   MnSelector *selector;
+  MnSelectorItem *selector_item;
+  gboolean new_selector = TRUE;
+  gboolean new_sel_item = TRUE;
+  enum {
+    SEL_IDENTIFIER,
+    SEL_CLASS,
+    SEL_PSEUDO_CLASS
+  } next_sel_type = SEL_IDENTIFIER;
 
-  token = g_scanner_get_next_token (scanner);
-  if (token != G_TOKEN_IDENTIFIER)
+  token = g_scanner_peek_next_token (scanner);
+  scanner->config->cset_skip_characters = "";
+  scanner->config->numbers_2_int = FALSE;
+  scanner->config->scan_symbols = FALSE;
+  scanner->config->scan_float = FALSE;
+
+  while (token != G_TOKEN_LEFT_CURLY)
     {
-      g_scanner_unexp_token (scanner, G_TOKEN_IDENTIFIER, NULL, NULL,
-                             "selector",
-                             "Expected an identifier that is part of a stylesheet.", TRUE);
-      scan_complete_block (scanner);
-      return NULL;
+      gchar *identifier;
+      token = g_scanner_get_next_token (scanner);
+
+      switch (token)
+        {
+        case '*':
+        case G_TOKEN_IDENTIFIER:
+          if (token == '*')
+            identifier = (gchar*) g_intern_string ((const gchar*) '*');
+          else
+            identifier = (gchar*) g_intern_string (scanner->value.v_string);
+
+          if (new_selector)
+            {
+              selector = mn_stylesheet_selector_new ();
+              selectors = g_slist_append (selectors, selector);
+              new_selector = FALSE;
+            }
+          if (new_sel_item)
+            {
+              selector_item = mn_stylesheet_selector_item_new ();
+              selector_item->next = selector->sel;
+              selector->sel = selector_item;
+              new_sel_item = FALSE;
+            }
+
+          switch (next_sel_type)
+            {
+            case SEL_IDENTIFIER:
+              g_assert (selector_item->identifier == NULL);
+              selector_item->identifier = identifier;
+              break;
+            case SEL_CLASS:
+              {
+                gint length;
+                gchar **tmp = selector_item->classes;
+                length = 0;
+                if (tmp)
+                  {
+                    while (*tmp != NULL)
+                      {
+                        length += 1;
+                        tmp += 1;
+                      }
+                  }
+                tmp = g_malloc0 (sizeof(gchar*) * (length + 2));
+
+                if (selector_item->classes)
+                  {
+                    memcpy (tmp, selector_item->classes, length * sizeof(gchar*));
+                    g_free (selector_item->classes);
+                  }
+                selector_item->classes = tmp;
+                selector_item->classes[length] = identifier;
+              }
+              break;
+            case SEL_PSEUDO_CLASS:
+              {
+                gint length;
+                gchar **tmp = selector_item->pseudo_classes;
+                length = 0;
+                if (tmp)
+                  {
+                    while (*tmp != NULL)
+                      {
+                        length += 1;
+                        tmp += 1;
+                      }
+                  }
+                tmp = g_malloc0 (sizeof(gchar*) * (length + 2));
+
+                if (selector_item->pseudo_classes)
+                  {
+                    memcpy (tmp, selector_item->pseudo_classes, length * sizeof(gchar*));
+                    g_free (selector_item->pseudo_classes);
+                  }
+                selector_item->pseudo_classes = tmp;
+                selector_item->pseudo_classes[length] = identifier;
+              }
+              break;
+            }
+
+          next_sel_type = SEL_IDENTIFIER;
+          break;
+        case '.':
+          if (next_sel_type != SEL_IDENTIFIER)
+            {
+              g_scanner_warn (scanner, "Got a stray dot.");
+              goto BAIL_PARSE_SELECTORS;
+            }
+          next_sel_type = SEL_CLASS;
+          break;
+        case ':':
+          if (next_sel_type != SEL_IDENTIFIER)
+            {
+              g_scanner_warn (scanner, "Got a stray colon.");
+              goto BAIL_PARSE_SELECTORS;
+            }
+          next_sel_type = SEL_PSEUDO_CLASS;
+          break;
+        case '>':
+          new_sel_item = TRUE;
+          selector_item->type = MN_SELECTOR_DIRECT_PARENT;
+          break;
+        case ',':
+          if (new_selector)
+            {
+              g_scanner_warn (scanner, "Ignoring stray ',' in selector");
+              goto BAIL_PARSE_SELECTORS;
+            }
+          new_selector = TRUE;
+          break;
+        case ' ':
+        case '\t':
+        case '\n':
+          if (next_sel_type != SEL_IDENTIFIER)
+            {
+              g_scanner_warn (scanner, "Got a stray dot.");
+              goto BAIL_PARSE_SELECTORS;
+            }
+          new_sel_item = TRUE;
+          break;
+        default:
+          g_scanner_warn (scanner, "Error while parsing selector");
+          goto BAIL_PARSE_SELECTORS;
+        }
+      token = g_scanner_peek_next_token (scanner);
     }
-  else
+
+  scanner->config->cset_skip_characters = cset_skip_characters;
+  scanner->config->numbers_2_int = numbers_2_int;
+  scanner->config->scan_symbols = scan_symbols;
+  scanner->config->scan_float = scan_float;
+  return selectors;
+
+BAIL_PARSE_SELECTORS:
+
+  item = selectors;
+  while (item)
     {
-      selector = mn_stylesheet_selector_new ();
-      selector->identifier = g_strdup (scanner->value.v_identifier);
-      return g_slist_append (NULL, selector);
+      selector = (MnSelector*) item->data;
+      mn_stylesheet_selector_free (selector);
+      item = item->next;
     }
+  g_slist_free (selectors);
+
+  g_scanner_unexp_token (scanner, G_TOKEN_IDENTIFIER, NULL, NULL,
+                         "selector",
+                         "Expected an identifier that is part of a selector.",
+                         TRUE);
+
+  scanner->config->cset_skip_characters = cset_skip_characters;
+  scanner->config->numbers_2_int = numbers_2_int;
+  scanner->config->scan_symbols = scan_symbols;
+  scanner->config->scan_float = scan_float;
+  return NULL;
 }
 
 static MnStyle*
@@ -356,7 +585,6 @@ mn_stylesheet_parse_style (MnStylesheet *stylesheet, GScanner *scanner)
           property = mn_stylesheet_property_new ();
           property->identifier = identifier;
           property->value = value;
-          g_print ("Adding property '%s' with value '%s'\n", identifier, value);
           style->properties = g_slist_append(style->properties, property);
         }
       token = g_scanner_get_next_token (scanner);
diff --git a/monet/mn-theme-type.c b/monet/mn-theme-type.c
new file mode 100644
index 0000000..43fd09a
--- /dev/null
+++ b/monet/mn-theme-type.c
@@ -0,0 +1,185 @@
+#include "mn-theme-type.h"
+
+G_DEFINE_TYPE (MnThemeType, mn_theme_type, G_TYPE_OBJECT)
+
+#define GET_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), MN_TYPE_THEME_TYPE, MnThemeTypePrivate))
+
+typedef struct _MnThemeTypePrivate MnThemeTypePrivate;
+
+struct _MnThemeTypePrivate {
+  GHashTable *property_pool;
+  GHashTable *alias_pool;
+  gchar *name;
+};
+
+enum {
+  PROP_NAME = 1
+};
+
+static GSList *mn_theme_types = NULL;
+
+MnThemeType*
+mn_theme_type_find (gchar *name)
+{
+  GSList *theme_type = mn_theme_types;
+
+  while (theme_type != NULL)
+    {
+      MnThemeType *mn_theme_type = (MnThemeType*) theme_type->data;
+
+      if (g_str_equal (mn_theme_type_get_name (mn_theme_type), name))
+        return mn_theme_type;
+
+      theme_type = theme_type->next;
+    }
+  return NULL;
+}
+
+const gchar*
+mn_theme_type_get_name (MnThemeType* theme_type)
+{
+  MnThemeTypePrivate *priv = GET_PRIVATE (theme_type);
+
+  return priv->name;
+}
+
+void
+mn_theme_type_install_property (MnThemeType      *theme_type,
+                                gchar            *property,
+                                GStrv             aliases,
+                                MnPropertyInfo   *info)
+{
+  MnThemeTypePrivate *priv = GET_PRIVATE (theme_type);
+  gchar *alias;
+
+  g_return_if_fail (property != NULL);
+  g_return_if_fail (info != NULL);
+
+  property = (gchar*) g_intern_string ((const gchar*) property);
+  g_hash_table_insert (priv->property_pool, property, info);
+
+  if (aliases == NULL)
+    return;
+
+  alias = *aliases;
+  aliases += 1;
+  while (alias)
+    {
+      alias = (gchar*) g_intern_string ((const gchar*) alias);
+      g_hash_table_insert (priv->alias_pool, alias, property);
+
+      alias = *aliases;
+      aliases += 1;
+    }
+}
+
+
+static void
+mn_theme_type_get_property (GObject *object, guint property_id,
+                              GValue *value, GParamSpec *pspec)
+{
+  MnThemeTypePrivate *priv = GET_PRIVATE (object);
+
+  switch (property_id) {
+  case PROP_NAME:
+    g_value_set_string (value, priv->name);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+  }
+}
+
+static void
+mn_theme_type_set_property (GObject *object, guint property_id,
+                              const GValue *value, GParamSpec *pspec)
+{
+  MnThemeTypePrivate *priv = GET_PRIVATE (object);
+
+  switch (property_id) {
+  case PROP_NAME:
+    g_free (priv->name);
+    priv->name = g_value_dup_string (value);
+    g_assert (priv->name != NULL);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+  }
+}
+
+static void
+mn_theme_type_constructed (GObject *object)
+{
+  mn_theme_types = g_slist_append (mn_theme_types, object);
+}
+
+static void
+mn_theme_type_dispose (GObject *object)
+{
+  G_OBJECT_CLASS (mn_theme_type_parent_class)->dispose (object);
+}
+
+static void
+mn_theme_type_finalize (GObject *object)
+{
+  MnThemeTypePrivate *priv = GET_PRIVATE (object);
+
+  mn_theme_types = g_slist_remove (mn_theme_types, object);
+
+  g_object_unref (G_OBJECT (priv->property_pool));
+  g_object_unref (G_OBJECT (priv->alias_pool));
+  g_free (priv->name);
+
+  G_OBJECT_CLASS (mn_theme_type_parent_class)->finalize (object);
+}
+
+static void
+mn_theme_type_class_init (MnThemeTypeClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (MnThemeTypePrivate));
+
+  object_class->get_property = mn_theme_type_get_property;
+  object_class->set_property = mn_theme_type_set_property;
+  object_class->constructed = mn_theme_type_constructed;
+  object_class->dispose = mn_theme_type_dispose;
+  object_class->finalize = mn_theme_type_finalize;
+
+  g_object_class_install_property(object_class, PROP_NAME,
+                                  g_param_spec_string ("name",
+                                                       "The theme type name",
+                                                       "A unique identifier for the theme type.",
+                                                       NULL,
+                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+destroy_info (MnPropertyInfo *info)
+{
+  if (info->free_func)
+    info->free_func (info);
+}
+
+static void
+mn_theme_type_init (MnThemeType *self)
+{
+  MnThemeTypePrivate *priv = GET_PRIVATE (self);
+
+  priv->name = NULL;
+  priv->property_pool = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+                                               NULL, (GDestroyNotify) destroy_info);
+  priv->alias_pool = g_hash_table_new (g_direct_hash, g_direct_equal);
+}
+
+MnThemeType*
+mn_theme_type_new (gchar *name)
+{
+  g_assert(name != NULL);
+
+  return g_object_new (MN_TYPE_THEME_TYPE,
+                       "name", name,
+                       NULL);
+}
+
+
diff --git a/monet/mn-theme-type.h b/monet/mn-theme-type.h
new file mode 100644
index 0000000..b692561
--- /dev/null
+++ b/monet/mn-theme-type.h
@@ -0,0 +1,66 @@
+#ifndef _MN_THEME_TYPE
+#define _MN_THEME_TYPE
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MN_TYPE_THEME_TYPE mn_theme_type_get_type()
+
+#define MN_THEME_TYPE(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), MN_TYPE_THEME_TYPE, MnThemeType))
+
+#define MN_THEME_TYPE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), MN_TYPE_THEME_TYPE, MnThemeTypeClass))
+
+#define MN_IS_THEME_TYPE(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MN_TYPE_THEME_TYPE))
+
+#define MN_IS_THEME_TYPE_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), MN_TYPE_THEME_TYPE))
+
+#define MN_THEME_TYPE_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), MN_TYPE_THEME_TYPE, MnThemeTypeClass))
+
+typedef struct {
+  GObject parent;
+} MnThemeType;
+
+typedef struct {
+  GObjectClass parent_class;
+} MnThemeTypeClass;
+
+typedef struct _MnPropertyInfo MnPropertyInfo;
+
+#include "mn-stylesheet.h"
+#include "mn-context.h"
+
+/* XXX: Do we need the stylesheet here to open files? */
+typedef gboolean (*MnPropertyParser) (MnPropertyInfo       *info,
+                                      const gchar          *alias,
+                                      MnContext            *context,
+                                      const GString        *rc_string,
+                                      GValue               *property_value);
+
+struct _MnPropertyInfo {
+  GType             property_type;
+  MnPropertyParser  parser;
+  GDestroyNotify    free_func;
+};
+
+GType mn_theme_type_get_type (void);
+
+MnThemeType* mn_theme_type_find (gchar *name);
+MnThemeType* mn_theme_type_new (gchar *name);
+
+void mn_theme_type_install_property (MnThemeType      *theme_type,
+                                     gchar            *property,
+                                     GStrv             aliases,
+                                     MnPropertyInfo   *info);
+
+const gchar* mn_theme_type_get_name (MnThemeType* theme_type);
+
+G_END_DECLS
+
+#endif /* _MN_THEME_TYPE */
+
diff --git a/monet/monet.h b/monet/monet.h
index 1a0feff..df990d9 100644
--- a/monet/monet.h
+++ b/monet/monet.h
@@ -1,4 +1,5 @@
 #include <glib-object.h>
+#include "mn-theme-type.h"
 #include "mn-enum-types.h"
 #include "mn-display.h"
 #include "mn-stylesheet.h"
@@ -8,7 +9,4 @@
 #include "mn-types.h"
 
 void monet_init (gint *argc, gchar ***argv);
-void monet_install_property_parser (GParamSpec        *pspec,
-                                    GSList            *aliases,
-                                    MnPropertyParser   parser);
 



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