--- gtk+.orig/gtk/gtkrc.c	2005-09-14 15:17:17.000000000 +0200
+++ gtk+/gtk/gtkrc.c	2005-09-17 01:00:25.000000000 +0200
@@ -66,9 +66,19 @@
 typedef struct _GtkRcNode   GtkRcNode;
 typedef struct _GtkRcFile   GtkRcFile;
 
+typedef struct
+{
+  gboolean is_class;
+  GPatternSpec * pspec;
+} GtkRcSetPSpecList;
+
 struct _GtkRcSet
 {
+  GtkPathType type;
+  
   GPatternSpec *pspec;
+  GSList * widget_class_pspecs;
+
   GtkRcStyle *rc_style;
   gint priority;
 };
@@ -196,6 +206,15 @@
 static gint	   gtk_rc_properties_cmp	     (gconstpointer    bsearch_node1,
 						      gconstpointer    bsearch_node2);
 
+static void        gtk_rc_set_set_pattern            (GtkRcSet        *rc_set,
+                                                      const gchar     *pattern,
+                                                      GtkPathType      type);
+static void        gtk_rc_set_free                   (GtkRcSet        *rc_set);
+static gboolean    gtk_rc_set_match                  (GtkRcSet        *rc_set,
+                                                      gint             path_length,
+                                                      const gchar     *path,
+                                                      const gchar     *path_reversed);
+
 static gpointer parent_class = NULL;
 
 static const GScannerConfig gtk_rc_scanner_config =
@@ -1274,8 +1293,7 @@
       GtkRcSet *rc_set;
 
       rc_set = slist->data;
-      g_pattern_spec_free (rc_set->pspec);
-      g_free (rc_set);
+      gtk_rc_set_free (rc_set);
 
       slist = slist->next;
     }
@@ -1575,7 +1593,7 @@
       rc_set = sets->data;
       sets = sets->next;
 
-      if (g_pattern_match (rc_set->pspec, path_length, path, path_reversed))
+      if (gtk_rc_set_match (rc_set, path_length, path, path_reversed))
 	rc_styles = g_slist_append (rc_styles, rc_set);
     }
   
@@ -1671,13 +1689,12 @@
   
   if (context->rc_sets_widget_class)
     {
-      gchar *path, *path_reversed;
+      gchar *path;
       guint path_length;
 
-      gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
-      rc_styles = gtk_rc_styles_match (rc_styles, context->rc_sets_widget_class, path_length, path, path_reversed);
+      gtk_widget_class_path (widget, &path_length, &path, NULL);
+      rc_styles = gtk_rc_styles_match (rc_styles, context->rc_sets_widget_class, path_length, path, NULL);
       g_free (path);
-      g_free (path_reversed);
     }
 
   if (context->rc_sets_class)
@@ -1786,15 +1803,11 @@
   
   if (class_path && context->rc_sets_widget_class)
     {
-      gchar *path_reversed;
       guint path_length;
 
       path_length = strlen (class_path);
-      path_reversed = g_strdup (class_path);
-      g_strreverse (path_reversed);
 
-      rc_styles = gtk_rc_styles_match (rc_styles, context->rc_sets_widget_class, path_length, class_path, path_reversed);
-      g_free (path_reversed);
+      rc_styles = gtk_rc_styles_match (rc_styles, context->rc_sets_widget_class, path_length, class_path, NULL);
     }
 
   if (type != G_TYPE_NONE && context->rc_sets_class)
@@ -1828,7 +1841,8 @@
 static GSList *
 gtk_rc_add_rc_sets (GSList      *slist,
 		    GtkRcStyle  *rc_style,
-		    const gchar *pattern)
+		    const gchar *pattern,
+		    GtkPathType  path_type)
 {
   GtkRcStyle *new_style;
   GtkRcSet *rc_set;
@@ -1844,7 +1858,7 @@
     new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
   
   rc_set = g_new (GtkRcSet, 1);
-  rc_set->pspec = g_pattern_spec_new (pattern);
+  gtk_rc_set_set_pattern (rc_set, pattern, path_type);
   rc_set->rc_style = rc_style;
   
   return g_slist_prepend (slist, rc_set);
@@ -1861,7 +1875,7 @@
 
   context = gtk_rc_context_get (gtk_settings_get_default ());
   
-  context->rc_sets_widget = gtk_rc_add_rc_sets (context->rc_sets_widget, rc_style, pattern);
+  context->rc_sets_widget = gtk_rc_add_rc_sets (context->rc_sets_widget, rc_style, pattern, GTK_PATH_WIDGET);
 }
 
 void
@@ -1875,7 +1889,7 @@
 
   context = gtk_rc_context_get (gtk_settings_get_default ());
   
-  context->rc_sets_widget_class = gtk_rc_add_rc_sets (context->rc_sets_widget_class, rc_style, pattern);
+  context->rc_sets_widget_class = gtk_rc_add_rc_sets (context->rc_sets_widget_class, rc_style, pattern, GTK_PATH_WIDGET_CLASS);
 }
 
 void
