Index: ChangeLog
===================================================================
--- ChangeLog	(revision 1776)
+++ ChangeLog	(working copy)
@@ -8,6 +8,22 @@
 gcalctool change history.
 =========================
 
+2007-11-2 Robert Ancell <robert.ancell@gmail.com>
+
+    * gcalctool/gtk.c:
+      glade/gcalctool.glade:
+      More work on bug #488694 - Move all popup menus into gcalctool.glade.
+      Split constant and function dialogs into seperate UI elements.
+
+    * gcalctool/graphics.c:
+      gcalctool/calctool.c:
+      gcalctool/calctool.h:
+      gcalctool/display.c:
+      gcalctool/functions.c:      
+      gcalctool/gtk.c:
+      glade/gcalctool.glade:      
+      More work on bug #488694 - Simplify menu code
+
 2007-10-31 Rich Burridge <rich.burridge@sun.com>
 
     * gcalctool/dsfuns.c:
@@ -18,11 +34,6 @@
       Code cleanup to a consistent style, plus fixup for various warnings
       from lint.
 
-    * gcalctool/gtk.c:
-      glade/gcalctool.glade:
-      More work on bug #488694 - Move all popup menus into gcalctool.glade.
-      Split constant and function dialogs into seperate UI elements.
-
 2007-10-31 Robert Ancell <robert.ancell@gmail.com>
 
     * gcalctool/mpmath.c:
Index: gcalctool/graphics.c
===================================================================
--- gcalctool/graphics.c	(revision 1775)
+++ gcalctool/graphics.c	(working copy)
@@ -28,34 +28,8 @@
 #include "lr_parser.h"
 #include "functions.h"
 
-/* Process menu selection. */
 
 void
-handle_menu_selection(struct button *n, int item)
-{
-    if (item != -1) {    
-        struct exprm_state *e;
-
-	v->pending = n->id;
-	if (v->current != NULL) {
-	    free(v->current);
-	}
-
-	e = get_state();
-	memcpy(&(e->button), n, sizeof(struct button));
-	e->value = v->current_value;
-	new_state();
-	
-	v->current = copy_button_info(n);
-	v->ismenu = 1;       /* To prevent grey buttons being redrawn. */
-	do_pending();
-	v->ismenu = 0;
-	v->down = 0;
-    }
-}
-
-
-void
 make_registers()            /* Calculate memory register frame values. */
 {
     char *mval;
Index: gcalctool/calctool.c
===================================================================
--- gcalctool/calctool.c	(revision 1775)
+++ gcalctool/calctool.c	(working copy)
@@ -200,37 +200,37 @@
     KEY_START_BLOCK,
     "(", /* Do not translate this as the equation solver expects this character always */
     do_paren,
-    parenthesis
+    none
 },
 {
     KEY_END_BLOCK,
     ")", /* Do not translate this as the equation solver expects this character always */
     do_paren,
-    parenthesis
+    none
 },
 {
     KEY_ADD,
     N_("+"),
     do_calc,
-    binop
+    none
 },
 {
     KEY_SUBTRACT,
     N_("-"),
     do_calc,
-    unop | binop
+    none
 },
 {
     KEY_MULTIPLY,
     N_("*"),
     do_calc,
-    binop
+    none
 },
 {
     KEY_DIVIDE,
     N_("/"),
     do_calc,
-    binop
+    none
 },
 {
     KEY_BACKSPACE,
@@ -260,13 +260,13 @@
     KEY_PERCENTAGE,
     N_("%"),
     do_percent,  
-    immediate
+    none
 },
 {
     KEY_SQUARE,
     N_("^2"),
     do_immed,  
-    immediate | postfixop
+    postfixop
 },
 {
     KEY_SQUARE_ROOT,
@@ -284,7 +284,7 @@
     KEY_E_POW_X,
     N_("e^"),
     do_immed, 
-    immediate | prefixop
+    prefixop
 },
 {
     KEY_10_POW_X,
@@ -296,13 +296,13 @@
     KEY_X_POW_Y,
     N_("^"),
     do_calc,
-    binop | postfixop
+    postfixop
 },
 {
     KEY_FACTORIAL,
     N_("!"),
     do_immed, 
-    immediate | postfixop
+    postfixop
 },
 {
     KEY_RANDOM,
@@ -363,7 +363,7 @@
     KEY_MODULUS_DIVIDE,
     N_(" Mod "),
     do_calc,
-    binop
+    none
 },
 {
     KEY_EXPONENTIAL,
@@ -375,31 +375,31 @@
     KEY_NOT,
     N_("~"),
     do_immed, 
-    unop | immediate
+    none
 },
 {
     KEY_OR,
     N_(" OR "),
     do_calc,
-    binop
+    none
 },
 {
     KEY_AND,
     N_(" AND "),
     do_calc,
-    binop
+    none
 },       
 {
     KEY_XOR,
     N_(" XOR "),
     do_calc,
-    binop
+    none
 },
 {
     KEY_XNOR,
     N_(" XNOR "),
     do_calc,
-    binop
+    none
 },
 {
     KEY_FINC_CTRM,
@@ -458,50 +458,50 @@
 {
     KEY_LEFT_SHIFT,
     NULL,
-    do_pending,
-    pending
+    do_lshift,
+    none
 },
 {
     KEY_RIGHT_SHIFT,
     NULL,
-    do_pending,
-    pending
+    do_rshift,
+    none
 },
 {
     KEY_STORE,
     NULL,
-    do_pending,
-    pending
+    do_sto,
+    none
 },
 {
     KEY_RECALL,
     NULL,
-    do_pending,
-    pending
+    do_rcl,
+    regrcl
 },
 {
     KEY_EXCHANGE,
     NULL,
-    do_pending,
-    pending
+    do_exchange,
+    none
 },
 {
-    KEY_ACCURACY_MENU,
+    KEY_SET_ACCURACY,
     NULL,
-    do_pending,
-    pending
+    do_accuracy,
+    none
 },
 {
-    KEY_CONSTANTS_MENU,
+    KEY_CONSTANT,
     NULL,
-    do_pending,
-    pending
+    do_constant,
+    con
 },
 {
-    KEY_FUNCTIONS_MENU,
+    KEY_FUNCTION,
     NULL,
-    do_pending,
-    pending
+    do_function,
+    none
 },
 };
 
@@ -547,15 +547,13 @@
     read_cfdefs();             /* Read constant/function definitions. */
     make_frames();             /* Create gcalctool window frames. */
 
-    v->current    = copy_button_info(&buttons[KEY_CALCULATE]);
+    v->current    = KEY_CALCULATE;
     v->shelf      = NULL;      /* No selection for shelf initially. */
     v->noparens   = 0;         /* No unmatched brackets initially. */
     v->opsptr     = 0;         /* Nothing on the parentheses op stack. */
     v->numsptr    = 0;         /* Nothing on the parenthese numeric stack. */
-    v->pending    = -1;        /* No initial pending command. */
     v->hyperbolic = 0;         /* Normal trig functions initially. */
     v->inverse    = 0;         /* No inverse functions initially. */
-    v->down       = 0;         /* No mouse presses initially. */
     v->warn_change_mode = 1;   /* Warn user when changing modes. */
 
     srand48((long) time((time_t *) 0));   /* Seed random number generator. */
Index: gcalctool/calctool.h
===================================================================
--- gcalctool/calctool.h	(revision 1775)
+++ gcalctool/calctool.h	(working copy)
@@ -65,10 +65,6 @@
 enum item_type { BASEITEM, TTYPEITEM, NUMITEM,
                  HYPITEM,  INVITEM,   OPITEM,  MODEITEM };
 
-/* Popup menu types. */
-enum menu_type { M_ACC,  M_CON,  M_EXCH, M_FUN,  M_LSHF,
-                 M_RCL,  M_RSHF, M_STO, M_NONE };
-
 /* Calculator modes. */
 enum mode_type { BASIC, ADVANCED, FINANCIAL, SCIENTIFIC };
 
@@ -158,9 +154,9 @@
     KEY_STORE,
     KEY_RECALL,
     KEY_EXCHANGE,
