metacity r4108 - in branches/rpnparser: . src src/ui



Author: tthurman
Date: Tue Feb  3 00:37:03 2009
New Revision: 4108
URL: http://svn.gnome.org/viewvc/metacity?rev=4108&view=rev

Log:
        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:



Modified:
   branches/rpnparser/ChangeLog
   branches/rpnparser/src/Makefile.am
   branches/rpnparser/src/ui/theme-parser.c
   branches/rpnparser/src/ui/theme.c
   branches/rpnparser/src/ui/theme.h

Modified: branches/rpnparser/src/Makefile.am
==============================================================================
--- branches/rpnparser/src/Makefile.am	(original)
+++ branches/rpnparser/src/Makefile.am	Tue Feb  3 00:37:03 2009
@@ -96,6 +96,8 @@
 	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 @@
 	ui/preview-widget.h			\
 	ui/theme-parser.c			\
 	ui/theme-parser.h			\
+	ui/rpn.c				\
+	ui/rpn.h				\
 	ui/theme.c				\
 	ui/theme.h
 

Modified: branches/rpnparser/src/ui/theme-parser.c
==============================================================================
--- branches/rpnparser/src/ui/theme-parser.c	(original)
+++ branches/rpnparser/src/ui/theme-parser.c	Tue Feb  3 00:37:03 2009
@@ -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 @@
 
       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 @@
       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 @@
 
       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 @@
 #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 @@
       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 @@
       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 @@
       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 @@
       
       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 @@
       
       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 @@
       
       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 @@
       
       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 @@
 
       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 @@
       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 @@
 
       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;      
       

Modified: branches/rpnparser/src/ui/theme.c
==============================================================================
--- branches/rpnparser/src/ui/theme.c	(original)
+++ branches/rpnparser/src/ui/theme.c	Tue Feb  3 00:37:03 2009
@@ -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 @@
     }
 }
 
-/**
- * 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 @@
    */
   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 @@
 
 
 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 @@
   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 @@
 
   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 @@
 }
 
 static int
-parse_y_position_unchecked (MetaDrawSpec              *spec,
+parse_y_position_unchecked (MetaToken                 *spec,
                             const MetaPositionExprEnv *env)
 {
   int retval;
@@ -2623,7 +1581,7 @@
 }
 
 static int
-parse_size_unchecked (MetaDrawSpec        *spec,
+parse_size_unchecked (MetaToken           *spec,
                       MetaPositionExprEnv *env)
 {
   int retval;
@@ -2642,41 +1600,6 @@
   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 @@
       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 @@
       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 @@
       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 @@
       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 @@
   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 @@
       
       ++i;
     }
+
 }
 
 void

Modified: branches/rpnparser/src/ui/theme.h
==============================================================================
--- branches/rpnparser/src/ui/theme.h	(original)
+++ branches/rpnparser/src/ui/theme.h	Tue Feb  3 00:37:03 2009
@@ -42,6 +42,7 @@
 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 @@
   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 @@
       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 @@
       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 @@
 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 @@
                                            const char  *name,
                                            char       **value);
 
+#if 0
 gboolean     meta_theme_replace_constants     (MetaTheme    *theme,
                                                PosToken     *tokens,
                                                int           n_tokens,
                                                GError      **err);
+#endif
 
 /* random stuff */
 



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