@@ -1889,7 +1903,7 @@
 
   context = gtk_rc_context_get (gtk_settings_get_default ());
   
-  context->rc_sets_class = gtk_rc_add_rc_sets (context->rc_sets_class, rc_style, pattern);
+  context->rc_sets_class = gtk_rc_add_rc_sets (context->rc_sets_class, rc_style, pattern, GTK_PATH_CLASS);
 }
 
 GScanner*
@@ -3612,7 +3626,7 @@
 	}
 
       rc_set = g_new (GtkRcSet, 1);
-      rc_set->pspec = g_pattern_spec_new (pattern);
+      gtk_rc_set_set_pattern (rc_set, pattern, path_type);
       rc_set->rc_style = rc_style;
       rc_set->priority = priority;
 
@@ -3917,6 +3931,287 @@
   return G_TOKEN_NONE;
 }
 
+
+static void
+gtk_rc_set_set_pattern (GtkRcSet * rc_set, const gchar * pattern, GtkPathType type)
+{
+  rc_set->type = type;
+  rc_set->pspec = NULL;
+  rc_set->widget_class_pspecs = NULL;
+  
+  if (rc_set->type != GTK_PATH_WIDGET_CLASS)
+    {
+      rc_set->pspec = g_pattern_spec_new (pattern);
+    }
+  else
+    {
+      GtkRcSetPSpecList * list_pspec;
+      GPatternSpec * pspec;
+      const gchar * cur_pos = pattern;
+      const gchar * class_start_pos;
+      const gchar * class_end_pos;
+      gchar * sub_pattern;
+      g_print ("adding widget_class: '%s'\n", pattern);
+      
+      /* search for first < */
+      class_start_pos = strchr (pattern, '<');
+      
+      while ((class_start_pos = strchr (cur_pos, '<')) && (class_end_pos = strchr (class_start_pos, '>')))
+        {
+          /* if the "class" is not at the begginning, or if there is only a dot in front of it. */
+          if ((class_start_pos != cur_pos) && (!((class_start_pos - 1 == cur_pos) && (*cur_pos == '.'))))
+            {
+              /* there is a raw pspec that needs to be added */
+              const gchar * pattern_end_pos = class_start_pos - 1;
+              const gchar * pattern_start_pos = cur_pos;
+              
+              /* cut of the last dot, if there is one */
+              if (*pattern_end_pos == '.')
+                pattern_end_pos -= 1;
+              /* cut of the first dot */
+              if (*pattern_start_pos == '.')
+                pattern_start_pos += 1;
+              
+              sub_pattern = g_strndup (pattern_start_pos, pattern_end_pos - pattern_start_pos + 1);
+              g_print ("pattern: '%s'\n", sub_pattern);
+              pspec = g_pattern_spec_new (sub_pattern);
+              g_free (sub_pattern);
+              
+              list_pspec = g_new (GtkRcSetPSpecList, 1);
+              list_pspec->is_class = FALSE;
+              list_pspec->pspec = pspec;
+              
+              rc_set->widget_class_pspecs = g_slist_append (rc_set->widget_class_pspecs, list_pspec);
+            }
+          
+          /* The < > need to be removed from the string. */
+          sub_pattern = g_strndup (class_start_pos + 1, class_end_pos - class_start_pos - 1);
+          g_print ("class: '%s'\n", sub_pattern);
+          pspec = g_pattern_spec_new (sub_pattern);
+          g_free (sub_pattern);
+          
+          list_pspec = g_new (GtkRcSetPSpecList, 1);
+          list_pspec->is_class = TRUE;
+          list_pspec->pspec = pspec;
+          
+          rc_set->widget_class_pspecs = g_slist_append (rc_set->widget_class_pspecs, list_pspec);
+          
+          cur_pos = class_end_pos + 1;
+        }
+      
+      /* add the rest, if anything is left */
+      if (strlen (cur_pos) > 0)
+        {
+          /* cut of dot if there is one. */
+          if (*cur_pos == '.')
+            cur_pos += 1;
+          
+          /* it may happen that cur_pos = "" but that is not a big deal. */
+          g_print ("pattern: '%s'\n", cur_pos);
+          pspec = g_pattern_spec_new (cur_pos);
+          
+          list_pspec = g_new (GtkRcSetPSpecList, 1);
+          list_pspec->is_class = FALSE;
+          list_pspec->pspec = pspec;
+          
+          rc_set->widget_class_pspecs = g_slist_append (rc_set->widget_class_pspecs, list_pspec);
+        }
+    }
+}
+
+static void
+free_widget_class_pspec (gpointer data, gpointer user_data)
+{
+  GtkRcSetPSpecList * pspec_list = data;
+  
+  g_pattern_spec_free (pspec_list->pspec);
+  g_free(pspec_list);
+}
+
+static void
+gtk_rc_set_free (GtkRcSet * rc_set)
+{
+  g_assert (rc_set != NULL);
+  
+  if (rc_set->pspec)
+    g_pattern_spec_free (rc_set->pspec);
+  
+  g_slist_foreach (rc_set->widget_class_pspecs, free_widget_class_pspec, NULL);
+  g_slist_free (rc_set->widget_class_pspecs);
+  
+  g_free (rc_set);
+}
+
+static gboolean
+match_class (GType type, GPatternSpec * pspec)
+{
+  while (type)
+    {
+      const gchar *path;
+      guint path_length;
+
+      path = g_type_name (type);
+      path_length = strlen (path);
+      
+      if (g_pattern_match (pspec, path_length, path, NULL))
+        return TRUE;
+      
+      type = g_type_parent (type);
+    }
+  
+  return FALSE;
+}
+
+static gboolean
+match_widget_class_recursive (GSList * list, gchar * path)
+{
+  GtkRcSetPSpecList * pspec_list;
+  
+  /* break out if we cannot match anymore. */
+  if (list == NULL)
+    {
+      if (strlen (path) > 0)
+        return FALSE;
+      else
+        return TRUE;
+    }
+  
+  /* there are two possibilities:
+      1. The next pattern should match the class.
+      2. First normal matching */
+  
+  pspec_list = list->data;
+  
+  if (pspec_list->is_class)
+    {
+      gchar * class_end_pos = strchr (path, '.');
+      
+      if (class_end_pos == NULL)
+        {
+          if (!match_class (g_type_from_name (path), pspec_list->pspec))
+            {
+              return FALSE;
+            }
+          else
+            {
+              return match_widget_class_recursive (g_slist_next (list), "");
+            }
+        }
+      else
+        {
+          *class_end_pos = '\0';
+          if (!match_class (g_type_from_name (path), pspec_list->pspec))
+            {
+              *class_end_pos = '.';
+              return FALSE;
+            }
+          else
+            {
+              *class_end_pos = '.';
+              return match_widget_class_recursive (g_slist_next (list), class_end_pos + 1);
+            }
+        }
+    }
+  else
+    {
+      GtkRcSetPSpecList * class_pspec_list;
+      gchar * class_start;
+      gchar * class_end;
+      gboolean result = FALSE;
+      
+      /* two possibilities:
+         there is a class for matching next. Or there is nothing. */
+      if (g_slist_next (list) == NULL)
+        {
+          /* just compare the param string. */
+          return g_pattern_match (pspec_list->pspec, strlen (path), path, NULL);
+        }
+      class_pspec_list = (g_slist_next (list))->data;
+      
+      g_assert (class_pspec_list->is_class == TRUE);
+      
+      
+      class_start = path;
+      class_end = strchr (class_start, '.');
+      
+      while (TRUE)
+        {
+          gchar * class;
+          
+          if (class_end != NULL)
+            class = g_strndup (class_start, class_end - class_start);
+          else
+            class = g_strdup (class_start);
+          
+          if (match_class (g_type_from_name (class), class_pspec_list->pspec))
+            {
+              /* this fits, so we should try if the pattern in front of us fits too. */
+              gchar * pattern = NULL;
+              
+              /* If this is not the first class, there is a dot which needs to be ignored. */
+              if (class_start > path)
+                pattern = g_strndup (path, class_start - path - 1);
+              else
+                pattern = g_strndup (path, class_start - path);
+              
+              if (pattern == NULL)
+                pattern = g_strdup ("");
+              
+              if (g_pattern_match (pspec_list->pspec, strlen (pattern), pattern, NULL))
+                {
+                  /* pattern matches, yay so go on recursive, and hope ... */
+                  if (class_end != NULL)
+                      result = match_widget_class_recursive (g_slist_next(g_slist_next (list)), class_end + 1);
+                  else
+                    result = match_widget_class_recursive (g_slist_next(g_slist_next (list)), "");
+                }
+                
+                g_free (pattern);
+            }
+          
+          g_free (class);
+          
+          if (result)
+            return TRUE;
+          
+          /* get next class in path, or break out */
+          if (class_end != NULL)
+            {
+              class_start = class_end + 1;
+              class_end = strchr (class_start, '.');
+            }
+          else
+            {
+              /* we reached the end and found nothing. */
+              return FALSE;
+            }
+        }
+    }
+}
+
+static gboolean
+gtk_rc_set_match (GtkRcSet    * rc_set,
+                  gint          path_length,
+                  const gchar * path,
+                  const gchar * path_reversed)
+{
+  if (rc_set->type != GTK_PATH_WIDGET_CLASS)
+    {
+      /* just match this. */
+      return g_pattern_match (rc_set->pspec, path_length, path, path_reversed);
+    }
+  else
+    {
+      gchar * real_path = g_strdup (path);
+      gboolean result;
+      
+      result = match_widget_class_recursive (rc_set->widget_class_pspecs, (gchar*) path);
+      
+      g_free (real_path);
+      return result;
+    }
+}
+
 #ifdef G_OS_WIN32
 
 /* DLL ABI stability backward compatibility versions */