-    KEY_ACCURACY_MENU,
-    KEY_CONSTANTS_MENU,
-    KEY_FUNCTIONS_MENU,
+    KEY_SET_ACCURACY,
+    KEY_CONSTANT,
+    KEY_FUNCTION,
     NKEYS
 };
 
@@ -179,15 +175,11 @@
 #define MAX_DIGITS     200         /* Maximum displayable number of digits. */
 #define MAX_LOCALIZED  (MAX_DIGITS * (1 + MB_LEN_MAX) + MB_LEN_MAX)
 
-/* Maximum number of various graphics pieces. */
-#define MAXITEMS       8          /* Maximum number of panel items. */
-#define MAXMENUS       9          /* Maximum number of popup menus. */
-
 #ifndef MAXLINE
 #define MAXLINE        512        /* Length of character strings. */
 #endif /*MAXLINE*/
 
-#define MAXACC         99     /* Max. number of digits after numeric point. */
+#define MAXACC         99         /* Max. number of digits after numeric point. */
 #define MAXBASES       4          /* Maximum number of numeric bases. */
 #define MAXCONFUN      10         /* Maximum number of constants/functions. */
 #define MAXDISPMODES   3          /* Maximum number of display modes. */
@@ -224,13 +216,8 @@
 
 enum button_flags {
     none         = 0,          /* No flags */
-    binop        = 1,          /* Is binary operation ie. A op B */ 
-    unop         = (1 << 1),   /* Is unary operation ie. op A. */
     enter        = (1 << 2),   /* Expression is entered */
     number       = (1 << 3),   /* Number button */
-    immediate    = (1 << 4),   /* Button does immediate function */
-
-    parenthesis  = (1 << 5),   /* Parenthesis */
     func         = (1 << 6),   /* Function */
     bsp          = (1 << 7),   /* Backspace */
     clear        = (1 << 8),   /* Clear display */
@@ -241,8 +228,7 @@
     expnum       = (1 << 13),  /* Exponential number */
     postfixop    = (1 << 14),  /* Unary postfix operation */
     prefixop     = (1 << 15),  /* Unary prefix operation */
-    dpoint       = (1 << 16),  /* Decimal point */
-    pending      = (1 << 17),  /* Is a pending button */
+    dpoint       = (1 << 16)   /* Decimal point */
 };
 
 enum shiftd {
@@ -287,7 +273,7 @@
 struct calcVars {                      /* Calctool variables and options. */
     struct exprm_state_history h;      /* History of expression mode states */
 
-    struct button *current;            /* Current button/character pressed. */
+    int current;                       /* Current button/character pressed. */
   
     char *appname;                     /* Application name for resources. */
     char con_names[MAXREGS][MAXLINE];  /* Selectable constant names. */
@@ -333,7 +319,6 @@
     int beep;          /* Indicates whether there is a beep sound on error. */
     int cur_op;        /* Current arithmetic operation. */
     int doing_mi;      /* Set if adjusting the "show zeroes" menu item. */
-    int down;          /* Indicates is a mouse button is down. */
     int error;         /* Indicates some kind of display error. */
     int ghost_zero;    /* Flag to indicate display with "0", actually 
                            having empty content. */
@@ -341,7 +326,6 @@
     int hyperbolic;    /* If set, trig functions will be hyperbolic. */
     int iconic;        /* Set if window is currently iconic. */
     int inverse;       /* If set, trig and log functions will be inversed. */
-    int ismenu;        /* Set when do_pending called via a popup menu. */
     int key_exp;       /* Set if entering exponent number. */
     int ndisplay;      /* Height of the numerical display. */
     int new_input;     /* New number input since last op. */
@@ -350,7 +334,6 @@
     int old_cal_value;      /* Previous calculation operator. */
     int opsptr;        /* Pointer into the parentheses operand stack. */
     int opstack[MAXSTACK];  /* Stack containing parentheses input. */
-    int pending;            /* Set for command depending on multiple presses. */
     int pointed;       /* Whether a decimal point has been given. */
     int rstate;        /* Indicates if memory register frame is displayed. */
     int show_paren;    /* Set if we wish to show DISPLAYITEM during parens. */
@@ -360,8 +343,6 @@
     int toclear;       /* Indicates if display should be cleared. */
     int warn_change_mode;    /* Should we warn user when changing modes? */
     int bitcalculating_mode;  /* 0 = no, else yes */
-    
-    int current_value; // FIXME
 };
 
 typedef struct calcVars *Vars;
@@ -377,7 +358,6 @@
 #define dmin(a, b)  (double) min(a, b)
 
 struct button *button_for_value(int);
-struct button *copy_button_info(struct button *);
 
 void syntaxdep_show_display();
 char *button_str(int);
@@ -396,12 +376,10 @@
 
 int button_mods(int);
 int button_value(int);
-int char_val(char);
 int do_rcl_reg(int reg, int value[MP_SIZE]);
 int do_sto_reg(int reg, int value[MP_SIZE]);
 int do_tfunc(int s[MP_SIZE], int t[MP_SIZE], enum trig_func tfunc);
 int get_int_resource(enum res_type, int *);
-int get_menu_entry(enum menu_type, int);
 int main(int, char **);
 
 void beep();
@@ -425,7 +403,14 @@
 void do_none();
 void do_number();
 void do_paren();
-void do_pending();
+void do_lshift();
+void do_rshift();
+void do_sto();
+void do_rcl();
+void do_exchange();
+void do_accuracy();
+void do_constant();
+void do_function();
 void do_point();
 void do_portion();
 void do_trig();
@@ -437,7 +422,6 @@
 void get_function(int);
 void get_options(int, char **);
 void grey_buttons(enum base_type);
-void handle_menu_selection(struct button *, int);
 void initialise();
 void init_args();
 void init_frame_sizes();
@@ -453,7 +437,7 @@
 void mperr();
 void MPstr_to_num(char *, enum base_type, int *);
 void paren_disp(int);
-void process_item(struct button *);
+void process_item(struct button *, int);
 void process_str(char *);
 void push_num(int *);
 void push_op(int);
@@ -477,7 +461,6 @@
 void show_change_mode_dialog();
 void show_display(int *);
 void show_error(char *);
-void show_menu();
 void srand48();
 void start_tool();
 void str_replace(char **, char *, char *);
Index: gcalctool/display.c
===================================================================
--- gcalctool/display.c	(revision 1775)
+++ gcalctool/display.c	(working copy)
@@ -91,7 +91,7 @@
 }
 
 
