]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcssselector.c
filechooserbutton: Add tests for unselect_all()
[~andy/gtk] / gtk / gtkcssselector.c
index a6b6947a9ba09aad5539252cd433ec8dedbeeefa..216090faaddccaeba251026712d5066ddac2c63e 100644 (file)
@@ -195,6 +195,19 @@ gtk_css_selector_tree_get_sibling (const GtkCssSelectorTree *tree)
   return gtk_css_selector_tree_at_offset (tree, tree->sibling_offset);
 }
 
+static void
+gtk_css_selector_tree_match_previous (const GtkCssSelectorTree *tree,
+                                     const GtkCssMatcher *matcher,
+                                     GHashTable *res)
+{
+  const GtkCssSelectorTree *prev;
+
+  for (prev = gtk_css_selector_tree_get_previous (tree);
+       prev != NULL;
+       prev = gtk_css_selector_tree_get_sibling (prev))
+    gtk_css_selector_tree_match (prev, matcher, res);
+}
+
 static GtkCssChange
 gtk_css_selector_tree_get_previous_change (const GtkCssSelectorTree *tree,
                                           const GtkCssMatcher      *matcher)
@@ -242,16 +255,12 @@ gtk_css_selector_descendant_tree_match (const GtkCssSelectorTree *tree,
                                        GHashTable *res)
 {
   GtkCssMatcher ancestor;
-  const GtkCssSelectorTree *prev;
 
   while (_gtk_css_matcher_get_parent (&ancestor, matcher))
     {
       matcher = &ancestor;
 
-      for (prev = gtk_css_selector_tree_get_previous (tree);
-          prev != NULL;
-          prev = gtk_css_selector_tree_get_sibling (prev))
-       gtk_css_selector_tree_match (prev, matcher, res);
+      gtk_css_selector_tree_match_previous (tree, matcher, res);
 
       /* any matchers are dangerous here, as we may loop forever, but
         we can terminate now as all possible matches have already been added */
@@ -338,15 +347,11 @@ gtk_css_selector_child_tree_match (const GtkCssSelectorTree *tree,
                                   GHashTable *res)
 {
   GtkCssMatcher parent;
-  const GtkCssSelectorTree *prev;
 
   if (!_gtk_css_matcher_get_parent (&parent, matcher))
     return;
 
-  for (prev = gtk_css_selector_tree_get_previous (tree);
-       prev != NULL;
-       prev = gtk_css_selector_tree_get_sibling (prev))
-    gtk_css_selector_tree_match (prev, &parent, res);
+  gtk_css_selector_tree_match_previous (tree, &parent, res);
 }
 
 
@@ -426,16 +431,12 @@ gtk_css_selector_sibling_tree_match (const GtkCssSelectorTree *tree,
                                     GHashTable *res)
 {
   GtkCssMatcher previous;
-  const GtkCssSelectorTree *prev;
 
   while (_gtk_css_matcher_get_previous (&previous, matcher))
     {
       matcher = &previous;
 
-      for (prev = gtk_css_selector_tree_get_previous (tree);
-          prev != NULL;
-          prev = gtk_css_selector_tree_get_sibling (prev))
-       gtk_css_selector_tree_match (prev, matcher, res);
+      gtk_css_selector_tree_match_previous (tree, matcher, res);
 
       /* any matchers are dangerous here, as we may loop forever, but
         we can terminate now as all possible matches have already been added */
@@ -524,17 +525,13 @@ gtk_css_selector_adjacent_tree_match (const GtkCssSelectorTree *tree,
                                      GHashTable *res)
 {
   GtkCssMatcher previous;
-  const GtkCssSelectorTree *prev;
 
   if (!_gtk_css_matcher_get_previous (&previous, matcher))
     return;
 
   matcher = &previous;
 
-  for (prev = gtk_css_selector_tree_get_previous (tree);
-       prev != NULL;
-       prev = gtk_css_selector_tree_get_sibling (prev))
-    gtk_css_selector_tree_match (prev, matcher, res);
+  gtk_css_selector_tree_match_previous (tree, matcher, res);
 }
 
 static GtkCssChange
@@ -612,7 +609,7 @@ gtk_css_selector_any_tree_match (const GtkCssSelectorTree *tree,
                                 const GtkCssMatcher  *matcher,
                                 GHashTable *res)
 {
-  const GtkCssSelectorTree *prev, *prev2;
+  const GtkCssSelectorTree *prev;
 
   gtk_css_selector_tree_found_match (tree, res);
 
@@ -622,12 +619,7 @@ gtk_css_selector_any_tree_match (const GtkCssSelectorTree *tree,
     {
       if (prev->selector.class == &GTK_CSS_SELECTOR_DESCENDANT &&
          _gtk_css_matcher_has_regions (matcher))
-       {
-         for (prev2 = gtk_css_selector_tree_get_previous (prev);
-              prev2 != NULL;
-              prev2 = gtk_css_selector_tree_get_sibling (prev2))
-           gtk_css_selector_tree_match (prev2, matcher, res);
-       }
+       gtk_css_selector_tree_match_previous (prev, matcher, res);
 
       gtk_css_selector_tree_match (prev, matcher, res);
     }
@@ -690,18 +682,77 @@ static const GtkCssSelectorClass GTK_CSS_SELECTOR_ANY = {
 
 /* NAME */
 
+typedef struct {
+  GType type;
+  const char *name;
+} TypeReference;
+
+static GHashTable *type_refs_ht = NULL;
+static guint type_refs_last_serial = 0;
+
+static TypeReference *
+get_type_reference (const char *name)
+{
+  TypeReference *ref;
+
+
+  if (type_refs_ht == NULL)
+    type_refs_ht = g_hash_table_new (g_str_hash, g_str_equal);
+
+  ref = g_hash_table_lookup (type_refs_ht, name);
+
+  if (ref != NULL)
+    return ref;
+
+  ref = g_slice_new (TypeReference);
+  ref->name = g_intern_string (name);
+  ref->type = g_type_from_name (ref->name);
+
+  g_hash_table_insert (type_refs_ht,
+                      (gpointer)ref->name, ref);
+
+  return ref;
+}
+
+static void
+update_type_references (void)
+{
+  GHashTableIter iter;
+  guint serial;
+  gpointer value;
+
+  serial = g_type_get_type_registration_serial ();
+
+  if (serial == type_refs_last_serial)
+    return;
+
+  type_refs_last_serial = serial;
+
+  if (type_refs_ht == NULL)
+    return;
+
+  g_hash_table_iter_init (&iter, type_refs_ht);
+  while (g_hash_table_iter_next (&iter,
+                                NULL, &value))
+    {
+      TypeReference *ref = value;
+      if (ref->type == G_TYPE_INVALID)
+       ref->type = g_type_from_name (ref->name);
+    }
+}
+
 static void
 gtk_css_selector_name_print (const GtkCssSelector *selector,
                              GString              *string)
 {
-  g_string_append (string, selector->data);
+  g_string_append (string, ((TypeReference *)selector->data)->name);
 }
 
 static gboolean
 gtk_css_selector_name_match (const GtkCssSelector *selector,
                              const GtkCssMatcher  *matcher)
 {
-  if (!_gtk_css_matcher_has_name (matcher, selector->data))
+  if (!_gtk_css_matcher_has_type (matcher, ((TypeReference *)selector->data)->type))
     return FALSE;
 
   return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher);
@@ -712,17 +763,12 @@ gtk_css_selector_name_tree_match (const GtkCssSelectorTree *tree,
                                  const GtkCssMatcher  *matcher,
                                  GHashTable *res)
 {
-  const GtkCssSelectorTree *prev;
-
-  if (!_gtk_css_matcher_has_name (matcher, tree->selector.data))
+  if (!_gtk_css_matcher_has_type (matcher, ((TypeReference *)tree->selector.data)->type))
     return;
 
   gtk_css_selector_tree_found_match (tree, res);
 
-  for (prev = gtk_css_selector_tree_get_previous (tree);
-       prev != NULL;
-       prev = gtk_css_selector_tree_get_sibling (prev))
-    gtk_css_selector_tree_match (prev, matcher, res);
+  gtk_css_selector_tree_match_previous (tree, matcher, res);
 }
 
 static GtkCssChange
@@ -731,7 +777,7 @@ gtk_css_selector_name_tree_get_change (const GtkCssSelectorTree *tree,
 {
   GtkCssChange change, previous_change;
 
-  if (!_gtk_css_matcher_has_name (matcher, tree->selector.data))
+  if (!_gtk_css_matcher_has_type (matcher, ((TypeReference *)tree->selector.data)->type))
     return 0;
 
   change = 0;
@@ -758,7 +804,8 @@ static int
 gtk_css_selector_name_compare_one (const GtkCssSelector *a,
                                   const GtkCssSelector *b)
 {
-  return strcmp (a->data, b->data);
+  return strcmp (((TypeReference *)a->data)->name,
+                ((TypeReference *)b->data)->name);
 }
 
 static const GtkCssSelectorClass GTK_CSS_SELECTOR_NAME = {
@@ -803,7 +850,7 @@ gtk_css_selector_region_tree_match (const GtkCssSelectorTree *tree,
                                    const GtkCssMatcher  *matcher,
                                    GHashTable *res)
 {
-  const GtkCssSelectorTree *prev, *prev2;
+  const GtkCssSelectorTree *prev;
 
   if (!_gtk_css_matcher_has_region (matcher, tree->selector.data, 0))
     return;
@@ -815,12 +862,7 @@ gtk_css_selector_region_tree_match (const GtkCssSelectorTree *tree,
        prev = gtk_css_selector_tree_get_sibling (prev))
     {
       if (prev->selector.class == &GTK_CSS_SELECTOR_DESCENDANT)
-       {
-         for (prev2 = gtk_css_selector_tree_get_previous (prev);
-              prev2 != NULL;
-              prev2 = gtk_css_selector_tree_get_sibling (prev2))
-           gtk_css_selector_tree_match (prev2, matcher, res);
-       }
+       gtk_css_selector_tree_match_previous (prev, matcher, res);
 
       gtk_css_selector_tree_match (prev, matcher, res);
     }
@@ -917,17 +959,12 @@ gtk_css_selector_class_tree_match (const GtkCssSelectorTree *tree,
                                   const GtkCssMatcher  *matcher,
                                   GHashTable *res)
 {
-  const GtkCssSelectorTree *prev;
-
   if (!_gtk_css_matcher_has_class (matcher, GPOINTER_TO_UINT (tree->selector.data)))
     return;
 
   gtk_css_selector_tree_found_match (tree, res);
 
-  for (prev = gtk_css_selector_tree_get_previous (tree);
-       prev != NULL;
-       prev = gtk_css_selector_tree_get_sibling (prev))
-    gtk_css_selector_tree_match (prev, matcher, res);
+  gtk_css_selector_tree_match_previous (tree, matcher, res);
 }
 
 static GtkCssChange
@@ -1002,17 +1039,12 @@ gtk_css_selector_id_tree_match (const GtkCssSelectorTree *tree,
                                const GtkCssMatcher  *matcher,
                                GHashTable *res)
 {
-  const GtkCssSelectorTree *prev;
-
   if (!_gtk_css_matcher_has_id (matcher, tree->selector.data))
     return;
 
   gtk_css_selector_tree_found_match (tree, res);
 
-  for (prev = gtk_css_selector_tree_get_previous (tree);
-       prev != NULL;
-       prev = gtk_css_selector_tree_get_sibling (prev))
-    gtk_css_selector_tree_match (prev, matcher, res);
+  gtk_css_selector_tree_match_previous (tree, matcher, res);
 }
 
 static GtkCssChange
@@ -1075,7 +1107,9 @@ gtk_css_selector_pseudoclass_state_print (const GtkCssSelector *selector,
     "insensitive",
     "inconsistent",
     "focus",
-    "backdrop"
+    "backdrop",
+    "dir(ltr)",
+    "dir(rtl)"
   };
   guint i, state;
 
@@ -1112,17 +1146,13 @@ gtk_css_selector_pseudoclass_state_tree_match (const GtkCssSelectorTree *tree,
                                               GHashTable *res)
 {
   GtkStateFlags state = GPOINTER_TO_UINT (tree->selector.data);
-  const GtkCssSelectorTree *prev;
 
   if ((_gtk_css_matcher_get_state (matcher) & state) != state)
     return;
 
   gtk_css_selector_tree_found_match (tree, res);
 
-  for (prev = gtk_css_selector_tree_get_previous (tree);
-       prev != NULL;
-       prev = gtk_css_selector_tree_get_sibling (prev))
-    gtk_css_selector_tree_match (prev, matcher, res);
+  gtk_css_selector_tree_match_previous (tree, matcher, res);
 }
 
 static GtkCssChange
@@ -1795,7 +1825,9 @@ parse_selector_pseudo_class (GtkCssParser   *parser,
     { "inconsistent", GTK_STATE_FLAG_INCONSISTENT, },
     { "focused",      GTK_STATE_FLAG_FOCUSED, },
     { "focus",        GTK_STATE_FLAG_FOCUSED, },
-    { "backdrop",     GTK_STATE_FLAG_BACKDROP, }
+    { "backdrop",     GTK_STATE_FLAG_BACKDROP, },
+    { "dir(ltr)",     GTK_STATE_FLAG_DIR_LTR, },
+    { "dir(rtl)",     GTK_STATE_FLAG_DIR_RTL, }
   };
   guint i;
 
@@ -1837,11 +1869,14 @@ try_parse_name (GtkCssParser   *parser,
   name = _gtk_css_parser_try_ident (parser, FALSE);
   if (name)
     {
-      selector = gtk_css_selector_new (_gtk_style_context_check_region_name (name)
-                                       ? &GTK_CSS_SELECTOR_REGION
-                                       : &GTK_CSS_SELECTOR_NAME,
-                                       selector,
-                                       g_intern_string (name));
+      if (_gtk_style_context_check_region_name (name))
+       selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_REGION,
+                                        selector,
+                                        g_intern_string (name));
+      else
+       selector = gtk_css_selector_new (&GTK_CSS_SELECTOR_NAME,
+                                        selector,
+                                        get_type_reference (name));
       g_free (name);
     }
   else if (_gtk_css_parser_try (parser, "*", FALSE))
@@ -1948,6 +1983,8 @@ _gtk_css_selector_tree_match_get_change (const GtkCssSelectorTree *tree)
 {
   GtkCssChange change = 0;
 
+  update_type_references ();
+
   while (tree)
     {
       change = tree->selector.class->get_change (&tree->selector, change);
@@ -1979,6 +2016,8 @@ _gtk_css_selector_matches (const GtkCssSelector *selector,
   g_return_val_if_fail (selector != NULL, FALSE);
   g_return_val_if_fail (matcher != NULL, FALSE);
 
+  update_type_references ();
+
   return gtk_css_selector_match (selector, matcher);
 }
 
@@ -2117,6 +2156,8 @@ _gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
   GHashTableIter iter;
   gpointer key;
 
+  update_type_references ();
+
   res = g_hash_table_new (g_direct_hash, g_direct_equal);
 
   for (; tree != NULL;