summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--src/Makefile.am4
-rw-r--r--src/ui/theme-parser.c115
-rw-r--r--src/ui/theme.c1228
-rw-r--r--src/ui/theme.h205
5 files changed, 214 insertions, 1351 deletions
diff --git a/ChangeLog b/ChangeLog
index 6504fad3..59e998bc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 */