[gtk+/wip/otte/tokenizer: 18/42] css: Add token parsing for number values



commit daba59c4850200f0107ae62bd3d26fbb176f0356
Author: Benjamin Otte <otte redhat com>
Date:   Thu Mar 17 00:36:51 2016 +0100

    css: Add token parsing for number values
    
    This includes calc() and the win32 number values.
    
    CSS properties using just <length>, <angle>, <time>, <percentage> or
    <number> have been converted.

 gtk/gtkcsscalcvalue.c             |  214 +++++++++++++++++++++++++++++++++++++
 gtk/gtkcsscalcvalueprivate.h      |    2 +
 gtk/gtkcssdimensionvalue.c        |  109 +++++++++++++++++++
 gtk/gtkcssdimensionvalueprivate.h |    3 +
 gtk/gtkcssnumbervalue.c           |   20 ++++
 gtk/gtkcssnumbervalueprivate.h    |    3 +
 gtk/gtkcssstylepropertyimpl.c     |  106 +++++++++++++++----
 gtk/gtkcsswin32sizevalue.c        |  133 +++++++++++++++++++++++
 gtk/gtkcsswin32sizevalueprivate.h |    2 +
 9 files changed, 573 insertions(+), 19 deletions(-)
---
diff --git a/gtk/gtkcsscalcvalue.c b/gtk/gtkcsscalcvalue.c
index 2004fba..4c9d79d 100644
--- a/gtk/gtkcsscalcvalue.c
+++ b/gtk/gtkcsscalcvalue.c
@@ -485,3 +485,217 @@ gtk_css_calc_value_parse (GtkCssParser           *parser,
   return value;
 }
 