-int
+static int
 char_val(char chr)
 {
     if (chr >= '0' && chr <= '9') {
@@ -131,22 +131,6 @@
 }
 
 
-/* FIXME: not a right location for this function. */
-
-struct button *
-copy_button_info(struct button *old)
-{
-    struct button *new;
-
-    int len = sizeof(struct button);
-    new = malloc(sizeof(struct button));
-    assert(new);
-    memcpy(new, old, len);
-
-    return(new);
-}
-
-
 void
 initialise()
 {
@@ -158,7 +142,6 @@
     v->error         = 0;           /* Currently no display error. */
     v->cur_op        = -1;         /* No arithmetic operator defined yet. */
     v->old_cal_value = -1;
-    v->pending       = -1;
     i = 0;
     mpcim(&i, v->MPresult);         /* No previous result yet. */
     mpcim(&i, v->MPdisp_val);         
@@ -484,12 +467,10 @@
 
     n = strlen(v->display);
     text = buttons[key].symname;
-    switch (key)
-    {
+    switch (key) {
     case -1:
     case KEY_CLEAR:
         v->noparens = v->opsptr = v->numsptr = 0;
-        v->pending = -1;
         v->cur_op = -1;
         i = 0;
         mpcim(&i, v->MPdisp_val);
@@ -506,14 +487,13 @@
             v->noparens--;
             if (!v->noparens) {
                 v->opsptr = v->numsptr = 0;
-                v->pending = -1;
                 v->cur_op = -1;
                 show_display(v->MPdisp_val);
                 return;
             }
         } else if (v->display[n-1] == ')') v->noparens++;
         v->display[n-1] = '\0';
-	break;
+        break;
 
     case KEY_START_BLOCK:
 
@@ -546,29 +526,26 @@
 
 
 void
-process_item(struct button *button)
+process_item(struct button *button, int arg)
 {
-    if (v->current != NULL) {
-        free(v->current);
-    }
-    v->current = copy_button_info(button);
+    v->current = button->id;
 
     if (v->error) {
         /* Must press a valid key first. */
-	if (v->current->id != KEY_CLEAR) {
+        if (v->current != KEY_CLEAR) {
             return;
         }
         set_error_state(FALSE);
     }
-
-    if (v->pending >= 0) {
-        buttons[v->pending].func();
+    
+    if (v->noparens > 0) {
+        do_paren();
         return;
     }
 
     STRCPY(v->opstr, v->op_item_text);
 
-    (*button->func)();
+    (*button->func)(arg);
 }
 
 
@@ -590,14 +567,15 @@
 refresh_display()
 {
     char localized[MAX_LOCALIZED];
+    struct exprm_state *e;
 
     switch (v->syntax) {
         case npa:
             show_display(v->MPdisp_val);
             break;
 
-        case exprs: {
-	    struct exprm_state *e = get_state();
+        case exprs:
+            e = get_state();
 
             if (e->expression && strlen(e->expression)) {
                 char *str = gc_strdup(e->expression);
@@ -631,8 +609,7 @@
                 show_display(MP1);
                 v->ghost_zero = 1;
             }
-        }    
-        break;
+            break;
 
         default:
             assert(0);
Index: gcalctool/functions.c
===================================================================
--- gcalctool/functions.c	(revision 1775)
+++ gcalctool/functions.c	(working copy)
@@ -34,13 +34,8 @@
 
 static int do_trigfunc(int s[MP_SIZE], int t[MP_SIZE]);
 
-static void do_accuracy();
-static void do_constant();
-static void do_exchange();
-static void do_function();
 static void do_immedfunc(int s[MP_SIZE], int t[MP_SIZE]);
 static void do_portionfunc(int num[MP_SIZE]);
-static void do_shift(enum shiftd);
 
 char *
 gc_strdup(char *str)
@@ -216,47 +211,42 @@
 }
 
 
-static void
-do_accuracy()     /* Set display accuracy. */
+void
+do_accuracy(int value)     /* Set display accuracy. */
 {
     char intval[5];
-    int i;
 
-    for (i = 0; i <= 9; i++) {
-        if (v->current_value == get_menu_entry(M_ACC, i)) {
-            v->accuracy = char_val(v->current_value);
-            SPRINTF(intval, "%d", v->accuracy);
-            put_resource(R_ACCURACY, intval);
-            set_accuracy_menu_item(v->accuracy);
-            set_accuracy_tooltip(v->accuracy);
-            make_registers();
-            clear_undo_history();
-            return;
-        }
-    }
+    v->accuracy = value;
+    SPRINTF(intval, "%d", v->accuracy);
+    put_resource(R_ACCURACY, intval);
+    set_accuracy_menu_item(v->accuracy);
+    set_accuracy_tooltip(v->accuracy);
+    make_registers();
+    clear_undo_history();
+    syntaxdep_show_display();
 }
 
 
 void
 do_business()     /* Perform special business mode calculations. */
 {
-    if (v->current->id == KEY_FINC_CTRM) {
+    if (v->current == KEY_FINC_CTRM) {
         calc_ctrm(v->MPdisp_val);
-    } else if (v->current->id == KEY_FINC_DDB) {
+    } else if (v->current == KEY_FINC_DDB) {
         calc_ddb(v->MPdisp_val);
-    } else if (v->current->id == KEY_FINC_FV) {
+    } else if (v->current == KEY_FINC_FV) {
         calc_fv(v->MPdisp_val);
-    } else if (v->current->id == KEY_FINC_PMT) {
+    } else if (v->current == KEY_FINC_PMT) {
         calc_pmt(v->MPdisp_val);
-    } else if (v->current->id == KEY_FINC_PV) {
+    } else if (v->current == KEY_FINC_PV) {
         calc_pv(v->MPdisp_val);
-    } else if (v->current->id == KEY_FINC_RATE) {
+    } else if (v->current == KEY_FINC_RATE) {
         calc_rate(v->MPdisp_val);
-    } else if (v->current->id == KEY_FINC_SLN) {
+    } else if (v->current == KEY_FINC_SLN) {
         calc_sln(v->MPdisp_val);
-    } else if (v->current->id == KEY_FINC_SYD) {
+    } else if (v->current == KEY_FINC_SYD) {
         calc_syd(v->MPdisp_val);
-    } else if (v->current->id == KEY_FINC_TERM) {
+    } else if (v->current == KEY_FINC_TERM) {
         calc_term(v->MPdisp_val);
     }
     show_display(v->MPdisp_val);
@@ -326,7 +316,7 @@
     if (e->expression) {
         ret = ce_parse(e->expression, MPnum);
     } else {
-	do_zero(MPnum);
+        do_zero(MPnum);
     }
 
     return ret;
@@ -509,14 +499,38 @@
     char *btext = NULL;
     struct exprm_state *e;
     int non_empty_expression;
+    
+    e = get_state();
 
+    /* FIXME: These match existing behaviour before Glade patches
+     * these should be acted on lower down in this function */
+    switch (e->button.id) {
+        case KEY_LEFT_SHIFT:
+            do_lshift(e->value);
+            return;
+        case KEY_RIGHT_SHIFT:
+            do_rshift(e->value);
+            return;
+        case KEY_SET_ACCURACY:
+            do_accuracy(e->value);
+            return;
+        case KEY_FUNCTION:
+            do_function(e->value);
+            return;
+        case KEY_STORE:
+            do_sto(e->value);
+            return;
+        case KEY_EXCHANGE:
+            do_exchange(e->value);
+            return;
+    }
+
     update_statusbar("", "");
 
-    e = get_state();
     if (e->button.flags & dpoint) {
-	btext = get_localized_numeric_point();
+        btext = get_localized_numeric_point();
     } else {
-	btext = e->button.symname;
+        btext = e->button.symname;
     }
     btext = gc_strdup(btext);
     trig_filter(&btext);
@@ -546,22 +560,21 @@
 	    char buf[1024];
 	    snprintf(buf, 128, "%s(Ans)", btext);
 	    exp_replace(buf);
-            update_display = 1;
+        update_display = 1;
     } else if (e->button.flags & clear) {
         exp_del();
         update_display = 1;
         set_error_state(FALSE);
         MPstr_to_num("0", DEC, e->ans);
     } else if (e->button.flags & regrcl) {
-        int i = char_val(e->value);
+        int i = e->value;
         char reg[3];
         int n = '0' +  i;
 
         snprintf(reg, 3, "R%c", n);
         exp_append(reg);
     } else if (e->button.flags & con) {
-        int *MPval = v->MPcon_vals[char_val(e->value)];
-
+        int *MPval = v->MPcon_vals[e->value];
         exp_append(make_number(MPval, v->base, FALSE));
     } else if (e->button.flags & bsp) {
         if (exp_has_postfix(e->expression, "Ans")) { 
@@ -595,62 +608,62 @@
         exp_inv();
         update_display = 1;
     } else if (e->button.flags & enter) {
-	  if (e->expression) {
-	    if (strcmp(e->expression, "Ans")) {
-            int MPval[MP_SIZE];
-            int ret = ce_parse(e->expression, MPval);
+        if (e->expression) {
+            if (strcmp(e->expression, "Ans")) {
+                int MPval[MP_SIZE];
+                int ret = ce_parse(e->expression, MPval);
             
-            if (!ret) {
-                mpstr(MPval, e->ans);
-                exp_replace("Ans");
-                update_display = 1;
-            } else {
-                char *message = NULL;
-                
-                switch (ret) {
-			    case -PARSER_ERR_INVALID_BASE:
-			        message = _("Invalid number for the current base");
-			        break;
+                if (!ret) {
+                    mpstr(MPval, e->ans);
+                    exp_replace("Ans");
+                    update_display = 1;
+                } else {
+                    char *message = NULL;
+                    
+                    switch (ret) {
+                        case -PARSER_ERR_INVALID_BASE:
+                            message = _("Invalid number for the current base");
+                            break;
 
-			    case -PARSER_ERR_TOO_LONG_NUMBER:
-			        message = _("Too long number");
-			        break;
+                        case -PARSER_ERR_TOO_LONG_NUMBER:
+                            message = _("Too long number");
+                            break;
 
-			    case -PARSER_ERR_BITWISEOP:
-			        message = _("Invalid bitwise operation parameter(s)");
-			        break;
+                        case -PARSER_ERR_BITWISEOP:
+                            message = _("Invalid bitwise operation parameter(s)");
+                            break;
 
-			    case -PARSER_ERR_MODULUSOP:
-			        message = _("Invalid modulus operation parameter(s)");
-			        break;
-
-			    case -MPMATH_ERR:
-			        message = _("Math operation error");
-			        break;
-
-			    default:
-			        message = _("Malformed expression");
-			}
-			update_statusbar(message, "gtk-dialog-error");
-		  }
-	    } else {
-		  perform_undo();
-		  if (is_undo_step()) {
-			perform_undo();
-                        update_display = 1;
-		  }
-	    }
-	  }
+                        case -PARSER_ERR_MODULUSOP:
+                            message = _("Invalid modulus operation parameter(s)");
+                            break;
+                        
+                        case -MPMATH_ERR:
+                            message = _("Math operation error");
+                            break;
+                        
+                        default:
+                            message = _("Malformed expression");
+                    }
+                    update_statusbar(message, "gtk-dialog-error");
+                }
+            } else {
+                perform_undo();
+                if (is_undo_step()) {
+                    perform_undo();
+                    update_display = 1;
+                }
+            }
+        }
     } else {
-	exp_append(btext);
-	if (e->button.flags & func) {
-	    exp_append("(");
-	}
+        exp_append(btext);
+        if (e->button.flags & func) {
+            exp_append("(");
+        }
     }
-
+    
     free(btext);
     btext = NULL;
-
+    
     update_display = 1;
     if (update_display) {
         refresh_display();
@@ -665,7 +678,7 @@
     int MP1[MP_SIZE], MP2[MP_SIZE];
 
     if (!(v->opsptr && !v->show_paren)) {  /* Don't do if processing parens. */
-        if (v->current->id == KEY_CALCULATE && 
+        if (v->current == KEY_CALCULATE && 
             v->old_cal_value == KEY_CALCULATE) {
             if (v->new_input) {
                 mpstr(v->MPlast_input, v->MPresult);
@@ -675,7 +688,7 @@
         }
     }
     
-    if (v->current->id != KEY_CALCULATE && 
+    if (v->current != KEY_CALCULATE && 
         v->old_cal_value == KEY_CALCULATE) {
         v->cur_op = -1;
     }
@@ -743,16 +756,16 @@
 
     show_display(v->MPresult);
 
-    if (!(v->current->id == KEY_CALCULATE &&
+    if (!(v->current == KEY_CALCULATE &&
 	v->old_cal_value == KEY_CALCULATE)) {
         mpstr(v->MPdisp_val, v->MPlast_input);
     }
 
     mpstr(v->MPresult, v->MPdisp_val);
-    if (v->current->id != KEY_CALCULATE) {
-        v->cur_op = v->current->id;
+    if (v->current != KEY_CALCULATE) {
+        v->cur_op = v->current;
     }
-    v->old_cal_value = v->current->id;
+    v->old_cal_value = v->current;
     v->new_input     = v->key_exp = 0;
 }
 
@@ -763,13 +776,13 @@
     enum trig_func tfunc;
     int sin_key, cos_key, tan_key;
 
-    if (!v->current) {
+    if (v->current < 0) {
         return(-EINVAL);
     }
 
-    sin_key = (v->current->id == KEY_SINE) ? 1 : 0;
-    cos_key = (v->current->id == KEY_COSINE) ? 1 : 0;
-    tan_key = (v->current->id == KEY_TANGENT) ? 1 : 0;
+    sin_key = (v->current == KEY_SINE) ? 1 : 0;
+    cos_key = (v->current == KEY_COSINE) ? 1 : 0;
+    tan_key = (v->current == KEY_TANGENT) ? 1 : 0;
   
     if (sin_key) {
         tfunc = SIN;
@@ -817,7 +830,7 @@
 
     assert(tfunc < 3); 
     
-    if (!v->current) {
+    if (v->current < 0) {
         return -EINVAL;
     }
     
@@ -846,38 +859,38 @@
 
 void
 do_base(enum base_type b)    /* Change the current base setting. */
-{    
+{
+    struct exprm_state *e;
+    int ret, MP[MP_SIZE];
+    
     switch (v->syntax) {
         case npa:
             v->base = b;
             put_resource(R_BASE, Rbstr[(int) v->base]);
             grey_buttons(v->base);
 
-            v->pending = -1;
             if (v->rstate) {
                 make_registers();
             }
-	    break;
+	        break;
 	
-        case exprs: {
-	    struct exprm_state *e = get_state();
-	    int MP[MP_SIZE];
-	    int ret = usable_num(MP);
+        case exprs:
+            e = get_state();
+            ret = usable_num(MP);
 
-	    if (ret) {
-	        update_statusbar(_("No sane value to convert"), 
-			         "gtk-dialog-error");
-	    } else if (!v->ghost_zero) {
-	        mpstr(MP, e->ans);
-	        exp_replace("Ans");
-	    }
+            if (ret) {
+                update_statusbar(_("No sane value to convert"), 
+                                 "gtk-dialog-error");
+            } else if (!v->ghost_zero) {
+                mpstr(MP, e->ans);
+                exp_replace("Ans");
+            }
             v->base = b;
             put_resource(R_BASE, Rbstr[(int) v->base]);
             grey_buttons(v->base);
             make_registers();
-	    clear_undo_history();
-        }
-        break;
+            clear_undo_history();
+            break;
     
         default:
 	    assert(0);
@@ -887,31 +900,32 @@
 }
 
 
-static void
-do_constant()
+void
+do_constant(int index)
 {
-    assert(v->current_value >= '0');
-    assert(v->current_value <= '9');
+    int *MPval;
+    struct exprm_state *e;
     
+    assert(index >= 0);
+    assert(index <= 9);
+    
     switch (v->syntax) {
-        case npa: {
-	    int *MPval = v->MPcon_vals[char_val(v->current_value)];
+        case npa:
+            MPval = v->MPcon_vals[index];
+            mpstr(MPval, v->MPdisp_val);
+            break;
 
-	    mpstr(MPval, v->MPdisp_val);
-	    break;
-        }
+        case exprs:
+	        e = get_state();
+            do_expression();
+            break;
 
-        case exprs: {
-	    struct exprm_state *e = get_state();
-
-	    e->button.flags = con;
-	    do_expression();
-        }
-        break;
-
         default:
             assert(0);
     }
+
+    v->new_input = 1;
+    syntaxdep_show_display();
 }
 
 
@@ -922,7 +936,7 @@
 
     len = strlen(v->display);
     if (len > 0) {
-	v->display[len-1] = '\0';
+        v->display[len-1] = '\0';
     }
 
 /*  If we were entering a scientific number, and we have backspaced over
@@ -950,43 +964,48 @@
 }
 
 
-static void
-do_exchange()         /* Exchange display with memory register. */
+void
+do_exchange(int index)         /* Exchange display with memory register. */
 {
     int MPtemp[MP_SIZE];
     int MPexpr[MP_SIZE];
+    struct exprm_state *e;
+    int ret;
+    int n;
 
     switch (v->syntax) {
-        case npa: {
+        case npa:
             mpstr(v->MPdisp_val, MPtemp);
-            mpstr(v->MPmvals[char_val(v->current_value)], v->MPdisp_val);
-            mpstr(MPtemp, v->MPmvals[char_val(v->current_value)]);
+            mpstr(v->MPmvals[index], v->MPdisp_val);
+            mpstr(MPtemp, v->MPmvals[index]);
             make_registers();
-        }
-        break;
+            break;
 
-        case exprs: {
-              struct exprm_state *e = get_state();
-              int ret = usable_num(MPexpr);
-              int n = char_val(e->value);
+        case exprs:
+            e = get_state();
+            ret = usable_num(MPexpr);
+            n = e->value;
+            
+            if (ret) {
+                update_statusbar(_("No sane value to store"), 
+                                 "gtk-dialog-error");
+            } else {
+                mpstr(v->MPmvals[n], MPtemp);
+                mpstr(MPexpr, v->MPmvals[n]);
+                mpstr(MPtemp, e->ans);	      
+                exp_replace("Ans");
+                refresh_display();
+                make_registers();
+            }
+            break;
 
-              if (ret) {
-                  update_statusbar(_("No sane value to store"), 
-                                   "gtk-dialog-error");
-              } else {
-                  mpstr(v->MPmvals[n], MPtemp);
-                  mpstr(MPexpr, v->MPmvals[n]);
-                  mpstr(MPtemp, e->ans);	      
-                  exp_replace("Ans");
-                  refresh_display();
-                  make_registers();
-	      }
-	  }
-          break;
-
         default:
             assert(0);
     }
+
+    v->new_input = 1;
+    syntaxdep_show_display();
+
 }
 
 
@@ -1060,39 +1079,27 @@
 }
 
 
-static void
-do_function()      /* Perform a user defined function. */
+void
+do_function(int index)      /* Perform a user defined function. */
 {
     char *str;
-    int fno, ret;
+    int ret;
+    
+    assert(index >= 0);
+    assert(index <= 9);
 
     switch (v->syntax) {
         case npa:
-            assert(v->current_value >= '0');
-            assert(v->current_value <= '9');
-
-            fno = char_val(v->current_value);
-            ret = 0;
-            str = v->fun_vals[fno];
+            str = v->fun_vals[index];
             assert(str);
-
             ret = lr_udf_parse(str);
             break;
 
-        case exprs: {
-            struct exprm_state *e = get_state();
-
-            assert(e->value >= '0');
-            assert(e->value <= '9');
-
-            fno = char_val(e->value);
-            ret = 0;
-            str = v->fun_vals[fno];
+        case exprs:
+            str = v->fun_vals[index];
             assert(str);
-
             ret = ce_udf_parse(str);
-        }
-        break;
+            break;
 
         default:
             assert(0);
@@ -1103,6 +1110,7 @@
     } else { 
         update_statusbar(_("Malformed function"), "gtk-dialog-error");
     }
+    v->new_input = 1;
 }
 
 
@@ -1111,36 +1119,36 @@
 {
     int MP1[MP_SIZE];
 
-    if (v->current->id == KEY_MASK_32) {                     /* &32 */
+    if (v->current == KEY_MASK_32) {                     /* &32 */
         calc_u32(s, t);
-    } else if (v->current->id == KEY_MASK_16) {              /* &16 */
+    } else if (v->current == KEY_MASK_16) {              /* &16 */
         calc_u16(s, t);
-    } else if (v->current->id == KEY_E_POW_X) {              /* e^x  */
+    } else if (v->current == KEY_E_POW_X) {              /* e^x  */
         mpstr(s, MP1);
         mpexp(MP1, t);
-    } else if (v->current->id == KEY_10_POW_X) {             /* 10^x */
+    } else if (v->current == KEY_10_POW_X) {             /* 10^x */
         calc_tenpowx(s, t);
-    } else if (v->current->id == KEY_NATURAL_LOGARITHM) {    /* Ln */
+    } else if (v->current == KEY_NATURAL_LOGARITHM) {    /* Ln */
         mpstr(s, MP1);
         mpln(MP1, t);
-    } else if (v->current->id == KEY_LOGARITHM) {            /* Log */
+    } else if (v->current == KEY_LOGARITHM) {            /* Log */
         mplog10(s, t);
-    } else if (v->current->id == KEY_RANDOM) {               /* Rand */
+    } else if (v->current == KEY_RANDOM) {               /* Rand */
         calc_rand(t);
-    } else if (v->current->id == KEY_SQUARE_ROOT) {          /* Sqrt */
+    } else if (v->current == KEY_SQUARE_ROOT) {          /* Sqrt */
         mpstr(s, MP1);
         mpsqrt(MP1, t);
-    } else if (v->current->id == KEY_NOT) {                  /* NOT */
+    } else if (v->current == KEY_NOT) {                  /* NOT */
         calc_not(t, s);
-    } else if (v->current->id == KEY_RECIPROCAL) {           /* 1/x */
+    } else if (v->current == KEY_RECIPROCAL) {           /* 1/x */
         calc_inv(s, t);
-    } else if (v->current->id == KEY_FACTORIAL) {            /* x! */
+    } else if (v->current == KEY_FACTORIAL) {            /* x! */
         do_factorial(s, MP1);
         mpstr(MP1, t);
-    } else if (v->current->id == KEY_SQUARE) {               /* x^2 */
+    } else if (v->current == KEY_SQUARE) {               /* x^2 */
         mpstr(s, MP1);
         mpmul(MP1, MP1, t);
-    } else if (v->current->id == KEY_CHANGE_SIGN) {          /* +/- */
+    } else if (v->current == KEY_CHANGE_SIGN) {          /* +/- */
          if (v->key_exp) {
              if (*v->exp_posn == '+') {
                  *v->exp_posn = '-';
@@ -1204,7 +1212,7 @@
         offset = strlen(v->display);
     }
     if (offset < MAXLINE) {
-        SNPRINTF(v->display+offset, MAXLINE-offset, "%s", v->current->symname);
+        SNPRINTF(v->display+offset, MAXLINE-offset, "%s", buttons[v->current].symname);
     }
 
     set_display(v->display, TRUE);
@@ -1221,7 +1229,6 @@
 
     switch (v->syntax) {
     case npa:
-        v->pending = -1;
         if (v->rstate) {
             make_registers();
         }
@@ -1257,62 +1264,63 @@
 {
     update_statusbar("", "");
 
-    if (v->current->id == KEY_START_BLOCK) {
-	v->pending = v->current->id;
-        if (v->noparens == 0) {
-            if (v->cur_op == -1) {
-	        v->display[0] = 0;
-	        update_statusbar(_("Cleared display, prefix without an operator is not allowed"), "");
-            } else {
-                paren_disp(v->cur_op);
+    switch (v->current) {
+        case KEY_START_BLOCK:
+            if (v->noparens == 0) {
+                if (v->cur_op == -1) {
+                    v->display[0] = 0;
+                    update_statusbar(_("Cleared display, prefix without an operator is not allowed"), "");
+                } else {
+                    paren_disp(v->cur_op);
+                }
             }
-        }
-        v->noparens++;
-    }
+            v->noparens++;
+            break;
 
-    if (v->noparens && v->current->id == KEY_END_BLOCK) {
-        v->noparens--;
-        if (!v->noparens) {
-            int ret, i = 0;
+        case KEY_END_BLOCK:
+            v->noparens--;
+            if (!v->noparens) {
+                int ret, i = 0;
+                while (v->display[i++] != '(') {
+                    /* do nothing */;
+                }
 
-            while (v->display[i++] != '(') {
-                /* do nothing */;
+                ret = lr_parse(&v->display[i], v->MPdisp_val);
+                if (!ret) {
+                    show_display(v->MPdisp_val);
+                    return;
+                } else {
+                    update_statusbar(_("Malformed parenthesis expression"), 
+                                     "gtk-dialog-error");
+                }
             }
-
-            ret = lr_parse(&v->display[i], v->MPdisp_val);
-            if (!ret) {
-	        show_display(v->MPdisp_val);
-	        v->pending = -1;
-	        return;
-            } else {
-                update_statusbar(_("Malformed parenthesis expression"), 
-                                 "gtk-dialog-error");
-            }
-        }
+            break;
+                
+        default:
+            /* Queue event */
+            break;
     }
-    paren_disp(v->current->id);
+    paren_disp(v->current);
 }
 
 
-static void
-do_sto()
+void
+do_sto(int index)
 {
-    int n = char_val(v->current_value);
-
+    int ret;
+    
     switch (v->syntax) {
         case npa:
-            mpstr(v->MPdisp_val, v->MPmvals[n]);
+            mpstr(v->MPdisp_val, v->MPmvals[index]);
             break;
 
-        case exprs: {
-            int ret = usable_num(v->MPmvals[n]);
-
+        case exprs:
+            ret = usable_num(v->MPmvals[index]);
             if (ret) {
-	        update_statusbar(_("No sane value to store"), 
+                update_statusbar(_("No sane value to store"), 
                                  "gtk-dialog-error");
             }
-        }
-        break;
+            break;
 
         default:
             assert(0);
@@ -1339,28 +1347,24 @@
 }
 
 
-static void
-do_rcl()
+void
+do_rcl(int index)
 {
     switch (v->syntax) {
-        case npa: {
-            int i = char_val(v->current_value);
-
-            mpstr(v->MPmvals[i], v->MPdisp_val);
+        case npa:
+            mpstr(v->MPmvals[index], v->MPdisp_val);
             break;
-        }
 
-        case exprs: {
-            struct exprm_state *e = get_state();
-
-            e->button.flags = regrcl;
+        case exprs:
             do_expression();
-        }
-        break;
+            break;
 
         default:
             assert(0);
     }
+    
+    v->new_input = 1;
+    syntaxdep_show_display();
 }
 
 
@@ -1400,54 +1404,6 @@
 
 
 void
-do_pending()
-{
-    if (!v->ismenu &&
-        !(v->pending == KEY_START_BLOCK)) {
-        show_menu();
-    }
-
-    if (v->pending == KEY_CONSTANTS_MENU)  {                 /* Con */
-        do_constant();
-	v->new_input = 1;
-	syntaxdep_show_display();
-    } else if (v->pending == KEY_EXCHANGE) {                 /* Exch */
-        do_exchange();
-	v->new_input = 1;
-	syntaxdep_show_display();
-    } else if (v->pending == KEY_FUNCTIONS_MENU)  {          /* Fun */
-        do_function();
-	v->new_input = 1;
-    } else if (v->pending == KEY_STORE) {
-        do_sto();
-    } else if (v->pending == KEY_RECALL) {
-       do_rcl();
-       v->new_input = 1;
-       syntaxdep_show_display();
-    } else if (v->pending == KEY_LEFT_SHIFT) {               /* < */
-        do_shift(left);
-	v->new_input = 1;
-	syntaxdep_show_display();
-    } else if (v->pending == KEY_RIGHT_SHIFT) {              /* > */
-        do_shift(right);
-	v->new_input = 1;
-	syntaxdep_show_display();
-    } else if (v->pending == KEY_ACCURACY_MENU) {            /* Acc */
-        do_accuracy();
-	syntaxdep_show_display();
-    } else if (v->pending == KEY_START_BLOCK) {              /* ( */
-        do_paren();
-        return;
-    } else if (v->pending < 0) {
-        v->pending = v->current->id;
-        return;
-    }
-
-    v->pending = -1;
-}
-
-
-void
 do_point()                   /* Handle numeric point. */
 {
     if (!v->pointed) {
@@ -1469,15 +1425,15 @@
 {
     int MP1[MP_SIZE];
 
-    if (v->current->id == KEY_ABSOLUTE_VALUE) {                 /* Abs */
+    if (v->current == KEY_ABSOLUTE_VALUE) {                 /* Abs */
         mpstr(num, MP1);
         mpabs(MP1, num);
 
-    } else if (v->current->id == KEY_FRACTION) {               /* Frac */
+    } else if (v->current == KEY_FRACTION) {               /* Frac */
         mpstr(num, MP1);
         mpcmf(MP1, num);
 
-    } else if (v->current->id == KEY_INTEGER) {                /* Int */
+    } else if (v->current == KEY_INTEGER) {                /* Int */
         mpstr(num, MP1);
         mpcmim(MP1, num);
     }
@@ -1493,70 +1449,70 @@
 
 
 static void
-do_shift(enum shiftd dir)     /* Perform bitwise shift on display value. */
+do_shift(enum shiftd dir, int count)     /* Perform bitwise shift on display value. */
 {
-    enum menu_type mtype;
+    int n, ret;
+    BOOLEAN temp;
+    double dval;
+    struct exprm_state *e;
+    int MPtemp[MP_SIZE], MPval[MP_SIZE];
     
-    if (dir == left)
-	mtype = M_LSHF;
-    else
-	mtype = M_RSHF;
-    
     switch (v->syntax) {
-        case npa: {
-            /* TODO: cleanup this code block. */
-            int i, MPtemp[MP_SIZE], shift;
-            BOOLEAN temp;
-            double dval;
-      
-            for (i = 0; i <= 15; i++) {
-                if (v->current_value == get_menu_entry(mtype, i)) {
-	            shift = char_val(v->current_value);
-	            MPstr_to_num(v->display, v->base, MPtemp);
-	            mpcmd(MPtemp, &dval);
-	            temp = ibool(dval);
+        case npa:
+            MPstr_to_num(v->display, v->base, MPtemp);
+            mpcmd(MPtemp, &dval);
+            temp = ibool(dval);
 	  
-	            if (v->pending == KEY_LEFT_SHIFT) {
-	                temp = temp << shift;
-	            } else if (v->pending == KEY_RIGHT_SHIFT) {
-	                temp = temp >> shift;
-	            }
-
-	            dval = setbool(temp);
-	            mpcdm(&dval, v->MPdisp_val);
-	            show_display(v->MPdisp_val);
-	            mpstr(v->MPdisp_val, v->MPlast_input);
-	            return;
-                }
+            if (dir == left) {
+                temp = temp << count;
+            } else if (dir == right) {
+                temp = temp >> count;
             }
-        } 
-        break;
 
-        case exprs: {
-	    struct exprm_state *e = get_state();
-            int MPval[MP_SIZE];
-            int n = char_val(e->value);
-            int ret = usable_num(MPval);
+            dval = setbool(temp);
+            mpcdm(&dval, v->MPdisp_val);
+            show_display(v->MPdisp_val);
+            mpstr(v->MPdisp_val, v->MPlast_input);
+            break;
 
+        case exprs:
+            e = get_state();
+            n = e->value;
+            ret = usable_num(MPval);
             if (ret || !is_integer(MPval)) {
-	        update_statusbar(_("No sane value to do bitwise shift"), 
+                update_statusbar(_("No sane value to do bitwise shift"), 
                                  "gtk-dialog-error");
-	        return;
-            } 
+                break;
+            }
 
             calc_rshift(MPval, e->ans, n, dir);
 
-	    exp_replace("Ans");
-        }
-        break;
+            exp_replace("Ans");
+            break;
 
         default:
             assert(0);
     }
+    
+    v->new_input = 1;
+    syntaxdep_show_display();
 }
 
 
+// FIXME: Make one shift function using sign
 void
+do_lshift(int count)
+{
+    do_shift(left, count);
+}
+
+void do_rshift(int count)
+{
+    do_shift(right, count);
+}
+
+
+void
 do_trigtype(enum trig_type t)    /* Change the current trigonometric type. */
 {
     v->ttype = t;
@@ -1567,7 +1523,6 @@
         mpstr(v->MPtresults[(int) v->ttype], v->MPdisp_val);
         show_display(v->MPtresults[(int) v->ttype]);
     }
-    v->pending = -1;
 }
 
 
Index: gcalctool/gtk.c
===================================================================
--- gcalctool/gtk.c	(revision 1776)
+++ gcalctool/gtk.c	(working copy)
@@ -42,6 +42,12 @@
 #include "ce_parser.h"
 #include "mpmath.h"
 
+/* Popup menu types. */
+/* FIXME: This enum could be removed */
+enum menu_type { M_ACC,  M_CON,  M_EXCH, M_FUN,  M_LSHF,
+                 M_RCL,  M_RSHF, M_STO, M_NONE };
+#define MAXMENUS       9          /* Maximum number of popup menus. */
+
 #define MAX_ACCELERATORS 8
 struct button_widget {
     int key;
@@ -51,35 +57,6 @@
     guint accelerator_keys[MAX_ACCELERATORS];
 };
 
-enum {
-    BUT_0,
-    BUT_1,
-    BUT_2,
-    BUT_3,
-    BUT_4,
-    BUT_5,
-    BUT_6,
-    BUT_7,
-    BUT_8,
-    BUT_9,
-    BUT_A,
-    BUT_B,
-    BUT_C,
-    BUT_D,
-    BUT_E,
-    BUT_F,
-    BUT_CLEAR_BASIC,
-    BUT_CLEAR_ADVANCED,
-    BUT_LEFT_SHIFT,
-    BUT_RIGHT_SHIFT,
-    BUT_ACCURACY_MENU,
-    BUT_CONSTANTS_MENU,
-    BUT_FUNCTIONS_MENU,
-    BUT_STORE,
-    BUT_RECALL,
-    BUT_EXCHANGE
-};
-
 /*  This table shows the keyboard values that are currently being used:
  *
  *           |  a b c d e f g h i j k l m n o p q r s t u v w x y z
@@ -173,15 +150,15 @@
     { GDK_SHIFT_MASK, 0 },
     { GDK_greater, 0 }},
 
-    {KEY_ACCURACY_MENU,      "accuracy", M_ACC,
+    {KEY_SET_ACCURACY,       "accuracy", M_ACC,
     { GDK_SHIFT_MASK, 0 },
     { GDK_A,          0 }},
 
-    {KEY_CONSTANTS_MENU,     "constants", M_CON,
+    {KEY_CONSTANT,           "constants", M_CON,
     { GDK_SHIFT_MASK, 0,              0 },
     { GDK_numbersign, GDK_numbersign, 0 }},
 
-    {KEY_FUNCTIONS_MENU,     "functions", M_FUN,
+    {KEY_FUNCTION,           "functions", M_FUN,
     { GDK_SHIFT_MASK, 0 },
     { GDK_F,          0 }},
 
@@ -451,6 +428,8 @@
     GtkWidget *menus[MAXMENUS];
 
     GtkWidget *buttons[NBUTTONS];
+    GtkWidget *digit_buttons[16];
+    GtkWidget *clear_buttons[2];
 
     GtkWidget *bas_panel;      /* Panel containing basic mode widgets. */
     GtkWidget *adv_panel;      /* Panel containing advanced mode widgets. */
@@ -599,7 +578,7 @@
             mpcmim(MP1, MP2);
             if (mpeq(MP1, MP2)) {
                 char *bit_str, label[3], tmp[MAXLINE];
-                int toclear = (v->current->id == KEY_CLEAR_ENTRY)
+                int toclear = (v->current == KEY_CLEAR_ENTRY)
                               ? TRUE : FALSE;
 
                 bit_str = make_fixed(MP1, tmp, BIN, MAXLINE, toclear);
@@ -755,8 +734,8 @@
         gtk_widget_set_sensitive(X->buttons[i], !v->error);
     }
     /* Clr button always sensitive. */
-    gtk_widget_set_sensitive(X->buttons[BUT_CLEAR_BASIC], TRUE);
-    gtk_widget_set_sensitive(X->buttons[BUT_CLEAR_ADVANCED], TRUE);
+    gtk_widget_set_sensitive(X->clear_buttons[0], TRUE);
+    gtk_widget_set_sensitive(X->clear_buttons[1], TRUE);
 
     if (!v->error) {
         grey_buttons(v->base);
@@ -1076,27 +1055,13 @@
     gdk_beep();
 }
 
-
-/*ARGSUSED*/
-static void
-button_cb(GtkWidget *widget)
+static void do_button(struct button *n, int arg)
 {
-    struct button *n;
+    struct exprm_state *e;
     
-    n = (struct button *) g_object_get_data(G_OBJECT(widget), "button");
-    assert(n);
-
     switch (v->syntax) {
         case npa:
-            if (v->pending >= 0) {
-                if (v->current != NULL) {
-                    free(v->current);
-                }
-                v->current = copy_button_info(n);
-                do_pending();
-            } else {
-                process_item(n);
-            }
+            process_item(n, arg);
             set_bit_panel();
             if (v->new_input && v->dtype == FIX) {
                 STRNCPY(v->fnum, v->display, MAX_DIGITS - 1);
@@ -1105,19 +1070,12 @@
             break;
 
         case exprs:
-            if ((n->flags) & pending) {
-                if (v->current != NULL) {
-                    free(v->current);
-                }
-                v->current = copy_button_info(n);
-                do_pending();
-            } else {
-                struct exprm_state *e = get_state();
-                memcpy(&(e->button), n, sizeof(struct button));
-                new_state();
-                do_expression();
-                set_bit_panel();
-            }
+            e = get_state();
+            e->value = arg;
+            memcpy(&(e->button), n, sizeof(struct button));
+            new_state();
+            do_expression();
+            set_bit_panel();
             break;
 
         default:
@@ -1126,7 +1084,18 @@
 }
 
 
+/*ARGSUSED*/
 static void
+button_cb(GtkWidget *widget)
+{
+    struct button *n;
+    
+    n = (struct button *) g_object_get_data(G_OBJECT(widget), "button");
+    do_button(n, 0);
+}
+
+
+static void
 help_display(void)
 {
     GError *error = NULL;
@@ -1213,12 +1182,8 @@
 static void
 menu_proc_cb(GtkMenuItem *mi, gpointer user_data)
 {
-    enum menu_type mtype = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(mi),
-                                                             "mtype"));
-
-    v->current_value = '0' + GPOINTER_TO_INT(user_data);
-    
-    handle_menu_selection(X->mrec[mtype], v->current_value);
+    struct button *n = (struct button *) g_object_get_data(G_OBJECT(mi), "button");
+    do_button(n, GPOINTER_TO_INT(user_data));
 }
 
 
@@ -1427,7 +1392,7 @@
                                        accuracy),
                               accuracy);
     tooltip = g_strdup_printf ("%s %s [A]", desc, current);
-    gtk_widget_set_tooltip_text (X->buttons[BUT_ACCURACY_MENU], tooltip);
+    gtk_widget_set_tooltip_text (GET_WIDGET("calc_accuracy_button"), tooltip);
     g_free(desc);
     g_free(current);
     g_free(tooltip);
@@ -1998,22 +1963,11 @@
 void
 grey_buttons(enum base_type base)
 {
-    gtk_widget_set_sensitive(X->buttons[BUT_0], (0 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_1], (1 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_2], (2 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_3], (3 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_4], (4 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_5], (5 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_6], (6 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_7], (7 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_8], (8 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_9], (9 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_A], (10 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_B], (11 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_C], (12 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_D], (13 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_E], (14 < basevals[(int) base]));
-    gtk_widget_set_sensitive(X->buttons[BUT_F], (15 < basevals[(int) base]));
+    int i, baseval = basevals[(int) base];
+
+    for (i = 0; i < 16; i++) {
+        gtk_widget_set_sensitive(X->digit_buttons[i], i < baseval);
+    }
 }
 
 
@@ -2319,14 +2273,6 @@
 }
 
 
-/*ARGSUSED*/
-void
-menu_cancel_cb(GtkWidget *widget)
-{
-    v->pending = -1;
-}
-
-
 static void
 show_menu_for_button(GtkWidget *widget, GdkEventKey *event)
 {
@@ -2348,34 +2294,6 @@
 }
 
 
-void
-show_menu()
-{
-    GtkWidget *button = NULL;
-    GdkEvent *event = gtk_get_current_event();
-
-    if (v->current->id == KEY_ACCURACY_MENU) {       /* Acc */
-        button = X->buttons[BUT_ACCURACY_MENU];
-    } else if (v->current->id == KEY_CONSTANTS_MENU) {  /* Con */
-        button = X->buttons[BUT_CONSTANTS_MENU];
-    } else if (v->current->id == KEY_EXCHANGE) {        /* Exch */
-        button = X->buttons[BUT_EXCHANGE];
-    } else if (v->current->id == KEY_FUNCTIONS_MENU) {  /* Fun */
-        button = X->buttons[BUT_FUNCTIONS_MENU];
-    } else if (v->current->id == KEY_LEFT_SHIFT) {      /* < */
-        button = X->buttons[BUT_LEFT_SHIFT];
-    } else if (v->current->id == KEY_RECALL) {          /* Rcl */
-        button = X->buttons[BUT_RECALL];
-    } else if (v->current->id == KEY_RIGHT_SHIFT) {     /* > */
-        button = X->buttons[BUT_RIGHT_SHIFT];
-    } else if (v->current->id == KEY_STORE) {           /* Sto */
-        button = X->buttons[BUT_STORE];
-    }
-
-    show_menu_for_button(button, (GdkEventKey *) event);
-}
-
-
 static void
 show_precision_frame()      /* Display Set Precision popup. */
 {
@@ -2510,12 +2428,11 @@
 static void
 shift_left_cb(GtkWidget *widget)
 {
-    int choice = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), 
+    int count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), 
                                                    "shiftcount"));
 
     if (v->started) {
-        choice += (choice < 10) ? '0' : 'A' - 10;
-        handle_menu_selection(X->mrec[(int) M_LSHF], choice);
+        do_button(&buttons[KEY_LEFT_SHIFT], count);
     }
 }
 
@@ -2523,12 +2440,11 @@
 static void
 shift_right_cb(GtkWidget *widget)
 {
-    int choice = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), 
+    int count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), 
                                                    "shiftcount"));
 
     if (v->started) {
-        choice += (choice < 10) ? '0' : 'A' - 10;
-        handle_menu_selection(X->mrec[(int) M_RSHF], choice);
+        do_button(&buttons[KEY_RIGHT_SHIFT], count);
     }
 }
 
@@ -2668,13 +2584,13 @@
 static void
 accuracy_radio_cb(GtkWidget *widget)
 {
-    char c;
+    int count;
     
-    c = '0' + GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "index"));
+    count = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "index"));
     
     if (v->started && 
         gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
-        handle_menu_selection(X->mrec[(int) M_ACC], c);
+        //FIXME: do_accuracy(count);
     }
 }
 
@@ -2703,8 +2619,6 @@
         
         set_show_zeroes_toggle(v->show_zeroes);
     }
-
-    v->pending = -1;
 }
 
 
@@ -3013,7 +2927,6 @@
     CONNECT_SIGNAL(shift_left_cb);
     CONNECT_SIGNAL(shift_right_cb);
     CONNECT_SIGNAL(accuracy_radio_cb);
-    CONNECT_SIGNAL(menu_cancel_cb);
     CONNECT_SIGNAL(bit_toggled);
     CONNECT_SIGNAL(dismiss_aframe);
     CONNECT_SIGNAL(aframe_ok_cb);
@@ -3078,7 +2991,16 @@
         g_object_set_data(G_OBJECT(X->buttons[i]), "mtype", 
                           GINT_TO_POINTER(button_widgets[i].mtype));
     }
+    
+    for (i = 0; i < 16; i++) {
+        SNPRINTF(name, MAXLINE, "calc_%x_button", i);
+        X->digit_buttons[i] = GET_WIDGET(name);
+    }
 
+    SNPRINTF(name, MAXLINE, "calc_%d_button", i);
+    X->clear_buttons[0] = GET_WIDGET("calc_clear_simple_button");
+    X->clear_buttons[1] = GET_WIDGET("calc_clear_advanced_button");
+    
     X->mode_panel = GET_WIDGET("mode_panel");
     X->trig[0] = GET_WIDGET("degrees_radio");
     X->trig[1] = GET_WIDGET("gradians_radio");
@@ -3118,10 +3040,10 @@
     grey_buttons(v->base);
     if (v->modetype == BASIC) {
         gtk_window_set_focus(GTK_WINDOW(X->kframe),
-                             GTK_WIDGET(X->buttons[BUT_CLEAR_BASIC]));
+                             GTK_WIDGET(X->clear_buttons[0]));
     } else {
         gtk_window_set_focus(GTK_WINDOW(X->kframe),
-                             GTK_WIDGET(X->buttons[BUT_CLEAR_ADVANCED]));
+                             GTK_WIDGET(X->clear_buttons[1]));
     }
 
     X->statusbar = GET_WIDGET("statusbar");
@@ -3199,7 +3121,7 @@
 
 
 static GtkWidget *
-create_menu_item_with_markup(char *label, int menu_no, int user_data)
+create_menu_item_with_markup(char *label, int menu_no, int index)
 {
     GtkWidget *accel_label;
     GtkWidget *menu_item;
@@ -3212,11 +3134,11 @@
     gtk_widget_show(accel_label);
     gtk_widget_show(menu_item);
 
-    g_object_set_data(G_OBJECT(menu_item), "mtype", GINT_TO_POINTER(menu_no));
+    g_object_set_data(G_OBJECT(menu_item), "button", X->mrec[menu_no]);
     gtk_menu_shell_append(GTK_MENU_SHELL(X->menus[menu_no]), menu_item);
 
     g_signal_connect(G_OBJECT(menu_item), "activate",
-                     G_CALLBACK(menu_proc_cb), GINT_TO_POINTER(user_data));
+                     G_CALLBACK(menu_proc_cb), GINT_TO_POINTER(index));
     
     return menu_item;
 }
@@ -3233,7 +3155,7 @@
     set_mode(v->modetype);
 
     X->menus[M_ACC] = GET_WIDGET("accuracy_popup");
-    X->mrec[M_ACC] = &buttons[KEY_ACCURACY_MENU];
+    X->mrec[M_ACC] = &buttons[KEY_SET_ACCURACY];
     set_accuracy_menu_item(v->accuracy);
     X->menus[M_LSHF] = GET_WIDGET("left_shift_popup");
     X->mrec[M_LSHF] = &buttons[KEY_LEFT_SHIFT];
@@ -3241,9 +3163,9 @@
     X->mrec[M_RSHF] = &buttons[KEY_RIGHT_SHIFT];
     
     X->menus[M_CON] = GET_WIDGET("constants_popup");
-    X->mrec[M_CON] = &buttons[KEY_CONSTANTS_MENU];
+    X->mrec[M_CON] = &buttons[KEY_CONSTANT];
     X->menus[M_FUN] = GET_WIDGET("functions_popup");
-    X->mrec[M_FUN] = &buttons[KEY_FUNCTIONS_MENU];
+    X->mrec[M_FUN] = &buttons[KEY_FUNCTION];
     for (i = 0; i < MAXCONFUN; i++) {
         X->constant_menu_items[i] = create_menu_item_with_markup("", M_CON, i);
         X->function_menu_items[i] = create_menu_item_with_markup("", M_FUN, i);
Index: glade/gcalctool.glade
===================================================================
--- glade/gcalctool.glade	(revision 1776)
+++ glade/gcalctool.glade	(working copy)
@@ -7570,9 +7570,6 @@
 </widget>
 
 <widget class="GtkMenu" id="constants_popup">
-  <signal name="cancel" handler="menu_cancel_cb" last_modification_time="Wed, 31 Oct 2007 09:00:42 GMT"/>
-  <signal name="deactivate" handler="menu_cancel_cb" last_modification_time="Wed, 31 Oct 2007 09:01:03 GMT"/>
-
   <child>
     <widget class="GtkMenuItem" id="edit_constants1">
       <property name="visible">True</property>
@@ -7584,9 +7581,6 @@
 </widget>
 
 <widget class="GtkMenu" id="functions_popup">
-  <signal name="cancel" handler="menu_cancel_cb" last_modification_time="Wed, 31 Oct 2007 09:00:42 GMT"/>
-  <signal name="deactivate" handler="menu_cancel_cb" last_modification_time="Wed, 31 Oct 2007 09:01:03 GMT"/>
-
   <child>
     <widget class="GtkMenuItem" id="menuitem6">
       <property name="visible">True</property>
@@ -7774,18 +7768,12 @@
 </widget>
 
 <widget class="GtkMenu" id="memory_store_popup">
-  <signal name="cancel" handler="menu_cancel_cb" last_modification_time="Wed, 31 Oct 2007 09:00:42 GMT"/>
-  <signal name="deactivate" handler="menu_cancel_cb" last_modification_time="Wed, 31 Oct 2007 09:01:03 GMT"/>
 </widget>
 
 <widget class="GtkMenu" id="memory_exchange_popup">
-  <signal name="cancel" handler="menu_cancel_cb" last_modification_time="Wed, 31 Oct 2007 09:00:42 GMT"/>
-  <signal name="deactivate" handler="menu_cancel_cb" last_modification_time="Wed, 31 Oct 2007 09:01:03 GMT"/>
 </widget>
 
 <widget class="GtkMenu" id="memory_recall_popup">
-  <signal name="cancel" handler="menu_cancel_cb" last_modification_time="Wed, 31 Oct 2007 09:00:42 GMT"/>
-  <signal name="deactivate" handler="menu_cancel_cb" last_modification_time="Wed, 31 Oct 2007 09:01:03 GMT"/>
 </widget>
 
 </glade-interface>
