diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/ui/theme-parser.c | 115 | ||||
-rw-r--r-- | src/ui/theme.c | 1228 | ||||
-rw-r--r-- | src/ui/theme.h | 205 |
5 files changed, 214 insertions, 1351 deletions
@@ -1,3 +1,16 @@ +2009-02-02 Thomas Thurman <tthurman@gnome.org> + + Basic work for a possible RPN-based parser which is + (slightly) faster and (hopefully) clearer than the + existing one; uses GScanner for tokenising; works + on all themes tested, but doesn't use GError etc + properly yet. + + * src/Makefile.am: + * src/ui/theme-parser.c: + * src/ui/theme.c: + * src/ui/theme.h: + 2009-02-01 Thomas Thurman <tthurman@gnome.org> * configure.in: Post-release bump to 2.25.233. diff --git a/src/Makefile.am b/src/Makefile.am index 4c9e39cc..fba1ec55 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -96,6 +96,8 @@ metacity_SOURCES= \ ui/theme.h \ ui/themewidget.c \ ui/themewidget.h \ + ui/rpn.c \ + ui/rpn.h \ ui/ui.c \ include/all-keybindings.h @@ -114,6 +116,8 @@ libmetacity_private_la_SOURCES= \ ui/preview-widget.h \ ui/theme-parser.c \ ui/theme-parser.h \ + ui/rpn.c \ + ui/rpn.h \ ui/theme.c \ ui/theme.h diff --git a/src/ui/theme-parser.c b/src/ui/theme-parser.c index 98dc1662..c3f9ba22 100644 --- a/src/ui/theme-parser.c +++ b/src/ui/theme-parser.c @@ -24,6 +24,7 @@ #include <config.h> #include "theme-parser.h" #include "util.h" +#include "rpn.h" #include <string.h> #include <stdlib.h> @@ -1656,10 +1657,10 @@ parse_draw_op_element (GMarkupParseContext *context, op->data.line.color_spec = color_spec; - op->data.line.x1 = meta_draw_spec_new (info->theme, x1, NULL); - op->data.line.y1 = meta_draw_spec_new (info->theme, y1, NULL); - op->data.line.x2 = meta_draw_spec_new (info->theme, x2, NULL); - op->data.line.y2 = meta_draw_spec_new (info->theme, y2, NULL); + op->data.line.x1 = meta_rpn_parse (info->theme, x1, NULL); + op->data.line.y1 = meta_rpn_parse (info->theme, y1, NULL); + op->data.line.x2 = meta_rpn_parse (info->theme, x2, NULL); + op->data.line.y2 = meta_rpn_parse (info->theme, y2, NULL); op->data.line.width = width_val; op->data.line.dash_on_length = dash_on_val; @@ -1723,10 +1724,10 @@ parse_draw_op_element (GMarkupParseContext *context, op = meta_draw_op_new (META_DRAW_RECTANGLE); op->data.rectangle.color_spec = color_spec; - op->data.rectangle.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.rectangle.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.rectangle.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.rectangle.height = meta_draw_spec_new (info->theme, + op->data.rectangle.x = meta_rpn_parse (info->theme, x, NULL); + op->data.rectangle.y = meta_rpn_parse (info->theme, y, NULL); + op->data.rectangle.width = meta_rpn_parse (info->theme, width, NULL); + op->data.rectangle.height = meta_rpn_parse (info->theme, height, NULL); op->data.rectangle.filled = filled_val; @@ -1859,10 +1860,10 @@ parse_draw_op_element (GMarkupParseContext *context, op->data.arc.color_spec = color_spec; - op->data.arc.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.arc.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.arc.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.arc.height = meta_draw_spec_new (info->theme, height, NULL); + op->data.arc.x = meta_rpn_parse (info->theme, x, NULL); + op->data.arc.y = meta_rpn_parse (info->theme, y, NULL); + op->data.arc.width = meta_rpn_parse (info->theme, width, NULL); + op->data.arc.height = meta_rpn_parse (info->theme, height, NULL); op->data.arc.filled = filled_val; op->data.arc.start_angle = start_angle_val; @@ -1904,10 +1905,10 @@ parse_draw_op_element (GMarkupParseContext *context, #endif op = meta_draw_op_new (META_DRAW_CLIP); - op->data.clip.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.clip.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.clip.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.clip.height = meta_draw_spec_new (info->theme, height, NULL); + op->data.clip.x = meta_rpn_parse (info->theme, x, NULL); + op->data.clip.y = meta_rpn_parse (info->theme, y, NULL); + op->data.clip.width = meta_rpn_parse (info->theme, width, NULL); + op->data.clip.height = meta_rpn_parse (info->theme, height, NULL); g_assert (info->op_list); @@ -1971,10 +1972,10 @@ parse_draw_op_element (GMarkupParseContext *context, op->data.tint.color_spec = color_spec; op->data.tint.alpha_spec = alpha_spec; - op->data.tint.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.tint.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.tint.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.tint.height = meta_draw_spec_new (info->theme, height, NULL); + op->data.tint.x = meta_rpn_parse (info->theme, x, NULL); + op->data.tint.y = meta_rpn_parse (info->theme, y, NULL); + op->data.tint.width = meta_rpn_parse (info->theme, width, NULL); + op->data.tint.height = meta_rpn_parse (info->theme, height, NULL); g_assert (info->op_list); @@ -2032,11 +2033,11 @@ parse_draw_op_element (GMarkupParseContext *context, g_assert (info->op == NULL); info->op = meta_draw_op_new (META_DRAW_GRADIENT); - info->op->data.gradient.x = meta_draw_spec_new (info->theme, x, NULL); - info->op->data.gradient.y = meta_draw_spec_new (info->theme, y, NULL); - info->op->data.gradient.width = meta_draw_spec_new (info->theme, + info->op->data.gradient.x = meta_rpn_parse (info->theme, x, NULL); + info->op->data.gradient.y = meta_rpn_parse (info->theme, y, NULL); + info->op->data.gradient.width = meta_rpn_parse (info->theme, width, NULL); - info->op->data.gradient.height = meta_draw_spec_new (info->theme, + info->op->data.gradient.height = meta_rpn_parse (info->theme, height, NULL); info->op->data.gradient.gradient_spec = meta_gradient_spec_new (type_val); @@ -2141,10 +2142,10 @@ parse_draw_op_element (GMarkupParseContext *context, op->data.image.pixbuf = pixbuf; op->data.image.colorize_spec = colorize_spec; - op->data.image.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.image.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.image.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.image.height = meta_draw_spec_new (info->theme, height, NULL); + op->data.image.x = meta_rpn_parse (info->theme, x, NULL); + op->data.image.y = meta_rpn_parse (info->theme, y, NULL); + op->data.image.width = meta_rpn_parse (info->theme, width, NULL); + op->data.image.height = meta_rpn_parse (info->theme, height, NULL); op->data.image.alpha_spec = alpha_spec; op->data.image.fill_type = fill_type_val; @@ -2292,10 +2293,10 @@ parse_draw_op_element (GMarkupParseContext *context, op = meta_draw_op_new (META_DRAW_GTK_ARROW); - op->data.gtk_arrow.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.gtk_arrow.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.gtk_arrow.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.gtk_arrow.height = meta_draw_spec_new (info->theme, + op->data.gtk_arrow.x = meta_rpn_parse (info->theme, x, NULL); + op->data.gtk_arrow.y = meta_rpn_parse (info->theme, y, NULL); + op->data.gtk_arrow.width = meta_rpn_parse (info->theme, width, NULL); + op->data.gtk_arrow.height = meta_rpn_parse (info->theme, height, NULL); op->data.gtk_arrow.filled = filled_val; @@ -2365,10 +2366,10 @@ parse_draw_op_element (GMarkupParseContext *context, op = meta_draw_op_new (META_DRAW_GTK_BOX); - op->data.gtk_box.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.gtk_box.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.gtk_box.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.gtk_box.height = meta_draw_spec_new (info->theme, height, NULL); + op->data.gtk_box.x = meta_rpn_parse (info->theme, x, NULL); + op->data.gtk_box.y = meta_rpn_parse (info->theme, y, NULL); + op->data.gtk_box.width = meta_rpn_parse (info->theme, width, NULL); + op->data.gtk_box.height = meta_rpn_parse (info->theme, height, NULL); op->data.gtk_box.state = state_val; op->data.gtk_box.shadow = shadow_val; @@ -2418,9 +2419,9 @@ parse_draw_op_element (GMarkupParseContext *context, op = meta_draw_op_new (META_DRAW_GTK_VLINE); - op->data.gtk_vline.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.gtk_vline.y1 = meta_draw_spec_new (info->theme, y1, NULL); - op->data.gtk_vline.y2 = meta_draw_spec_new (info->theme, y2, NULL); + op->data.gtk_vline.x = meta_rpn_parse (info->theme, x, NULL); + op->data.gtk_vline.y1 = meta_rpn_parse (info->theme, y1, NULL); + op->data.gtk_vline.y2 = meta_rpn_parse (info->theme, y2, NULL); op->data.gtk_vline.state = state_val; @@ -2484,10 +2485,10 @@ parse_draw_op_element (GMarkupParseContext *context, op = meta_draw_op_new (META_DRAW_ICON); - op->data.icon.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.icon.y = meta_draw_spec_new (info->theme, y, NULL); - op->data.icon.width = meta_draw_spec_new (info->theme, width, NULL); - op->data.icon.height = meta_draw_spec_new (info->theme, height, NULL); + op->data.icon.x = meta_rpn_parse (info->theme, x, NULL); + op->data.icon.y = meta_rpn_parse (info->theme, y, NULL); + op->data.icon.width = meta_rpn_parse (info->theme, width, NULL); + op->data.icon.height = meta_rpn_parse (info->theme, height, NULL); op->data.icon.alpha_spec = alpha_spec; op->data.icon.fill_type = fill_type_val; @@ -2535,8 +2536,8 @@ parse_draw_op_element (GMarkupParseContext *context, op->data.title.color_spec = color_spec; - op->data.title.x = meta_draw_spec_new (info->theme, x, NULL); - op->data.title.y = meta_draw_spec_new (info->theme, y, NULL); + op->data.title.x = meta_rpn_parse (info->theme, x, NULL); + op->data.title.y = meta_rpn_parse (info->theme, y, NULL); g_assert (info->op_list); @@ -2607,12 +2608,12 @@ parse_draw_op_element (GMarkupParseContext *context, meta_draw_op_list_ref (op_list); op->data.op_list.op_list = op_list; - op->data.op_list.x = meta_draw_spec_new (info->theme, x ? x : "0", NULL); - op->data.op_list.y = meta_draw_spec_new (info->theme, y ? y : "0", NULL); - op->data.op_list.width = meta_draw_spec_new (info->theme, + op->data.op_list.x = meta_rpn_parse (info->theme, x ? x : "0", NULL); + op->data.op_list.y = meta_rpn_parse (info->theme, y ? y : "0", NULL); + op->data.op_list.width = meta_rpn_parse (info->theme, width ? width : "width", NULL); - op->data.op_list.height = meta_draw_spec_new (info->theme, + op->data.op_list.height = meta_rpn_parse (info->theme, height ? height : "height", NULL); @@ -2702,22 +2703,22 @@ parse_draw_op_element (GMarkupParseContext *context, meta_draw_op_list_ref (op_list); - op->data.tile.x = meta_draw_spec_new (info->theme, x ? x : "0", NULL); - op->data.tile.y = meta_draw_spec_new (info->theme, y ? y : "0", NULL); - op->data.tile.width = meta_draw_spec_new (info->theme, + op->data.tile.x = meta_rpn_parse (info->theme, x ? x : "0", NULL); + op->data.tile.y = meta_rpn_parse (info->theme, y ? y : "0", NULL); + op->data.tile.width = meta_rpn_parse (info->theme, width ? width : "width", NULL); - op->data.tile.height = meta_draw_spec_new (info->theme, + op->data.tile.height = meta_rpn_parse (info->theme, height ? height : "height", NULL); - op->data.tile.tile_xoffset = meta_draw_spec_new (info->theme, + op->data.tile.tile_xoffset = meta_rpn_parse (info->theme, tile_xoffset ? tile_xoffset : "0", NULL); - op->data.tile.tile_yoffset = meta_draw_spec_new (info->theme, + op->data.tile.tile_yoffset = meta_rpn_parse (info->theme, tile_yoffset ? tile_yoffset : "0", NULL); - op->data.tile.tile_width = meta_draw_spec_new (info->theme, tile_width, NULL); - op->data.tile.tile_height = meta_draw_spec_new (info->theme, tile_height, NULL); + op->data.tile.tile_width = meta_rpn_parse (info->theme, tile_width, NULL); + op->data.tile.tile_height = meta_rpn_parse (info->theme, tile_height, NULL); op->data.tile.op_list = op_list; diff --git a/src/ui/theme.c b/src/ui/theme.c index ccd3fc0d..ecbfc702 100644 --- a/src/ui/theme.c +++ b/src/ui/theme.c @@ -57,11 +57,15 @@ #include "theme-parser.h" #include "util.h" #include "gradient.h" +#include "rpn.h" #include <gtk/gtk.h> #include <string.h> #include <stdlib.h> #include <math.h> +#include <sys/time.h> +#include <time.h> + #define GDK_COLOR_RGBA(color) \ ((guint32) (0xff | \ (((color).red / 256) << 24) | \ @@ -1431,1046 +1435,12 @@ meta_color_spec_render (MetaColorSpec *spec, } } -/** - * Represents an operation as a string. - * - * \param type an operation, such as addition - * \return a string, such as "+" - */ -static const char* -op_name (PosOperatorType type) -{ - switch (type) - { - case POS_OP_ADD: - return "+"; - case POS_OP_SUBTRACT: - return "-"; - case POS_OP_MULTIPLY: - return "*"; - case POS_OP_DIVIDE: - return "/"; - case POS_OP_MOD: - return "%"; - case POS_OP_MAX: - return "`max`"; - case POS_OP_MIN: - return "`min`"; - case POS_OP_NONE: - break; - } - - return "<unknown>"; -} - -/** - * Parses a string and returns an operation. - * - * \param p a pointer into a string representing an operation; part of an - * expression somewhere, so not null-terminated - * \param len set to the length of the string found. Set to 0 if none is. - * \return the operation found. If none was, returns POS_OP_NONE. - */ -static PosOperatorType -op_from_string (const char *p, - int *len) -{ - *len = 0; - - switch (*p) - { - case '+': - *len = 1; - return POS_OP_ADD; - case '-': - *len = 1; - return POS_OP_SUBTRACT; - case '*': - *len = 1; - return POS_OP_MULTIPLY; - case '/': - *len = 1; - return POS_OP_DIVIDE; - case '%': - *len = 1; - return POS_OP_MOD; - - case '`': - if (p[0] == '`' && - p[1] == 'm' && - p[2] == 'a' && - p[3] == 'x' && - p[4] == '`') - { - *len = 5; - return POS_OP_MAX; - } - else if (p[0] == '`' && - p[1] == 'm' && - p[2] == 'i' && - p[3] == 'n' && - p[4] == '`') - { - *len = 5; - return POS_OP_MIN; - } - } - - return POS_OP_NONE; -} - -/** - * Frees an array of tokens. All the tokens and their associated memory - * will be freed. - * - * \param tokens an array of tokens to be freed - * \param n_tokens how many tokens are in the array. - */ -static void -free_tokens (PosToken *tokens, - int n_tokens) -{ - int i; - - /* n_tokens can be 0 since tokens may have been allocated more than - * it was initialized - */ - - for (i = 0; i < n_tokens; i++) - if (tokens[i].type == POS_TOKEN_VARIABLE) - g_free (tokens[i].d.v.name); - - g_free (tokens); -} - -/** - * Tokenises a number in an expression. - * - * \param p a pointer into a string representing an operation; part of an - * expression somewhere, so not null-terminated - * \param end_return set to a pointer to the end of the number found; but - * not updated if no number was found at all - * \param next set to either an integer or a float token - * \param[out] err set to the problem if there was a problem - * \return TRUE if a valid number was found, FALSE otherwise (and "err" will - * have been set) - * - * \bug The "while (*start)..." part: what's wrong with strchr-ish things? - * \bug The name is wrong: it doesn't parse anything. - * \ingroup tokenizer - */ -static gboolean -parse_number (const char *p, - const char **end_return, - PosToken *next, - GError **err) -{ - const char *start = p; - char *end; - gboolean is_float; - char *num_str; - - while (*p && (*p == '.' || g_ascii_isdigit (*p))) - ++p; - - if (p == start) - { - char buf[7] = { '\0' }; - buf[g_unichar_to_utf8 (g_utf8_get_char (p), buf)] = '\0'; - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_BAD_CHARACTER, - _("Coordinate expression contains character '%s' which is not allowed"), - buf); - return FALSE; - } - - *end_return = p; - - /* we need this to exclude floats like "1e6" */ - num_str = g_strndup (start, p - start); - start = num_str; - is_float = FALSE; - while (*start) - { - if (*start == '.') - is_float = TRUE; - ++start; - } - - if (is_float) - { - next->type = POS_TOKEN_DOUBLE; - next->d.d.val = g_ascii_strtod (num_str, &end); - - if (end == num_str) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression contains floating point number '%s' which could not be parsed"), - num_str); - g_free (num_str); - return FALSE; - } - } - else - { - next->type = POS_TOKEN_INT; - next->d.i.val = strtol (num_str, &end, 10); - if (end == num_str) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression contains integer '%s' which could not be parsed"), - num_str); - g_free (num_str); - return FALSE; - } - } - - g_free (num_str); - - g_assert (next->type == POS_TOKEN_INT || next->type == POS_TOKEN_DOUBLE); - - return TRUE; -} - -/** - * Whether a variable can validly appear as part of the name of a variable. - */ -#define IS_VARIABLE_CHAR(c) (g_ascii_isalpha ((c)) || (c) == '_') - -#if 0 -static void -debug_print_tokens (PosToken *tokens, - int n_tokens) -{ - int i; - - for (i = 0; i < n_tokens; i++) - { - PosToken *t = &tokens[i]; - - g_print (" "); - - switch (t->type) - { - case POS_TOKEN_INT: - g_print ("\"%d\"", t->d.i.val); - break; - case POS_TOKEN_DOUBLE: - g_print ("\"%g\"", t->d.d.val); - break; - case POS_TOKEN_OPEN_PAREN: - g_print ("\"(\""); - break; - case POS_TOKEN_CLOSE_PAREN: - g_print ("\")\""); - break; - case POS_TOKEN_VARIABLE: - g_print ("\"%s\"", t->d.v.name); - break; - case POS_TOKEN_OPERATOR: - g_print ("\"%s\"", op_name (t->d.o.op)); - break; - } - } - - g_print ("\n"); -} -#endif - -/** - * Tokenises an expression. - * - * \param expr The expression - * \param[out] tokens_p The resulting tokens - * \param[out] n_tokens_p The number of resulting tokens - * \param[out] err set to the problem if there was a problem - * - * \return True if the expression was successfully tokenised; false otherwise. - * - * \ingroup tokenizer - */ -static gboolean -pos_tokenize (const char *expr, - PosToken **tokens_p, - int *n_tokens_p, - GError **err) -{ - PosToken *tokens; - int n_tokens; - int allocated; - const char *p; - - *tokens_p = NULL; - *n_tokens_p = 0; - - allocated = 3; - n_tokens = 0; - tokens = g_new (PosToken, allocated); - - p = expr; - while (*p) - { - PosToken *next; - int len; - - if (n_tokens == allocated) - { - allocated *= 2; - tokens = g_renew (PosToken, tokens, allocated); - } - - next = &tokens[n_tokens]; - - switch (*p) - { - case '*': - case '/': - case '+': - case '-': /* negative numbers aren't allowed so this is easy */ - case '%': - case '`': - next->type = POS_TOKEN_OPERATOR; - next->d.o.op = op_from_string (p, &len); - if (next->d.o.op != POS_OP_NONE) - { - ++n_tokens; - p = p + (len - 1); /* -1 since we ++p later */ - } - else - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression contained unknown operator at the start of this text: \"%s\""), - p); - - goto error; - } - break; - - case '(': - next->type = POS_TOKEN_OPEN_PAREN; - ++n_tokens; - break; - - case ')': - next->type = POS_TOKEN_CLOSE_PAREN; - ++n_tokens; - break; - - case ' ': - case '\t': - case '\n': - break; - - default: - if (IS_VARIABLE_CHAR (*p)) - { - /* Assume variable */ - const char *start = p; - while (*p && IS_VARIABLE_CHAR (*p)) - ++p; - g_assert (p != start); - next->type = POS_TOKEN_VARIABLE; - next->d.v.name = g_strndup (start, p - start); - ++n_tokens; - --p; /* since we ++p again at the end of while loop */ - } - else - { - /* Assume number */ - const char *end; - - if (!parse_number (p, &end, next, err)) - goto error; - - ++n_tokens; - p = end - 1; /* -1 since we ++p again at the end of while loop */ - } - - break; - } - - ++p; - } - - if (n_tokens == 0) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression was empty or not understood")); - - goto error; - } - - *tokens_p = tokens; - *n_tokens_p = n_tokens; - - return TRUE; - - error: - g_assert (err == NULL || *err != NULL); - - free_tokens (tokens, n_tokens); - return FALSE; -} - -/** - * The type of a PosExpr: either integer, double, or an operation. - * \ingroup parser - */ -typedef enum -{ - POS_EXPR_INT, - POS_EXPR_DOUBLE, - POS_EXPR_OPERATOR -} PosExprType; - -/** - * Type and value of an expression in a parsed sequence. We don't - * keep expressions in a tree; if this is of type POS_EXPR_OPERATOR, - * the arguments of the operator will be in the array positions - * immediately preceding and following this operator; they cannot - * themselves be operators. - * - * \bug operator is char; it should really be of PosOperatorType. - * \ingroup parser - */ -typedef struct -{ - PosExprType type; - union - { - double double_val; - int int_val; - char operator; - } d; -} PosExpr; - -#if 0 -static void -debug_print_exprs (PosExpr *exprs, - int n_exprs) -{ - int i; - - for (i = 0; i < n_exprs; i++) - { - switch (exprs[i].type) - { - case POS_EXPR_INT: - g_print (" %d", exprs[i].d.int_val); - break; - case POS_EXPR_DOUBLE: - g_print (" %g", exprs[i].d.double_val); - break; - case POS_EXPR_OPERATOR: - g_print (" %s", op_name (exprs[i].d.operator)); - break; - } - } - g_print ("\n"); -} -#endif - -static gboolean -do_operation (PosExpr *a, - PosExpr *b, - PosOperatorType op, - GError **err) -{ - /* Promote types to double if required */ - if (a->type == POS_EXPR_DOUBLE || - b->type == POS_EXPR_DOUBLE) - { - if (a->type != POS_EXPR_DOUBLE) - { - a->type = POS_EXPR_DOUBLE; - a->d.double_val = a->d.int_val; - } - if (b->type != POS_EXPR_DOUBLE) - { - b->type = POS_EXPR_DOUBLE; - b->d.double_val = b->d.int_val; - } - } - - g_assert (a->type == b->type); - - if (a->type == POS_EXPR_INT) - { - switch (op) - { - case POS_OP_MULTIPLY: - a->d.int_val = a->d.int_val * b->d.int_val; - break; - case POS_OP_DIVIDE: - if (b->d.int_val == 0) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_DIVIDE_BY_ZERO, - _("Coordinate expression results in division by zero")); - return FALSE; - } - a->d.int_val = a->d.int_val / b->d.int_val; - break; - case POS_OP_MOD: - if (b->d.int_val == 0) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_DIVIDE_BY_ZERO, - _("Coordinate expression results in division by zero")); - return FALSE; - } - a->d.int_val = a->d.int_val % b->d.int_val; - break; - case POS_OP_ADD: - a->d.int_val = a->d.int_val + b->d.int_val; - break; - case POS_OP_SUBTRACT: - a->d.int_val = a->d.int_val - b->d.int_val; - break; - case POS_OP_MAX: - a->d.int_val = MAX (a->d.int_val, b->d.int_val); - break; - case POS_OP_MIN: - a->d.int_val = MIN (a->d.int_val, b->d.int_val); - break; - case POS_OP_NONE: - g_assert_not_reached (); - break; - } - } - else if (a->type == POS_EXPR_DOUBLE) - { - switch (op) - { - case POS_OP_MULTIPLY: - a->d.double_val = a->d.double_val * b->d.double_val; - break; - case POS_OP_DIVIDE: - if (b->d.double_val == 0.0) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_DIVIDE_BY_ZERO, - _("Coordinate expression results in division by zero")); - return FALSE; - } - a->d.double_val = a->d.double_val / b->d.double_val; - break; - case POS_OP_MOD: - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_MOD_ON_FLOAT, - _("Coordinate expression tries to use mod operator on a floating-point number")); - return FALSE; - case POS_OP_ADD: - a->d.double_val = a->d.double_val + b->d.double_val; - break; - case POS_OP_SUBTRACT: - a->d.double_val = a->d.double_val - b->d.double_val; - break; - case POS_OP_MAX: - a->d.double_val = MAX (a->d.double_val, b->d.double_val); - break; - case POS_OP_MIN: - a->d.double_val = MIN (a->d.double_val, b->d.double_val); - break; - case POS_OP_NONE: - g_assert_not_reached (); - break; - } - } - else - g_assert_not_reached (); - - return TRUE; -} - -static gboolean -do_operations (PosExpr *exprs, - int *n_exprs, - int precedence, - GError **err) -{ - int i; - -#if 0 - g_print ("Doing prec %d ops on %d exprs\n", precedence, *n_exprs); - debug_print_exprs (exprs, *n_exprs); -#endif - - i = 1; - while (i < *n_exprs) - { - gboolean compress; - - /* exprs[i-1] first operand - * exprs[i] operator - * exprs[i+1] second operand - * - * we replace first operand with result of mul/div/mod, - * or skip over operator and second operand if we have - * an add/subtract - */ - - if (exprs[i-1].type == POS_EXPR_OPERATOR) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression has an operator \"%s\" where an operand was expected"), - op_name (exprs[i-1].d.operator)); - return FALSE; - } - - if (exprs[i].type != POS_EXPR_OPERATOR) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression had an operand where an operator was expected")); - return FALSE; - } - - if (i == (*n_exprs - 1)) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression ended with an operator instead of an operand")); - return FALSE; - } - - g_assert ((i+1) < *n_exprs); - - if (exprs[i+1].type == POS_EXPR_OPERATOR) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression has operator \"%c\" following operator \"%c\" with no operand in between"), - exprs[i+1].d.operator, - exprs[i].d.operator); - return FALSE; - } - - compress = FALSE; - - switch (precedence) - { - case 2: - switch (exprs[i].d.operator) - { - case POS_OP_DIVIDE: - case POS_OP_MOD: - case POS_OP_MULTIPLY: - compress = TRUE; - if (!do_operation (&exprs[i-1], &exprs[i+1], - exprs[i].d.operator, - err)) - return FALSE; - break; - } - break; - case 1: - switch (exprs[i].d.operator) - { - case POS_OP_ADD: - case POS_OP_SUBTRACT: - compress = TRUE; - if (!do_operation (&exprs[i-1], &exprs[i+1], - exprs[i].d.operator, - err)) - return FALSE; - break; - } - break; - /* I have no rationale at all for making these low-precedence */ - case 0: - switch (exprs[i].d.operator) - { - case POS_OP_MAX: - case POS_OP_MIN: - compress = TRUE; - if (!do_operation (&exprs[i-1], &exprs[i+1], - exprs[i].d.operator, - err)) - return FALSE; - break; - } - break; - } - - if (compress) - { - /* exprs[i-1] first operand (now result) - * exprs[i] operator - * exprs[i+1] second operand - * exprs[i+2] new operator - * - * we move new operator just after first operand - */ - if ((i+2) < *n_exprs) - { - g_memmove (&exprs[i], &exprs[i+2], - sizeof (PosExpr) * (*n_exprs - i - 2)); - } - - *n_exprs -= 2; - } - else - { - /* Skip operator and next operand */ - i += 2; - } - } - - return TRUE; -} - -/** - * There is a predefined set of variables which can appear in an expression. - * Here we take a token representing a variable, and return the current value - * of that variable in a particular environment. - * (The value is always an integer.) - * - * There are supposedly some circumstances in which this function can be - * called from outside Metacity, in which case env->theme will be NULL, and - * therefore we can't use it to find out quark values, so we do the comparison - * using strcmp, which is slower. - * - * \param t The token representing a variable - * \param[out] result The value of that variable; not set if the token did - * not represent a known variable - * \param env The environment within which t should be evaluated - * \param[out] err set to the problem if there was a problem - * - * \return true if we found the variable asked for, false if we didn't - * - * \bug shouldn't t be const? - * \bug we should perhaps consider some sort of lookup arrangement into an - * array; also, the duplication of code is unlovely; perhaps using glib - * string hashes instead of quarks would fix both problems? - * \ingroup parser - */ -static gboolean -pos_eval_get_variable (PosToken *t, - int *result, - const MetaPositionExprEnv *env, - GError **err) -{ - if (env->theme) - { - if (t->d.v.name_quark == env->theme->quark_width) - *result = env->rect.width; - else if (t->d.v.name_quark == env->theme->quark_height) - *result = env->rect.height; - else if (env->object_width >= 0 && - t->d.v.name_quark == env->theme->quark_object_width) - *result = env->object_width; - else if (env->object_height >= 0 && - t->d.v.name_quark == env->theme->quark_object_height) - *result = env->object_height; - else if (t->d.v.name_quark == env->theme->quark_left_width) - *result = env->left_width; - else if (t->d.v.name_quark == env->theme->quark_right_width) - *result = env->right_width; - else if (t->d.v.name_quark == env->theme->quark_top_height) - *result = env->top_height; - else if (t->d.v.name_quark == env->theme->quark_bottom_height) - *result = env->bottom_height; - else if (t->d.v.name_quark == env->theme->quark_mini_icon_width) - *result = env->mini_icon_width; - else if (t->d.v.name_quark == env->theme->quark_mini_icon_height) - *result = env->mini_icon_height; - else if (t->d.v.name_quark == env->theme->quark_icon_width) - *result = env->icon_width; - else if (t->d.v.name_quark == env->theme->quark_icon_height) - *result = env->icon_height; - else if (t->d.v.name_quark == env->theme->quark_title_width) - *result = env->title_width; - else if (t->d.v.name_quark == env->theme->quark_title_height) - *result = env->title_height; - else - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_UNKNOWN_VARIABLE, - _("Coordinate expression had unknown variable or constant \"%s\""), - t->d.v.name); - return FALSE; - } - } - else - { - if (strcmp (t->d.v.name, "width") == 0) - *result = env->rect.width; - else if (strcmp (t->d.v.name, "height") == 0) - *result = env->rect.height; - else if (env->object_width >= 0 && - strcmp (t->d.v.name, "object_width") == 0) - *result = env->object_width; - else if (env->object_height >= 0 && - strcmp (t->d.v.name, "object_height") == 0) - *result = env->object_height; - else if (strcmp (t->d.v.name, "left_width") == 0) - *result = env->left_width; - else if (strcmp (t->d.v.name, "right_width") == 0) - *result = env->right_width; - else if (strcmp (t->d.v.name, "top_height") == 0) - *result = env->top_height; - else if (strcmp (t->d.v.name, "bottom_height") == 0) - *result = env->bottom_height; - else if (strcmp (t->d.v.name, "mini_icon_width") == 0) - *result = env->mini_icon_width; - else if (strcmp (t->d.v.name, "mini_icon_height") == 0) - *result = env->mini_icon_height; - else if (strcmp (t->d.v.name, "icon_width") == 0) - *result = env->icon_width; - else if (strcmp (t->d.v.name, "icon_height") == 0) - *result = env->icon_height; - else if (strcmp (t->d.v.name, "title_width") == 0) - *result = env->title_width; - else if (strcmp (t->d.v.name, "title_height") == 0) - *result = env->title_height; - else - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_UNKNOWN_VARIABLE, - _("Coordinate expression had unknown variable or constant \"%s\""), - t->d.v.name); - return FALSE; - } - } - - return TRUE; -} - -/** - * Evaluates a sequence of tokens within a particular environment context, - * and returns the current value. May recur if parantheses are found. - * - * \param tokens A list of tokens to evaluate. - * \param n_tokens How many tokens are in the list. - * \param env The environment context in which to evaluate the expression. - * \param[out] result The current value of the expression - * - * \bug Yes, we really do reparse the expression every time it's evaluated. - * We should keep the parse tree around all the time and just - * run the new values through it. - * \ingroup parser - */ -static gboolean -pos_eval_helper (PosToken *tokens, - int n_tokens, - const MetaPositionExprEnv *env, - PosExpr *result, - GError **err) -{ - /* Lazy-ass hardcoded limit on number of terms in expression */ -#define MAX_EXPRS 32 - int paren_level; - int first_paren; - int i; - PosExpr exprs[MAX_EXPRS]; - int n_exprs; - int precedence; - - /* Our first goal is to get a list of PosExpr, essentially - * substituting variables and handling parentheses. - */ - - first_paren = 0; - paren_level = 0; - n_exprs = 0; - for (i = 0; i < n_tokens; i++) - { - PosToken *t = &tokens[i]; - - if (n_exprs >= MAX_EXPRS) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression parser overflowed its buffer.")); - return FALSE; - } - - if (paren_level == 0) - { - switch (t->type) - { - case POS_TOKEN_INT: - exprs[n_exprs].type = POS_EXPR_INT; - exprs[n_exprs].d.int_val = t->d.i.val; - ++n_exprs; - break; - - case POS_TOKEN_DOUBLE: - exprs[n_exprs].type = POS_EXPR_DOUBLE; - exprs[n_exprs].d.double_val = t->d.d.val; - ++n_exprs; - break; - - case POS_TOKEN_OPEN_PAREN: - ++paren_level; - if (paren_level == 1) - first_paren = i; - break; - - case POS_TOKEN_CLOSE_PAREN: - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_BAD_PARENS, - _("Coordinate expression had a close parenthesis with no open parenthesis")); - return FALSE; - - case POS_TOKEN_VARIABLE: - exprs[n_exprs].type = POS_EXPR_INT; - - /* FIXME we should just dump all this crap - * in a hash, maybe keep width/height out - * for optimization purposes - */ - if (!pos_eval_get_variable (t, &exprs[n_exprs].d.int_val, env, err)) - return FALSE; - - ++n_exprs; - break; - - case POS_TOKEN_OPERATOR: - exprs[n_exprs].type = POS_EXPR_OPERATOR; - exprs[n_exprs].d.operator = t->d.o.op; - ++n_exprs; - break; - } - } - else - { - g_assert (paren_level > 0); - - switch (t->type) - { - case POS_TOKEN_INT: - case POS_TOKEN_DOUBLE: - case POS_TOKEN_VARIABLE: - case POS_TOKEN_OPERATOR: - break; - - case POS_TOKEN_OPEN_PAREN: - ++paren_level; - break; - - case POS_TOKEN_CLOSE_PAREN: - if (paren_level == 1) - { - /* We closed a toplevel paren group, so recurse */ - if (!pos_eval_helper (&tokens[first_paren+1], - i - first_paren - 1, - env, - &exprs[n_exprs], - err)) - return FALSE; - - ++n_exprs; - } - - --paren_level; - break; - - } - } - } - - if (paren_level > 0) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_BAD_PARENS, - _("Coordinate expression had an open parenthesis with no close parenthesis")); - return FALSE; - } - - /* Now we have no parens and no vars; so we just do all the multiplies - * and divides, then all the add and subtract. - */ - if (n_exprs == 0) - { - g_set_error (err, META_THEME_ERROR, - META_THEME_ERROR_FAILED, - _("Coordinate expression doesn't seem to have any operators or operands")); - return FALSE; - } - - /* precedence 1 ops */ - precedence = 2; - while (precedence >= 0) - { - if (!do_operations (exprs, &n_exprs, precedence, err)) - return FALSE; - --precedence; - } - - g_assert (n_exprs == 1); - - *result = *exprs; - - return TRUE; -} - -/* - * expr = int | double | expr * expr | expr / expr | - * expr + expr | expr - expr | (expr) - * - * so very not worth fooling with bison, yet so very painful by hand. - */ -/** - * Evaluates an expression. - * - * \param spec The expression to evaluate. - * \param env The environment context to evaluate the expression in. - * \param[out] val_p The integer value of the expression; if the expression - * is of type float, this will be rounded. If we return - * FALSE because the expression is invalid, this will be - * zero. - * \param[out] err The error, if anything went wrong. - * - * \return True if we evaluated the expression successfully; false otherwise. - * - * \bug Shouldn't spec be const? - * \ingroup parser - */ -static gboolean -pos_eval (MetaDrawSpec *spec, - const MetaPositionExprEnv *env, - int *val_p, - GError **err) -{ - PosExpr expr; - - *val_p = 0; - - if (pos_eval_helper (spec->tokens, spec->n_tokens, env, &expr, err)) - { - switch (expr.type) - { - case POS_EXPR_INT: - *val_p = expr.d.int_val; - break; - case POS_EXPR_DOUBLE: - *val_p = expr.d.double_val; - break; - case POS_EXPR_OPERATOR: - g_assert_not_reached (); - break; - } - return TRUE; - } - else - { - return FALSE; - } -} - /* We always return both X and Y, but only one will be meaningful in * most contexts. */ gboolean -meta_parse_position_expression (MetaDrawSpec *spec, +meta_parse_position_expression (MetaToken *spec, const MetaPositionExprEnv *env, int *x_return, int *y_return, @@ -2484,17 +1454,10 @@ meta_parse_position_expression (MetaDrawSpec *spec, */ int val; - if (spec->constant) - val = spec->value; - else + if (!meta_rpn_eval (spec, env, &val, err)) { - if (pos_eval (spec, env, &spec->value, err) == FALSE) - { - g_assert (err == NULL || *err != NULL); - return FALSE; - } - - val = spec->value; + g_assert (err == NULL || *err != NULL); + return FALSE; } if (x_return) @@ -2507,24 +1470,17 @@ meta_parse_position_expression (MetaDrawSpec *spec, gboolean -meta_parse_size_expression (MetaDrawSpec *spec, +meta_parse_size_expression (MetaToken *spec, const MetaPositionExprEnv *env, int *val_return, GError **err) { int val; - if (spec->constant) - val = spec->value; - else + if (!meta_rpn_eval (spec, env, &val, err)) { - if (pos_eval (spec, env, &spec->value, err) == FALSE) - { - g_assert (err == NULL || *err != NULL); - return FALSE; - } - - val = spec->value; + g_assert (err == NULL || *err != NULL); + return FALSE; } if (val_return) @@ -2533,6 +1489,7 @@ meta_parse_size_expression (MetaDrawSpec *spec, return TRUE; } +#if 0 /* not yet */ /* To do this we tokenize, replace variable tokens * that are constants, then reassemble. The purpose * here is to optimize expressions so we don't do hash @@ -2581,9 +1538,10 @@ meta_theme_replace_constants (MetaTheme *theme, return is_constant; } +#endif static int -parse_x_position_unchecked (MetaDrawSpec *spec, +parse_x_position_unchecked (MetaToken *spec, const MetaPositionExprEnv *env) { int retval; @@ -2603,7 +1561,7 @@ parse_x_position_unchecked (MetaDrawSpec *spec, } static int -parse_y_position_unchecked (MetaDrawSpec *spec, +parse_y_position_unchecked (MetaToken *spec, const MetaPositionExprEnv *env) { int retval; @@ -2623,7 +1581,7 @@ parse_y_position_unchecked (MetaDrawSpec *spec, } static int -parse_size_unchecked (MetaDrawSpec *spec, +parse_size_unchecked (MetaToken *spec, MetaPositionExprEnv *env) { int retval; @@ -2642,41 +1600,6 @@ parse_size_unchecked (MetaDrawSpec *spec, return retval; } -void -meta_draw_spec_free (MetaDrawSpec *spec) -{ - free_tokens (spec->tokens, spec->n_tokens); - g_slice_free (MetaDrawSpec, spec); -} - -MetaDrawSpec * -meta_draw_spec_new (MetaTheme *theme, - const char *expr, - GError **error) -{ - MetaDrawSpec *spec; - - spec = g_slice_new0 (MetaDrawSpec); - - pos_tokenize (expr, &spec->tokens, &spec->n_tokens, NULL); - - spec->constant = meta_theme_replace_constants (theme, spec->tokens, - spec->n_tokens, NULL); - if (spec->constant) - { - gboolean result; - - result = pos_eval (spec, NULL, &spec->value, error); - if (result == FALSE) - { - meta_draw_spec_free (spec); - return NULL; - } - } - - return spec; -} - MetaDrawOp* meta_draw_op_new (MetaDrawType type) { @@ -2761,37 +1684,37 @@ meta_draw_op_free (MetaDrawOp *op) if (op->data.line.color_spec) meta_color_spec_free (op->data.line.color_spec); - meta_draw_spec_free (op->data.line.x1); - meta_draw_spec_free (op->data.line.y1); - meta_draw_spec_free (op->data.line.x2); - meta_draw_spec_free (op->data.line.y2); + g_free (op->data.line.x1); + g_free (op->data.line.y1); + g_free (op->data.line.x2); + g_free (op->data.line.y2); break; case META_DRAW_RECTANGLE: if (op->data.rectangle.color_spec) g_free (op->data.rectangle.color_spec); - meta_draw_spec_free (op->data.rectangle.x); - meta_draw_spec_free (op->data.rectangle.y); - meta_draw_spec_free (op->data.rectangle.width); - meta_draw_spec_free (op->data.rectangle.height); + g_free (op->data.rectangle.x); + g_free (op->data.rectangle.y); + g_free (op->data.rectangle.width); + g_free (op->data.rectangle.height); break; case META_DRAW_ARC: if (op->data.arc.color_spec) g_free (op->data.arc.color_spec); - meta_draw_spec_free (op->data.arc.x); - meta_draw_spec_free (op->data.arc.y); - meta_draw_spec_free (op->data.arc.width); - meta_draw_spec_free (op->data.arc.height); + g_free (op->data.arc.x); + g_free (op->data.arc.y); + g_free (op->data.arc.width); + g_free (op->data.arc.height); break; case META_DRAW_CLIP: - meta_draw_spec_free (op->data.clip.x); - meta_draw_spec_free (op->data.clip.y); - meta_draw_spec_free (op->data.clip.width); - meta_draw_spec_free (op->data.clip.height); + g_free (op->data.clip.x); + g_free (op->data.clip.y); + g_free (op->data.clip.width); + g_free (op->data.clip.height); break; case META_DRAW_TINT: @@ -2801,10 +1724,10 @@ meta_draw_op_free (MetaDrawOp *op) if (op->data.tint.alpha_spec) meta_alpha_gradient_spec_free (op->data.tint.alpha_spec); - meta_draw_spec_free (op->data.tint.x); - meta_draw_spec_free (op->data.tint.y); - meta_draw_spec_free (op->data.tint.width); - meta_draw_spec_free (op->data.tint.height); + g_free (op->data.tint.x); + g_free (op->data.tint.y); + g_free (op->data.tint.width); + g_free (op->data.tint.height); break; case META_DRAW_GRADIENT: @@ -2814,10 +1737,10 @@ meta_draw_op_free (MetaDrawOp *op) if (op->data.gradient.alpha_spec) meta_alpha_gradient_spec_free (op->data.gradient.alpha_spec); - meta_draw_spec_free (op->data.gradient.x); - meta_draw_spec_free (op->data.gradient.y); - meta_draw_spec_free (op->data.gradient.width); - meta_draw_spec_free (op->data.gradient.height); + g_free (op->data.gradient.x); + g_free (op->data.gradient.y); + g_free (op->data.gradient.width); + g_free (op->data.gradient.height); break; case META_DRAW_IMAGE: @@ -2833,72 +1756,72 @@ meta_draw_op_free (MetaDrawOp *op) if (op->data.image.colorize_cache_pixbuf) g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf)); - meta_draw_spec_free (op->data.image.x); - meta_draw_spec_free (op->data.image.y); - meta_draw_spec_free (op->data.image.width); - meta_draw_spec_free (op->data.image.height); + g_free (op->data.image.x); + g_free (op->data.image.y); + g_free (op->data.image.width); + g_free (op->data.image.height); break; case META_DRAW_GTK_ARROW: - meta_draw_spec_free (op->data.gtk_arrow.x); - meta_draw_spec_free (op->data.gtk_arrow.y); - meta_draw_spec_free (op->data.gtk_arrow.width); - meta_draw_spec_free (op->data.gtk_arrow.height); + g_free (op->data.gtk_arrow.x); + g_free (op->data.gtk_arrow.y); + g_free (op->data.gtk_arrow.width); + g_free (op->data.gtk_arrow.height); break; case META_DRAW_GTK_BOX: - meta_draw_spec_free (op->data.gtk_box.x); - meta_draw_spec_free (op->data.gtk_box.y); - meta_draw_spec_free (op->data.gtk_box.width); - meta_draw_spec_free (op->data.gtk_box.height); + g_free (op->data.gtk_box.x); + g_free (op->data.gtk_box.y); + g_free (op->data.gtk_box.width); + g_free (op->data.gtk_box.height); break; case META_DRAW_GTK_VLINE: - meta_draw_spec_free (op->data.gtk_vline.x); - meta_draw_spec_free (op->data.gtk_vline.y1); - meta_draw_spec_free (op->data.gtk_vline.y2); + g_free (op->data.gtk_vline.x); + g_free (op->data.gtk_vline.y1); + g_free (op->data.gtk_vline.y2); break; case META_DRAW_ICON: if (op->data.icon.alpha_spec) meta_alpha_gradient_spec_free (op->data.icon.alpha_spec); - meta_draw_spec_free (op->data.icon.x); - meta_draw_spec_free (op->data.icon.y); - meta_draw_spec_free (op->data.icon.width); - meta_draw_spec_free (op->data.icon.height); + g_free (op->data.icon.x); + g_free (op->data.icon.y); + g_free (op->data.icon.width); + g_free (op->data.icon.height); break; case META_DRAW_TITLE: if (op->data.title.color_spec) meta_color_spec_free (op->data.title.color_spec); - meta_draw_spec_free (op->data.title.x); - meta_draw_spec_free (op->data.title.y); + g_free (op->data.title.x); + g_free (op->data.title.y); break; case META_DRAW_OP_LIST: if (op->data.op_list.op_list) meta_draw_op_list_unref (op->data.op_list.op_list); - meta_draw_spec_free (op->data.op_list.x); - meta_draw_spec_free (op->data.op_list.y); - meta_draw_spec_free (op->data.op_list.width); - meta_draw_spec_free (op->data.op_list.height); + g_free (op->data.op_list.x); + g_free (op->data.op_list.y); + g_free (op->data.op_list.width); + g_free (op->data.op_list.height); break; case META_DRAW_TILE: if (op->data.tile.op_list) meta_draw_op_list_unref (op->data.tile.op_list); - meta_draw_spec_free (op->data.tile.x); - meta_draw_spec_free (op->data.tile.y); - meta_draw_spec_free (op->data.tile.width); - meta_draw_spec_free (op->data.tile.height); - meta_draw_spec_free (op->data.tile.tile_xoffset); - meta_draw_spec_free (op->data.tile.tile_yoffset); - meta_draw_spec_free (op->data.tile.tile_width); - meta_draw_spec_free (op->data.tile.tile_height); + g_free (op->data.tile.x); + g_free (op->data.tile.y); + g_free (op->data.tile.width); + g_free (op->data.tile.height); + g_free (op->data.tile.tile_xoffset); + g_free (op->data.tile.tile_yoffset); + g_free (op->data.tile.tile_width); + g_free (op->data.tile.tile_height); break; } @@ -4300,7 +3223,7 @@ meta_frame_style_draw_with_style (MetaFrameStyle *style, GdkRectangle left_edge, right_edge, bottom_edge; PangoRectangle extents; MetaDrawInfo draw_info; - + g_return_if_fail (style_gtk->colormap == gdk_drawable_get_colormap (drawable)); titlebar_rect.x = 0; @@ -4523,6 +3446,7 @@ meta_frame_style_draw_with_style (MetaFrameStyle *style, ++i; } + } void diff --git a/src/ui/theme.h b/src/ui/theme.h index ddf777d4..ae827de8 100644 --- a/src/ui/theme.h +++ b/src/ui/theme.h @@ -42,6 +42,7 @@ typedef struct _MetaFrameGeometry MetaFrameGeometry; typedef struct _MetaTheme MetaTheme; typedef struct _MetaPositionExprEnv MetaPositionExprEnv; typedef struct _MetaDrawInfo MetaDrawInfo; +typedef enum MetaToken MetaToken; #define META_THEME_ERROR (g_quark_from_static_string ("meta-theme-error")) @@ -330,87 +331,6 @@ typedef enum META_DRAW_TILE } MetaDrawType; -typedef enum -{ - POS_TOKEN_INT, - POS_TOKEN_DOUBLE, - POS_TOKEN_OPERATOR, - POS_TOKEN_VARIABLE, - POS_TOKEN_OPEN_PAREN, - POS_TOKEN_CLOSE_PAREN -} PosTokenType; - -typedef enum -{ - POS_OP_NONE, - POS_OP_ADD, - POS_OP_SUBTRACT, - POS_OP_MULTIPLY, - POS_OP_DIVIDE, - POS_OP_MOD, - POS_OP_MAX, - POS_OP_MIN -} PosOperatorType; - -/** - * A token, as output by the tokeniser. - * - * \ingroup tokenizer - */ -typedef struct -{ - PosTokenType type; - - union - { - struct { - int val; - } i; - - struct { - double val; - } d; - - struct { - PosOperatorType op; - } o; - - struct { - char *name; - GQuark name_quark; - } v; - - } d; -} PosToken; - -/** - * A computed expression in our simple vector drawing language. - * While it appears to take the form of a tree, this is actually - * merely a list; concerns such as precedence of operators are - * currently recomputed on every recalculation. - * - * Created by meta_draw_spec_new(), destroyed by meta_draw_spec_free(). - * pos_eval() fills this with ...FIXME. Are tokens a tree or a list? - * \ingroup parser - */ -typedef struct _MetaDrawSpec -{ - /** - * If this spec is constant, this is the value of the constant; - * otherwise it is zero. - */ - int value; - - /** A list of tokens in the expression. */ - PosToken *tokens; - - /** How many tokens are in the tokens list. */ - int n_tokens; - - /** Does the expression contain any variables? */ - gboolean constant : 1; -} MetaDrawSpec; - /** * A single drawing operation in our simple vector drawing language. */ @@ -426,65 +346,65 @@ struct _MetaDrawOp int dash_on_length; int dash_off_length; int width; - MetaDrawSpec *x1; - MetaDrawSpec *y1; - MetaDrawSpec *x2; - MetaDrawSpec *y2; + MetaToken *x1; + MetaToken *y1; + MetaToken *x2; + MetaToken *y2; } line; struct { MetaColorSpec *color_spec; gboolean filled; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; + MetaToken *x; + MetaToken *y; + MetaToken *width; + MetaToken *height; } rectangle; struct { MetaColorSpec *color_spec; gboolean filled; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; + MetaToken *x; + MetaToken *y; + MetaToken *width; + MetaToken *height; double start_angle; double extent_angle; } arc; struct { - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; + MetaToken *x; + MetaToken *y; + MetaToken *width; + MetaToken *height; } clip; struct { MetaColorSpec *color_spec; MetaAlphaGradientSpec *alpha_spec; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; + MetaToken *x; + MetaToken *y; + MetaToken *width; + MetaToken *height; } tint; struct { MetaGradientSpec *gradient_spec; MetaAlphaGradientSpec *alpha_spec; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; + MetaToken *x; + MetaToken *y; + MetaToken *width; + MetaToken *height; } gradient; struct { MetaColorSpec *colorize_spec; MetaAlphaGradientSpec *alpha_spec; GdkPixbuf *pixbuf; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; + MetaToken *x; + MetaToken *y; + MetaToken *width; + MetaToken *height; guint32 colorize_cache_pixel; GdkPixbuf *colorize_cache_pixbuf; @@ -499,61 +419,61 @@ struct _MetaDrawOp GtkArrowType arrow; gboolean filled; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; + MetaToken *x; + MetaToken *y; + MetaToken *width; + MetaToken *height; } gtk_arrow; struct { GtkStateType state; GtkShadowType shadow; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; + MetaToken *x; + MetaToken *y; + MetaToken *width; + MetaToken *height; } gtk_box; struct { GtkStateType state; - MetaDrawSpec *x; - MetaDrawSpec *y1; - MetaDrawSpec *y2; + MetaToken *x; + MetaToken *y1; + MetaToken *y2; } gtk_vline; struct { MetaAlphaGradientSpec *alpha_spec; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; + MetaToken *x; + MetaToken *y; + MetaToken *width; + MetaToken *height; MetaImageFillType fill_type; } icon; struct { MetaColorSpec *color_spec; - MetaDrawSpec *x; - MetaDrawSpec *y; + MetaToken *x; + MetaToken *y; } title; struct { MetaDrawOpList *op_list; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; + MetaToken *x; + MetaToken *y; + MetaToken *width; + MetaToken *height; } op_list; struct { MetaDrawOpList *op_list; - MetaDrawSpec *x; - MetaDrawSpec *y; - MetaDrawSpec *width; - MetaDrawSpec *height; - MetaDrawSpec *tile_xoffset; - MetaDrawSpec *tile_yoffset; - MetaDrawSpec *tile_width; - MetaDrawSpec *tile_height; + MetaToken *x; + MetaToken *y; + MetaToken *width; + MetaToken *height; + MetaToken *tile_xoffset; + MetaToken *tile_yoffset; + MetaToken *tile_width; + MetaToken *tile_height; } tile; } data; @@ -865,20 +785,19 @@ void meta_frame_layout_calc_geometry (const MetaFrameLayout *layout gboolean meta_frame_layout_validate (const MetaFrameLayout *layout, GError **error); -gboolean meta_parse_position_expression (MetaDrawSpec *spec, +gboolean meta_parse_position_expression (MetaToken *spec, const MetaPositionExprEnv *env, int *x_return, int *y_return, GError **err); -gboolean meta_parse_size_expression (MetaDrawSpec *spec, +gboolean meta_parse_size_expression (MetaToken *spec, const MetaPositionExprEnv *env, int *val_return, GError **err); -MetaDrawSpec* meta_draw_spec_new (MetaTheme *theme, +MetaToken* meta_draw_spec_new (MetaTheme *theme, const char *expr, GError **error); -void meta_draw_spec_free (MetaDrawSpec *spec); MetaColorSpec* meta_color_spec_new (MetaColorSpecType type); MetaColorSpec* meta_color_spec_new_from_string (const char *str, @@ -1128,10 +1047,12 @@ gboolean meta_theme_lookup_color_constant (MetaTheme *theme, const char *name, char **value); +#if 0 gboolean meta_theme_replace_constants (MetaTheme *theme, PosToken *tokens, int n_tokens, GError **err); +#endif /* random stuff */ |