diff --git a/gtk/gtkcsscalcvalue.c b/gtk/gtkcsscalcvalue.c index 2004fbac53..4c9d79ddf3 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 2d113150ff..cd70553291 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 92c2d99cda..22365c40f0 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 2e08eba785..5a9bf97a70 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 54e1d1c006..c31874cb21 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 ddded6674c..b4cb0ca5da 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 3c896bd539..27918ea339 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, @@ -665,6 +672,13 @@ parse_letter_spacing (GtkCssStyleProperty *property, return _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH); } +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) @@ -817,6 +831,13 @@ dpi_parse (GtkCssStyleProperty *property, return _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER); } +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) @@ -843,6 +864,15 @@ outline_parse (GtkCssStyleProperty *property, | GTK_CSS_PARSE_LENGTH); } +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) @@ -892,6 +922,15 @@ minmax_parse (GtkCssStyleProperty *property, | GTK_CSS_POSITIVE_ONLY); } +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) { @@ -985,6 +1024,15 @@ parse_margin (GtkCssStyleProperty *property, | GTK_CSS_PARSE_LENGTH); } +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) @@ -995,6 +1043,16 @@ parse_padding (GtkCssStyleProperty *property, | GTK_CSS_PARSE_LENGTH); } +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) @@ -1005,6 +1063,16 @@ parse_border_width (GtkCssStyleProperty *property, | GTK_CSS_PARSE_LENGTH); } +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) { @@ -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 134078b3a5..82fa5c6615 100644 --- a/gtk/gtkcsswin32sizevalue.c +++ b/gtk/gtkcsswin32sizevalue.c @@ -33,13 +33,13 @@ typedef enum { } GtkWin32SizeType; static const char *css_value_names[] = { - "-gtk-win32-size(", - "-gtk-win32-part-width(", - "-gtk-win32-part-height(", - "-gtk-win32-part-border-top(", - "-gtk-win32-part-border-right(", - "-gtk-win32-part-border-bottom(", - "-gtk-win32-part-border-left(" + "-gtk-win32-size", + "-gtk-win32-part-width", + "-gtk-win32-part-height", + "-gtk-win32-part-border-top", + "-gtk-win32-part-border-right", + "-gtk-win32-part-border-bottom", + "-gtk-win32-part-border-left" }; struct _GtkCssValue { @@ -160,6 +160,7 @@ gtk_css_value_win32_size_print (const GtkCssValue *value, g_string_append_printf (string, "%g * ", value->scale); } g_string_append (string, css_value_names[value->type]); + g_string_append (string, "("); gtk_win32_theme_print (value->theme, string); switch (value->type) @@ -341,7 +342,7 @@ gtk_css_win32_size_value_parse (GtkCssParser *parser, for (type = 0; type < G_N_ELEMENTS(css_value_names); type++) { - if (_gtk_css_parser_try (parser, css_value_names[type], TRUE)) + if (_gtk_css_parser_try (parser, css_value_names[type], FALSE)) break; } @@ -351,6 +352,12 @@ gtk_css_win32_size_value_parse (GtkCssParser *parser, return NULL; } + if (!_gtk_css_parser_try (parser, "(", TRUE)) + { + _gtk_css_parser_error (parser, "Expected '('"); + return NULL; + } + theme = gtk_win32_theme_parse (parser); if (theme == NULL) return NULL; @@ -399,3 +406,138 @@ 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; + } + + gtk_css_token_source_consume_token (source); + + 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; + } + + token = gtk_css_token_source_get_token (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 fd9bf19a40..d426d7ed38 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