Index: gimpsizeentry.c
===================================================================
--- gimpsizeentry.c	(revision 24776)
+++ gimpsizeentry.c	(working copy)
@@ -25,7 +25,10 @@
 
 #include <gtk/gtk.h>
 
+#include <string.h>
+
 #include "libgimpbase/gimpbase.h"
+#include "libgimpmath/gimpmath.h"
 
 #include "gimpwidgets.h"
 
@@ -86,6 +89,18 @@ static void   gimp_size_entry_update_uni
 static void   gimp_size_entry_unit_callback   (GtkWidget          *widget,
                                                GimpSizeEntry      *sizeentry);
 
+/* input validation / evaluation */
+static gint   gimp_size_entry_input_callback  (GtkSpinButton      *spinner,
+                                               gdouble            *return_val,
+                                               GimpSizeEntryField *gsef);
+static GimpEevlQuantity
+              gimp_size_entry_unit_resolver   (const gchar        *ident,
+                                               gint                len_ident,
+                                               gpointer            data);
+static GimpEevlQuantity
+              gimp_size_entry_var_resolver    (const gchar        *ident,
+                                               gint                len_ident,
+                                               gpointer            data);
 
 G_DEFINE_TYPE (GimpSizeEntry, gimp_size_entry, GTK_TYPE_TABLE)
 
@@ -288,6 +303,13 @@ gimp_size_entry_new (gint               
                                                      1.0, 10.0, 0.0,
                                                      1.0, digits);
 
+      /* non-numeric input allows expression evaluation */
+      gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (gsef->value_spinbutton),
+                                   FALSE);
+      g_signal_connect (gsef->value_spinbutton, "input",
+                        G_CALLBACK (gimp_size_entry_input_callback),
+                        gsef);
+
       if (spinbutton_width > 0)
         {
           if (spinbutton_width < 17)
@@ -404,6 +426,15 @@ gimp_size_entry_add_field  (GimpSizeEntr
                     G_CALLBACK (gimp_size_entry_value_callback),
                     gsef);
 
+  /* non-numeric input allows expression evaluation */
+  gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (gsef->value_spinbutton),
+                               FALSE);
+  gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (gsef->value_spinbutton),
+                                     GTK_UPDATE_IF_VALID);
+  g_signal_connect (gsef->value_spinbutton, "input",
+                    G_CALLBACK (gimp_size_entry_input_callback),
+                    gsef);
+
   if (gse->show_refval)
     {
       gsef->refval_adjustment =
@@ -1269,3 +1300,134 @@ gimp_size_entry_get_help_widget (GimpSiz
   return (gsef->refval_spinbutton ?
           gsef->refval_spinbutton : gsef->value_spinbutton);
 }
+
+static GimpEevlQuantity
+gimp_size_entry_var_resolver (const gchar *ident,
+                               gint         len_ident,
+                               gpointer     data)
+{
+  return gimp_eevl_quantity_invalid ();
+}
+
+static GimpEevlQuantity
+gimp_size_entry_unit_resolver (const gchar *ident,
+                               gint         len_ident,
+                               gpointer     data)
+{
+  GimpEevlQuantity    invalid_unit;
+  GimpSizeEntryField *gsef;
+  GimpSizeEntry      *gse;
+  GimpUnit            unit;
+  gint                units;
+  
+  gsef = (GimpSizeEntryField*) data;
+
+  invalid_unit = gimp_eevl_quantity_invalid ();
+
+  g_return_val_if_fail (gsef, invalid_unit);
+  
+  gse = gsef->gse;
+
+  g_return_val_if_fail (GIMP_IS_SIZE_ENTRY (gse), invalid_unit);
+
+  units = gimp_unit_get_number_of_units ();
+
+  for (unit = 0; unit <= units; unit++)
+    {
+      const gchar *symbol;
+      const gchar *abbrev;
+      gint         len_symbol;
+      gint         len_abbrev;
+      
+      /* a shortcut to handling percent within the loop */
+      if (unit == units)
+        unit = GIMP_UNIT_PERCENT;
+
+      symbol = gimp_unit_get_symbol (unit);
+      abbrev = gimp_unit_get_abbreviation (unit);
+      len_symbol = strlen (symbol);
+      len_abbrev = strlen (abbrev);
+
+      if (   (len_symbol == len_ident
+              && 0  ==  strncmp (symbol, ident, len_ident))
+          || (len_abbrev == len_ident
+              && 0 == strncmp (abbrev, ident, len_ident)))
+        {
+          /* either the abbreviation or symbol matched. */
+          GimpEevlQuantity eevl_unit = {1, 1};
+          switch (unit)
+            {
+            case GIMP_UNIT_PIXEL:
+              eevl_unit.val = gsef->resolution;
+              break;
+            case GIMP_UNIT_PERCENT:
+              /* percent is a unitless factor of 1/100, i.e 2in*50 % = 1in */
+              eevl_unit.val = 100;
+              eevl_unit.space = 0;
+              break;
+            default:
+              eevl_unit.val = gimp_unit_get_factor (unit);
+            }
+            return eevl_unit;
+        }
+    }
+
+  return invalid_unit;
+}
+
+static gint
+gimp_size_entry_input_callback (GtkSpinButton      *spinner,
+                                gdouble            *return_val,
+                                GimpSizeEntryField *gsef)
+{
+  GimpSizeEntry    *gse;
+  GimpEevlQuantity  result;
+  GimpEevlQuantity  ui_unit = {1, 1};
+
+  const gchar      *errptr = 0;
+  const gchar      *errstr = 0;
+
+  g_return_val_if_fail (gsef, FALSE);
+
+  gse = gsef->gse;
+
+  g_return_val_if_fail (GTK_IS_SPIN_BUTTON (spinner), FALSE);
+  g_return_val_if_fail (GIMP_IS_SIZE_ENTRY (gse), FALSE);
+
+  switch (gse->unit)
+    {
+    case GIMP_UNIT_PIXEL:
+      ui_unit.val = gsef->resolution;
+      break;
+    case GIMP_UNIT_PERCENT:
+      ui_unit.space = 0;
+      break;
+    default:
+      ui_unit.val = gimp_unit_get_factor(gse->unit);
+    }
+
+  result = gimp_eevl_evaluate (gtk_entry_get_text (GTK_ENTRY (spinner)),
+                               ui_unit,
+                               gsef->resolution,
+                               gimp_size_entry_var_resolver,
+                               gimp_size_entry_unit_resolver,
+                               gsef,
+                               &errptr, &errstr);
+  if (errptr)
+    {
+      g_print ("ERROR: %s before '%s'\n", errstr,
+               *errptr ? errptr : "<End of input>");
+      return GTK_INPUT_ERROR;
+    }
+
+  if (result.space != 1)
+    {
+      g_print ("ERROR: result has wrong dimension (%d)\n", result.space);
+      return GTK_INPUT_ERROR;
+    }
+
+  /* transform back to UI-unit */
+  *return_val = result.val * ui_unit.val;
+  return TRUE;
+
+}