+GtkCssValue * gtk_css_calc_value_token_parse_sum (GtkCssTokenSource      *source,
+                                                  GtkCssNumberParseFlags  flags);
+
+GtkCssValue *
+gtk_css_calc_value_token_parse_value (GtkCssTokenSource      *source,
+                                      GtkCssNumberParseFlags  flags)
+{
+  const GtkCssToken *token;
+  GtkCssValue *result;
+
+  token = gtk_css_token_source_get_token (source);
+
+  if (gtk_css_token_is_function (token, "calc"))
+    {
+      gtk_css_token_source_error (source, "Nested calc() expressions are not allowed.");
+      gtk_css_token_source_consume_all (source);
+      return NULL;
+    }
+  else if (gtk_css_token_is (token, GTK_CSS_TOKEN_OPEN_PARENS))
+    {
+      gtk_css_token_source_consume_token (source);
+      gtk_css_token_source_consume_whitespace (source);
+
+      result = gtk_css_calc_value_token_parse_sum (source, flags);
+      if (result == NULL)
+        return NULL;
+
+      token = gtk_css_token_source_get_token (source);
+      if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
+        {
+          gtk_css_token_source_error (source, "Missing closing ')' in calc() subterm");
+          gtk_css_token_source_consume_all (source);
+          _gtk_css_value_unref (result);
+          return NULL;
+        }
+
+      gtk_css_token_source_consume_token (source);
+      gtk_css_token_source_consume_whitespace (source);
+
+      return result;
+    }
+  else
+    {
+      result = gtk_css_number_value_token_parse (source, flags);
+      if (result == NULL)
+        return NULL;
+
+      gtk_css_token_source_consume_whitespace (source);
+    }
+
+  return result;
+}
+
+GtkCssValue *
+gtk_css_calc_value_token_parse_product (GtkCssTokenSource      *source,
+                                        GtkCssNumberParseFlags  flags)
+{
+  GtkCssValue *result, *value, *temp;
+  GtkCssNumberParseFlags actual_flags;
+
+  actual_flags = flags | GTK_CSS_PARSE_NUMBER;
+
+  result = gtk_css_calc_value_token_parse_value (source, actual_flags);
+  if (result == NULL)
+    return NULL;
+
+  while (TRUE)
+    {
+      const GtkCssToken *token = gtk_css_token_source_get_token (source);
+
+      if (actual_flags != GTK_CSS_PARSE_NUMBER && !is_number (result))
+        actual_flags = GTK_CSS_PARSE_NUMBER;
+
+      if (gtk_css_token_is_delim (token, '*'))
+        {
+          gtk_css_token_source_consume_token (source);
+          gtk_css_token_source_consume_whitespace (source);
+
+          value = gtk_css_calc_value_token_parse_product (source, actual_flags);
+          if (value == NULL)
+            goto fail;
+          if (is_number (value))
+            temp = gtk_css_number_value_multiply (result, _gtk_css_number_value_get (value, 100));
+          else
+            temp = gtk_css_number_value_multiply (value, _gtk_css_number_value_get (result, 100));
+          _gtk_css_value_unref (value);
+          _gtk_css_value_unref (result);
+          result = temp;
+        }
+      else if (gtk_css_token_is_delim (token, '/'))
+        {
+          gtk_css_token_source_consume_token (source);
+          gtk_css_token_source_consume_whitespace (source);
+
+          value = gtk_css_calc_value_token_parse_product (source, GTK_CSS_PARSE_NUMBER);
+          if (value == NULL)
+            goto fail;
+          temp = gtk_css_number_value_multiply (result, 1.0 / _gtk_css_number_value_get (value, 100));
+          _gtk_css_value_unref (value);
+          _gtk_css_value_unref (result);
+          result = temp;
+        }
+      else
+        {
+          break;
+        }
+    }
+
+  if (is_number (result) && !(flags & GTK_CSS_PARSE_NUMBER))
+    {
+      gtk_css_token_source_error (source, "calc() product term has no units");
+      gtk_css_token_source_consume_all (source);
+      goto fail;
+    }
+
+  return result;
+
+fail:
+  _gtk_css_value_unref (result);
+  return NULL;
+}
+
+GtkCssValue *
+gtk_css_calc_value_token_parse_sum (GtkCssTokenSource      *source,
+                                    GtkCssNumberParseFlags  flags)
+{
+  GtkCssValue *result;
+  const GtkCssToken *token;
+
+  result = gtk_css_calc_value_token_parse_product (source, flags);
+  if (result == NULL)
+    return NULL;
+
+  while (TRUE)
+    {
+      GtkCssValue *next, *temp;
+
+      token = gtk_css_token_source_get_token (source);
+      if (gtk_css_token_is_delim (token, '+'))
+        {
+          gtk_css_token_source_consume_token (source);
+          gtk_css_token_source_consume_whitespace (source);
+
+          next = gtk_css_calc_value_token_parse_product (source, flags);
+          if (next == NULL)
+            goto fail;
+        }
+      else if (gtk_css_token_is_delim (token, '-'))
+        {
+          gtk_css_token_source_consume_token (source);
+          gtk_css_token_source_consume_whitespace (source);
+
+          temp = gtk_css_calc_value_token_parse_product (source, flags);
+          if (temp == NULL)
+            goto fail;
+          next = gtk_css_number_value_multiply (temp, -1);
+          _gtk_css_value_unref (temp);
+        }
+      else
+        {
+          break;
+        }
+
+      temp = gtk_css_number_value_add (result, next);
+      _gtk_css_value_unref (result);
+      _gtk_css_value_unref (next);
+      result = temp;
+    }
+
+  return result;
+
+fail:
+  _gtk_css_value_unref (result);
+  return NULL;
+}
+
+GtkCssValue *
+gtk_css_calc_value_token_parse (GtkCssTokenSource      *source,
+                                GtkCssNumberParseFlags  flags)
+{
+  const GtkCssToken *token;
+  GtkCssValue *value;
+
+  /* This confuses '*' and '/' so we disallow backwards compat. */
+  flags &= ~GTK_CSS_NUMBER_AS_PIXELS;
+  /* This can only be handled at compute time, we allow negative numbers everywhere */
+  flags &= ~GTK_CSS_POSITIVE_ONLY;
+
+  token = gtk_css_token_source_get_token (source);
+  if (!gtk_css_token_is_function (token, "calc"))
+    {
+      gtk_css_token_source_error (source, "Expected 'calc('");
+      gtk_css_token_source_consume_all (source);
+      return NULL;
+    }
+  gtk_css_token_source_consume_token (source);
+  gtk_css_token_source_consume_whitespace (source);
+
+  value = gtk_css_calc_value_token_parse_sum (source, flags);
+  if (value == NULL)
+    return NULL;
+
+  token = gtk_css_token_source_get_token (source);
+  if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
+    {
+      _gtk_css_value_unref (value);
+      gtk_css_token_source_error (source, "Expected ')' after calc() statement");
+      gtk_css_token_source_consume_all (source);
+      return NULL;
+    }
+  gtk_css_token_source_consume_token (source);
+
+  return value;
+}
diff --git a/gtk/gtkcsscalcvalueprivate.h b/gtk/gtkcsscalcvalueprivate.h
index 2d11315..cd70553 100644
--- a/gtk/gtkcsscalcvalueprivate.h
+++ b/gtk/gtkcsscalcvalueprivate.h
@@ -27,6 +27,8 @@ GtkCssValue *   gtk_css_calc_value_new_sum          (GtkCssValue            *val
 
 GtkCssValue *   gtk_css_calc_value_parse            (GtkCssParser           *parser,
                                                      GtkCssNumberParseFlags  flags);
+GtkCssValue *   gtk_css_calc_value_token_parse      (GtkCssTokenSource      *source,
+                                                     GtkCssNumberParseFlags  flags);
 
 G_END_DECLS
 
diff --git a/gtk/gtkcssdimensionvalue.c b/gtk/gtkcssdimensionvalue.c
index 92c2d99..22365c4 100644
--- a/gtk/gtkcssdimensionvalue.c
+++ b/gtk/gtkcssdimensionvalue.c
@@ -323,3 +323,112 @@ gtk_css_dimension_value_new (double     value,
   return result;
 }
 
+GtkCssValue *
+gtk_css_dimension_value_token_parse (GtkCssTokenSource      *source,
+                                     GtkCssNumberParseFlags  flags)
+{
+  const GtkCssToken *token = gtk_css_token_source_get_token (source);
+  double d;
+  GtkCssUnit unit;
+
+  if ((gtk_css_token_is (token, GTK_CSS_TOKEN_INTEGER) ||
+       gtk_css_token_is (token, GTK_CSS_TOKEN_NUMBER)) &&
+      ((flags & (GTK_CSS_PARSE_NUMBER | GTK_CSS_NUMBER_AS_PIXELS)) ||
+       (token->number.number == 0.0 && (flags & (GTK_CSS_PARSE_LENGTH | GTK_CSS_PARSE_ANGLE)))))
+    {
+      d = token->number.number;
+      if (flags & GTK_CSS_NUMBER_AS_PIXELS)
+        {
+          if (d != 0.0)
+            gtk_css_token_source_deprecated (source, "Not using units is deprecated. Assuming 'px'.");
+          unit = GTK_CSS_PX;
+        }
+      else
+        {
+          if (flags & GTK_CSS_PARSE_NUMBER)
+            unit = GTK_CSS_NUMBER;
+          else if (flags & GTK_CSS_PARSE_LENGTH)
+            unit = GTK_CSS_PX;
+          else if (flags & GTK_CSS_PARSE_ANGLE)
+            unit = GTK_CSS_DEG;
+        }
+    }
+  else if (gtk_css_token_is (token, GTK_CSS_TOKEN_PERCENTAGE) &&
+           (flags & GTK_CSS_PARSE_PERCENT))
+    {
+      d = token->number.number;
+      unit = GTK_CSS_PERCENT;
+    }
+  else if (gtk_css_token_is (token, GTK_CSS_TOKEN_INTEGER_DIMENSION) ||
+           gtk_css_token_is (token, GTK_CSS_TOKEN_DIMENSION))
+    {
+      static const struct {
+        const char *name;
+        GtkCssUnit unit;
+        GtkCssNumberParseFlags flag;
+      } units[] = {
+        { "px",   GTK_CSS_PX,      GTK_CSS_PARSE_LENGTH },
+        { "pt",   GTK_CSS_PT,      GTK_CSS_PARSE_LENGTH },
+        { "em",   GTK_CSS_EM,      GTK_CSS_PARSE_LENGTH },
+        { "ex",   GTK_CSS_EX,      GTK_CSS_PARSE_LENGTH },
+        { "rem",  GTK_CSS_REM,     GTK_CSS_PARSE_LENGTH },
+        { "pc",   GTK_CSS_PC,      GTK_CSS_PARSE_LENGTH },
+        { "in",   GTK_CSS_IN,      GTK_CSS_PARSE_LENGTH },
+        { "cm",   GTK_CSS_CM,      GTK_CSS_PARSE_LENGTH },
+        { "mm",   GTK_CSS_MM,      GTK_CSS_PARSE_LENGTH },
+        { "rad",  GTK_CSS_RAD,     GTK_CSS_PARSE_ANGLE  },
+        { "deg",  GTK_CSS_DEG,     GTK_CSS_PARSE_ANGLE  },
+        { "grad", GTK_CSS_GRAD,    GTK_CSS_PARSE_ANGLE  },
+        { "turn", GTK_CSS_TURN,    GTK_CSS_PARSE_ANGLE  },
+        { "s",    GTK_CSS_S,       GTK_CSS_PARSE_TIME   },
+        { "ms",   GTK_CSS_MS,      GTK_CSS_PARSE_TIME   }
+      };
+      guint i;
+
+      for (i = 0; i < G_N_ELEMENTS (units); i++)
+        {
+          if ((flags & units[i].flag) == 0)
+            continue;
+
+          if (g_ascii_strcasecmp (units[i].name, token->dimension.dimension) == 0)
+            {
+              d = token->dimension.value;
+              unit = units[i].unit;
+              break;
+            }
+        }
+
+      if (i == G_N_ELEMENTS (units))
+        {
+          gtk_css_token_source_error (source, "'%s' is not a valid unit.", token->dimension.dimension);
+          gtk_css_token_source_consume_all (source);
+          return NULL;
+        }
+    }
+  else
+    {
+      if (flags & GTK_CSS_PARSE_LENGTH)
+        gtk_css_token_source_error (source, "Expected a length");
+      else if (flags & GTK_CSS_PARSE_ANGLE)
+        gtk_css_token_source_error (source, "Expected an angle");
+      else if (flags & GTK_CSS_PARSE_TIME)
+        gtk_css_token_source_error (source, "Expected a time");
+      else if (flags & GTK_CSS_PARSE_PERCENT)
+        gtk_css_token_source_error (source, "Expected a percentage");
+      else
+        gtk_css_token_source_error (source, "Expected a number");
+      gtk_css_token_source_consume_all (source);
+      return NULL;
+    }
+  
+  if ((flags & GTK_CSS_POSITIVE_ONLY) && d < 0.0)
+    {
+      gtk_css_token_source_error (source, "Negative values are not allowed");
+      gtk_css_token_source_consume_all (source);
+      return NULL;
+    }
+
+  gtk_css_token_source_consume_token (source);
+  return gtk_css_dimension_value_new (d, unit);
+}
+
diff --git a/gtk/gtkcssdimensionvalueprivate.h b/gtk/gtkcssdimensionvalueprivate.h
index 2e08eba..5a9bf97 100644
--- a/gtk/gtkcssdimensionvalueprivate.h
+++ b/gtk/gtkcssdimensionvalueprivate.h
@@ -30,6 +30,9 @@ GtkCssValue *   gtk_css_dimension_value_new         (double                  val
 GtkCssValue *   gtk_css_dimension_value_parse       (GtkCssParser           *parser,
                                                      GtkCssNumberParseFlags  flags);
 
+GtkCssValue *   gtk_css_dimension_value_token_parse (GtkCssTokenSource      *source,
+                                                     GtkCssNumberParseFlags  flags);
+
 G_END_DECLS
 
 #endif /* __GTK_CSS_DIMENSION_VALUE_PRIVATE_H__ */
diff --git a/gtk/gtkcssnumbervalue.c b/gtk/gtkcssnumbervalue.c
index 54e1d1c..c31874c 100644
--- a/gtk/gtkcssnumbervalue.c
+++ b/gtk/gtkcssnumbervalue.c
@@ -158,6 +158,26 @@ _gtk_css_number_value_parse (GtkCssParser           *parser,
   return gtk_css_dimension_value_parse (parser, flags);
 }
 
+GtkCssValue *
+gtk_css_number_value_token_parse (GtkCssTokenSource      *source,
+                                  GtkCssNumberParseFlags  flags)
+{
+  const GtkCssToken *token = gtk_css_token_source_get_token (source);
+
+  if (gtk_css_token_is_function (token, "calc"))
+    return gtk_css_calc_value_token_parse (source, flags);
+  else if (gtk_css_token_is_function (token, "-gtk-win32-size") ||
+           gtk_css_token_is_function (token, "-gtk-win32-part-width") ||
+           gtk_css_token_is_function (token, "-gtk-win32-part-height") ||
+           gtk_css_token_is_function (token, "-gtk-win32-part-border-top") ||
+           gtk_css_token_is_function (token, "-gtk-win32-part-border-left") ||
+           gtk_css_token_is_function (token, "-gtk-win32-part-border-bottom") ||
+           gtk_css_token_is_function (token, "-gtk-win32-part-border-right"))
+    return gtk_css_win32_size_value_token_parse (source, flags);
+  else
+    return gtk_css_dimension_value_token_parse (source, flags);
+}
+
 double
 _gtk_css_number_value_get (const GtkCssValue *number,
                            double             one_hundred_percent)
diff --git a/gtk/gtkcssnumbervalueprivate.h b/gtk/gtkcssnumbervalueprivate.h
index ddded66..b4cb0ca 100644
--- a/gtk/gtkcssnumbervalueprivate.h
+++ b/gtk/gtkcssnumbervalueprivate.h
@@ -21,6 +21,7 @@
 #define __GTK_CSS_NUMBER_VALUE_PRIVATE_H__
 
 #include "gtkcssparserprivate.h"
+#include "gtkcsstokensourceprivate.h"
 #include "gtkcsstypesprivate.h"
 #include "gtkcssvalueprivate.h"
 
@@ -61,6 +62,8 @@ GtkCssValue *   gtk_css_number_value_transition     (GtkCssValue            *sta
 gboolean        gtk_css_number_value_can_parse      (GtkCssParser           *parser);
 GtkCssValue *   _gtk_css_number_value_parse         (GtkCssParser           *parser,
                                                      GtkCssNumberParseFlags  flags);
+GtkCssValue *   gtk_css_number_value_token_parse    (GtkCssTokenSource      *source,
+                                                     GtkCssNumberParseFlags  flags);
 
 GtkCssDimension gtk_css_number_value_get_dimension  (const GtkCssValue      *value);
 gboolean        gtk_css_number_value_has_percent    (const GtkCssValue      *value);
diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c
index 3c896bd..27918ea 100644
--- a/gtk/gtkcssstylepropertyimpl.c
+++ b/gtk/gtkcssstylepropertyimpl.c
@@ -488,6 +488,13 @@ opacity_parse (GtkCssStyleProperty *property,
   return _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
 }
 
+static GtkCssValue *
+opacity_token_parse (GtkCssTokenSource   *source,
+                     GtkCssStyleProperty *property)
+{
+  return gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER);
+}
+
 static void
 opacity_query (GtkCssStyleProperty *property,
                const GtkCssValue   *css_value,
@@ -666,6 +673,13 @@ parse_letter_spacing (GtkCssStyleProperty *property,
 }
 
 static GtkCssValue *
+token_parse_letter_spacing (GtkCssTokenSource   *source,
+                            GtkCssStyleProperty *property)
+{
+  return gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH);
+}
+
+static GtkCssValue *
 parse_text_decoration_line (GtkCssStyleProperty *property,
                             GtkCssParser        *parser)
 {
@@ -818,6 +832,13 @@ dpi_parse (GtkCssStyleProperty *property,
 }
 
 static GtkCssValue *
+dpi_token_parse (GtkCssTokenSource   *source,
+                 GtkCssStyleProperty *property)
+{
+  return gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER);
+}
+
+static GtkCssValue *
 font_size_parse (GtkCssStyleProperty *property,
                  GtkCssParser        *parser)
 {
@@ -844,6 +865,15 @@ outline_parse (GtkCssStyleProperty *property,
 }
 
 static GtkCssValue *
+outline_token_parse (GtkCssTokenSource   *source,
+                     GtkCssStyleProperty *property)
+{
+  return gtk_css_number_value_token_parse (source,
+                                           GTK_CSS_NUMBER_AS_PIXELS
+                                           | GTK_CSS_PARSE_LENGTH);
+}
+
+static GtkCssValue *
 border_image_repeat_parse (GtkCssStyleProperty *property,
                            GtkCssParser        *parser)
 {
@@ -893,6 +923,15 @@ minmax_parse (GtkCssStyleProperty *property,
 }
 
 static GtkCssValue *
+minmax_token_parse (GtkCssTokenSource   *source,
+                    GtkCssStyleProperty *property)
+{
+  return gtk_css_number_value_token_parse (source,
+                                           GTK_CSS_PARSE_LENGTH
+                                           | GTK_CSS_POSITIVE_ONLY);
+}
+
+static GtkCssValue *
 transition_property_parse_one (GtkCssParser *parser)
 {
   GtkCssValue *value;
@@ -986,6 +1025,15 @@ parse_margin (GtkCssStyleProperty *property,
 }
 
 static GtkCssValue *
+token_parse_margin (GtkCssTokenSource   *source,
+                    GtkCssStyleProperty *property)
+{
+  return gtk_css_number_value_token_parse (source,
+                                           GTK_CSS_NUMBER_AS_PIXELS
+                                           | GTK_CSS_PARSE_LENGTH);
+}
+
+static GtkCssValue *
 parse_padding (GtkCssStyleProperty *property,
                GtkCssParser        *parser)
 {
@@ -996,6 +1044,16 @@ parse_padding (GtkCssStyleProperty *property,
 }
 
 static GtkCssValue *
+token_parse_padding (GtkCssTokenSource   *source,
+                     GtkCssStyleProperty *property)
+{
+  return gtk_css_number_value_token_parse (source,
+                                           GTK_CSS_POSITIVE_ONLY
+                                           | GTK_CSS_NUMBER_AS_PIXELS
+                                           | GTK_CSS_PARSE_LENGTH);
+}
+
+static GtkCssValue *
 parse_border_width (GtkCssStyleProperty *property,
                     GtkCssParser        *parser)
 {
@@ -1006,6 +1064,16 @@ parse_border_width (GtkCssStyleProperty *property,
 }
 
 static GtkCssValue *
+token_parse_border_width (GtkCssTokenSource   *source,
+                          GtkCssStyleProperty *property)
+{
+  return gtk_css_number_value_token_parse (source,
+                                           GTK_CSS_POSITIVE_ONLY
+                                           | GTK_CSS_NUMBER_AS_PIXELS
+                                           | GTK_CSS_PARSE_LENGTH);
+}
+
+static GtkCssValue *
 background_repeat_value_parse_one (GtkCssParser *parser)
 {
   GtkCssValue *value = _gtk_css_background_repeat_value_try_parse (parser);
@@ -1072,7 +1140,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_FONT | GTK_CSS_AFFECTS_TEXT | GTK_CSS_AFFECTS_SIZE,
                                           dpi_parse,
-                                          gtk_css_style_property_token_parse_default,
+                                          dpi_token_parse,
                                           NULL,
                                           NULL,
                                           _gtk_css_number_value_new (96.0, GTK_CSS_NUMBER));
@@ -1178,7 +1246,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_TEXT | GTK_CSS_AFFECTS_TEXT_ATTRS,
                                           parse_letter_spacing,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_letter_spacing,
                                           NULL,
                                           NULL,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1242,7 +1310,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_SIZE,
                                           parse_margin,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_margin,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1252,7 +1320,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_SIZE,
                                           parse_margin,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_margin,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1262,7 +1330,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_SIZE,
                                           parse_margin,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_margin,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1272,7 +1340,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_SIZE,
                                           parse_margin,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_margin,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1282,7 +1350,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_SIZE,
                                           parse_padding,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_padding,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1292,7 +1360,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_SIZE,
                                           parse_padding,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_padding,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1302,7 +1370,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_SIZE,
                                           parse_padding,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_padding,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1312,7 +1380,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_SIZE,
                                           parse_padding,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_padding,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1335,7 +1403,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_BORDER | GTK_CSS_AFFECTS_SIZE,
                                           parse_border_width,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_border_width,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1355,7 +1423,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_BORDER | GTK_CSS_AFFECTS_SIZE,
                                           parse_border_width,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_border_width,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1375,7 +1443,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_BORDER | GTK_CSS_AFFECTS_SIZE,
                                           parse_border_width,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_border_width,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1395,7 +1463,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_BORDER | GTK_CSS_AFFECTS_SIZE,
                                           parse_border_width,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_border_width,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1461,7 +1529,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_OUTLINE | GTK_CSS_AFFECTS_CLIP,
                                           parse_border_width,
-                                          gtk_css_style_property_token_parse_default,
+                                          token_parse_border_width,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1471,7 +1539,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_OUTLINE | GTK_CSS_AFFECTS_CLIP,
                                           outline_parse,
-                                          gtk_css_style_property_token_parse_default,
+                                          outline_token_parse,
                                           query_length_as_int,
                                           assign_length_from_int,
                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
@@ -1737,7 +1805,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_SIZE,
                                           minmax_parse,
-                                          gtk_css_style_property_token_parse_default,
+                                          minmax_token_parse,
                                           query_length_as_int,
                                           NULL,
                                           _gtk_css_number_value_new (0, GTK_CSS_PX));
@@ -1747,7 +1815,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_SIZE,
                                           minmax_parse,
-                                          gtk_css_style_property_token_parse_default,
+                                          minmax_token_parse,
                                           query_length_as_int,
                                           NULL,
                                           _gtk_css_number_value_new (0, GTK_CSS_PX));
@@ -1882,7 +1950,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           0,
                                           opacity_parse,
-                                          gtk_css_style_property_token_parse_default,
+                                          opacity_token_parse,
                                           opacity_query,
                                           NULL,
                                           _gtk_css_number_value_new (1, GTK_CSS_NUMBER));
diff --git a/gtk/gtkcsswin32sizevalue.c b/gtk/gtkcsswin32sizevalue.c
index 134078b..42a6bd3 100644
--- a/gtk/gtkcsswin32sizevalue.c
+++ b/gtk/gtkcsswin32sizevalue.c
@@ -399,3 +399,136 @@ gtk_css_win32_size_value_parse (GtkCssParser           *parser,
 
   return result;
 }
+
+GtkCssValue *
+gtk_css_win32_size_value_token_parse (GtkCssTokenSource      *source,
+                                      GtkCssNumberParseFlags  flags)
+{
+  GtkWin32Theme *theme;
+  const GtkCssToken *token;
+  GtkCssValue *result;
+  guint type;
+
+  token = gtk_css_token_source_get_token (source);
+  for (type = 0; type < G_N_ELEMENTS(css_value_names); type++)
+    {
+      if (gtk_css_token_is_function (token, css_value_names[type]))
+        break;
+    }
+
+  if (type >= G_N_ELEMENTS(css_value_names))
+    {
+      gtk_css_token_source_error (source, "Not a win32 size value");
+      gtk_css_token_source_consume_all (source);
+      return NULL;
+    }
+
+  theme = gtk_win32_theme_token_parse (source);
+  if (theme == NULL)
+    return NULL;
+
+  gtk_css_token_source_consume_whitespace (source);
+  token = gtk_css_token_source_get_token (source);
+  if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COMMA))
+    {
+      gtk_win32_theme_unref (theme);
+      gtk_css_token_source_error (source, "Expected ','");
+      gtk_css_token_source_consume_all (source);
+      return NULL;
+    }
+  gtk_css_token_source_consume_token (source);
+  gtk_css_token_source_consume_whitespace (source);
+
+  result = gtk_css_win32_size_value_new (1.0, theme, type);
+  gtk_win32_theme_unref (theme);
+
+  switch (result->type)
+    {
+    case GTK_WIN32_SIZE:
+      token = gtk_css_token_source_get_token (source);
+      if (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT))
+        {
+          result->val.size.id = gtk_win32_get_sys_metric_id_for_name (token->string.string);
+          if (result->val.size.id == -1)
+            {
+              gtk_css_token_source_error (source, "'%s' is not a name for a win32 metric.", 
token->string.string);
+              gtk_css_token_source_consume_all (source);
+              _gtk_css_value_unref (result);
+              return NULL;
+            }
+          gtk_css_token_source_consume_token (source);
+        }
+      else if (gtk_css_token_is (token, GTK_CSS_TOKEN_INTEGER))
+        {
+          result->val.size.id = token->number.number;
+          gtk_css_token_source_consume_token (source);
+        }
+      else
+        {
+          _gtk_css_value_unref (result);
+          gtk_css_token_source_error (source, "Expected an integer ID");
+          gtk_css_token_source_consume_all (source);
+          return NULL;
+        }
+      break;
+
+    case GTK_WIN32_PART_WIDTH:
+    case GTK_WIN32_PART_HEIGHT:
+    case GTK_WIN32_PART_BORDER_TOP:
+    case GTK_WIN32_PART_BORDER_RIGHT:
+    case GTK_WIN32_PART_BORDER_BOTTOM:
+    case GTK_WIN32_PART_BORDER_LEFT:
+      token = gtk_css_token_source_get_token (source);
+      if (!gtk_css_token_is (token, GTK_CSS_TOKEN_INTEGER))
+        {
+          _gtk_css_value_unref (result);
+          gtk_css_token_source_error (source, "Expected an integer part ID");
+          gtk_css_token_source_consume_all (source);
+          return NULL;
+        }
+      result->val.part.part = token->number.number;
+      gtk_css_token_source_consume_token (source);
+      gtk_css_token_source_consume_whitespace (source);
+
+      token = gtk_css_token_source_get_token (source);
+      if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COMMA))
+        {
+          _gtk_css_value_unref (result);
+          gtk_css_token_source_error (source, "Expected ','");
+          gtk_css_token_source_consume_all (source);
+          return NULL;
+        }
+      gtk_css_token_source_consume_token (source);
+      gtk_css_token_source_consume_whitespace (source);
+
+      token = gtk_css_token_source_get_token (source);
+      if (!gtk_css_token_is (token, GTK_CSS_TOKEN_INTEGER))
+        {
+          _gtk_css_value_unref (result);
+          gtk_css_token_source_error (source, "Expected an integer state ID");
+          gtk_css_token_source_consume_all (source);
+          return NULL;
+        }
+      result->val.part.state = token->number.number;
+      gtk_css_token_source_consume_token (source);
+      break;
+
+    default:
+      g_assert_not_reached ();
+      _gtk_css_value_unref (result);
+      result = NULL;
+      break;
+    }
+
+  gtk_css_token_source_consume_whitespace (source);
+  if (!gtk_css_token_is (token, GTK_CSS_TOKEN_CLOSE_PARENS))
+    {
+      _gtk_css_value_unref (result);
+      gtk_css_token_source_error (source, "Expected ')'");
+      gtk_css_token_source_consume_all (source);
+      return NULL;
+    }
+  gtk_css_token_source_consume_token (source);
+
+  return result;
+}
diff --git a/gtk/gtkcsswin32sizevalueprivate.h b/gtk/gtkcsswin32sizevalueprivate.h
index fd9bf19..d426d7e 100644
--- a/gtk/gtkcsswin32sizevalueprivate.h
+++ b/gtk/gtkcsswin32sizevalueprivate.h
@@ -26,6 +26,8 @@ G_BEGIN_DECLS
 
 GtkCssValue *   gtk_css_win32_size_value_parse      (GtkCssParser           *parser,
                                                      GtkCssNumberParseFlags  flags);
+GtkCssValue *   gtk_css_win32_size_value_token_parse(GtkCssTokenSource      *source,
+                                                     GtkCssNumberParseFlags  flags);
 
 G_END_DECLS
 


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