[gcalctool] Tidy up MathEquation



commit 15bb5168b1c8a21a038ebbde71bd21421ac79bee
Author: Robert Ancell <robert ancell gmail com>
Date:   Tue Apr 6 12:59:46 2010 +1000

    Tidy up MathEquation

 src/financial.c      |    2 +-
 src/math-buttons.c   |   92 +++---
 src/math-buttons.h   |    4 +-
 src/math-display.c   |  486 +++++----------------------
 src/math-display.h   |   29 --
 src/math-equation.c  |  934 +++++++++++++++++++++++++++++++++-----------------
 src/math-equation.h  |  149 +++------
 src/ui-preferences.c |   12 +-
 src/ui.c             |    6 +-
 9 files changed, 813 insertions(+), 901 deletions(-)
---
diff --git a/src/financial.c b/src/financial.c
index 43f0878..b855f21 100644
--- a/src/financial.c
+++ b/src/financial.c
@@ -75,7 +75,7 @@ calc_ddb(MathEquation *equation, MPNumber *t, MPNumber *cost, MPNumber *life, MP
     }
 
     if (len >= 0) {
-        display_set_error (equation, ("Error: the number of periods must be positive"));
+        math_equation_set_status (equation, ("Error: the number of periods must be positive"));
         mp_set_from_integer(0, t);
     }
 }
diff --git a/src/math-buttons.c b/src/math-buttons.c
index 9b42017..85656d6 100644
--- a/src/math-buttons.c
+++ b/src/math-buttons.c
@@ -23,7 +23,7 @@
 
 enum {
     PROP_0,
-    PROP_DISPLAY
+    PROP_EQUATION
 };
 
 #define MAXBITS 64      /* Bit panel: number of bit fields. */
@@ -31,7 +31,7 @@ enum {
 
 struct MathButtonsPrivate
 {
-    MathDisplay *display; // FIXME: Change to MathEquation
+    MathEquation *equation;
 
     ButtonMode mode;
     GtkBuilder *basic_ui, *advanced_ui, *financial_ui, *programming_ui;
@@ -140,9 +140,9 @@ static char *finc_dialog_fields[][5] = {
 
 
 MathButtons *
-math_buttons_new(MathDisplay *display)
+math_buttons_new(MathEquation *equation)
 {
-    return g_object_new (math_buttons_get_type(), "display", display, NULL);
+    return g_object_new (math_buttons_get_type(), "equation", equation, NULL);
 }
 
 
@@ -342,12 +342,12 @@ load_mode(MathButtons *buttons, ButtonMode mode)
         name = g_strdup_printf("calc_%d_button", i);
         button = GET_WIDGET(builder, name);     
         if (button)
-            gtk_button_set_label(GTK_BUTTON(button), math_equation_get_digit_text(math_display_get_equation(buttons->priv->display), i));
+            gtk_button_set_label(GTK_BUTTON(button), math_equation_get_digit_text(buttons->priv->equation, i));
         g_free(name);
     }
     widget = GET_WIDGET(builder, "calc_numeric_point_button");
     if (widget)
-        gtk_button_set_label(GTK_BUTTON(widget), math_equation_get_numeric_point_text(math_display_get_equation(buttons->priv->display)));
+        gtk_button_set_label(GTK_BUTTON(widget), math_equation_get_numeric_point_text(buttons->priv->equation));
 
     /* Connect super and subscript */
     for (i = 0; i < 10; i++) {
@@ -360,13 +360,13 @@ load_mode(MathButtons *buttons, ButtonMode mode)
     widget = GET_WIDGET(builder, "superscript_togglebutton");
     if (widget) {
         buttons->priv->superscript_toggles = g_list_append(buttons->priv->superscript_toggles, widget);
-        if (math_display_get_number_mode(buttons->priv->display) == SUPERSCRIPT)
+        if (math_equation_get_number_mode(buttons->priv->equation) == SUPERSCRIPT)
             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
     }
     widget = GET_WIDGET(builder, "subscript_togglebutton");
     if (widget) {
         buttons->priv->subscript_toggles = g_list_append(buttons->priv->subscript_toggles, widget);
-        if (math_display_get_number_mode(buttons->priv->display) == SUBSCRIPT)
+        if (math_equation_get_number_mode(buttons->priv->equation) == SUBSCRIPT)
             gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
     }
 
@@ -501,7 +501,7 @@ G_MODULE_EXPORT
 void
 base_cb(GtkWidget *widget, MathButtons *buttons)
 {
-    math_display_set_base(buttons->priv->display, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "base")));
+    math_equation_set_base(buttons->priv->equation, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "base")));
 }
 
 
@@ -509,7 +509,7 @@ G_MODULE_EXPORT
 void
 exponent_cb(GtkWidget *widget, MathButtons *buttons)
 {
-    math_display_insert_exponent(buttons->priv->display);
+    math_equation_insert_exponent(buttons->priv->equation);
 }
 
 
@@ -517,7 +517,7 @@ G_MODULE_EXPORT
 void
 subtract_cb(GtkWidget *widget, MathButtons *buttons)
 {
-    math_display_insert_subtract(buttons->priv->display);  
+    math_equation_insert_subtract(buttons->priv->equation);  
 }
 
 
@@ -525,7 +525,7 @@ G_MODULE_EXPORT
 void
 button_cb(GtkWidget *widget, MathButtons *buttons)
 {
-    math_display_insert(buttons->priv->display, g_object_get_data(G_OBJECT(widget), "calc_text"));
+    math_equation_insert(buttons->priv->equation, g_object_get_data(G_OBJECT(widget), "calc_text"));
 }
 
 
@@ -533,14 +533,14 @@ G_MODULE_EXPORT
 void
 store_menu_cb(GtkMenuItem *menu, MathButtons *buttons)
 {
-    math_display_store(buttons->priv->display, g_object_get_data(G_OBJECT(menu), "register_id"));
+    math_equation_store(buttons->priv->equation, g_object_get_data(G_OBJECT(menu), "register_id"));
 }
 
 
 static void
 recall_menu_cb(GtkMenuItem *menu, MathButtons *buttons)
 {
-    math_display_recall(buttons->priv->display, g_object_get_data(G_OBJECT(menu), "register_id"));  
+    math_equation_recall(buttons->priv->equation, g_object_get_data(G_OBJECT(menu), "register_id"));  
 }
 
 
@@ -548,7 +548,7 @@ G_MODULE_EXPORT
 void
 solve_cb(GtkWidget *widget, MathButtons *buttons)
 {
-    math_display_solve(buttons->priv->display);
+    math_equation_solve(buttons->priv->equation);
 }
 
 
@@ -556,14 +556,14 @@ G_MODULE_EXPORT
 void
 clear_cb(GtkWidget *widget, MathButtons *buttons)
 {
-    math_display_clear(buttons->priv->display);
+    math_equation_clear(buttons->priv->equation);
 }
 
 
 static void
 shift_cb(GtkWidget *widget, MathButtons *buttons)
 {
-    math_display_shift(buttons->priv->display, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "shiftcount")));
+    math_equation_shift(buttons->priv->equation, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "shiftcount")));
 }
 
 
@@ -603,7 +603,7 @@ update_store_menu(MathButtons *buttons)
 
         t = register_get_value(registers[i]);
         if (t)
-            display_make_number(math_display_get_equation(buttons->priv->display), value, 1024, t);
+            display_make_number(buttons->priv->equation, value, 1024, t);
         mstr = g_strdup_printf("<span weight=\"bold\">%s</span> = %s", registers[i], value);
         gtk_label_set_markup_with_mnemonic(GTK_LABEL(buttons->priv->store_menu_labels[i]), mstr);
         g_free(mstr);
@@ -679,7 +679,7 @@ update_recall_menu(MathButtons *buttons)
 
         t = register_get_value(registers[i]);
         if (t)
-            display_make_number(math_display_get_equation(buttons->priv->display), value, 1024, t);
+            display_make_number(buttons->priv->equation, value, 1024, t);
         mstr = g_strdup_printf("<span weight=\"bold\">%s</span> = %s", registers[i], value);
         gtk_label_set_markup_with_mnemonic(GTK_LABEL(buttons->priv->recall_menu_labels[i]), mstr);
         g_free(mstr);
@@ -786,7 +786,7 @@ G_MODULE_EXPORT
 void
 factorize_cb(GtkWidget *widget, MathButtons *buttons)
 {
-    math_display_factorize (buttons->priv->display);
+    math_equation_factorize (buttons->priv->equation);
 }
 
 
@@ -794,7 +794,7 @@ G_MODULE_EXPORT
 void
 digit_cb(GtkWidget *widget, MathButtons *buttons)
 {
-    math_display_insert_digit(buttons->priv->display, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "calc_digit")));
+    math_equation_insert_digit(buttons->priv->equation, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "calc_digit")));
 }
 
 
@@ -802,7 +802,7 @@ G_MODULE_EXPORT
 void
 numeric_point_cb(GtkWidget *widget, MathButtons *buttons)
 {
-    math_display_insert_numeric_point(buttons->priv->display);
+    math_equation_insert_numeric_point(buttons->priv->equation);
 }
 
 
@@ -878,7 +878,7 @@ finc_response_cb(GtkWidget *widget, gint response_id, MathButtons *buttons)
     }
     gtk_widget_grab_focus(GET_WIDGET(buttons->priv->financial_ui, finc_dialog_fields[dialog][0]));
 
-    do_finc_expression(math_display_get_equation(buttons->priv->display), dialog, &arg[0], &arg[1], &arg[2], &arg[3]);
+    do_finc_expression(buttons->priv->equation, dialog, &arg[0], &arg[1], &arg[2], &arg[3]);
 }
 
 
@@ -1001,7 +1001,7 @@ currency_cb(GtkWidget *widget, MathButtons *buttons)
     win = GTK_DIALOG(gtk_builder_get_object(buttons->priv->financial_ui, "currency_dialog"));
     c_amount_upper = GTK_SPIN_BUTTON(gtk_builder_get_object(buttons->priv->financial_ui, "currency_amount_upper"));
     c_amount_lower = GTK_SPIN_BUTTON(gtk_builder_get_object(buttons->priv->financial_ui, "currency_amount_lower"));
-    if (display_is_usable_number(math_display_get_equation(buttons->priv->display), &display_val)) {
+    if (display_is_usable_number(buttons->priv->equation, &display_val)) {
         double start_val = mp_cast_to_double(&display_val);
         gtk_spin_button_set_value(c_amount_upper, start_val);
     }
@@ -1014,7 +1014,7 @@ currency_cb(GtkWidget *widget, MathButtons *buttons)
         mp_set_from_string(result, &display_val);
         g_free(result);
 
-        display_set_number(math_display_get_equation(buttons->priv->display), &display_val);
+        display_set_number(buttons->priv->equation, &display_val);
     }
 
     gtk_widget_hide(GTK_WIDGET(win));
@@ -1030,7 +1030,7 @@ character_code_dialog_response_cb(GtkWidget *dialog, gint response_id, MathButto
     text = gtk_entry_get_text(GTK_ENTRY(buttons->priv->character_code_entry));
 
     if (response_id == GTK_RESPONSE_OK)
-        math_display_insert_character(buttons->priv->display, text);
+        math_equation_insert_character(buttons->priv->equation, text);
 
     gtk_widget_hide(dialog);
 }
@@ -1057,7 +1057,7 @@ G_MODULE_EXPORT
 gboolean
 bit_toggle_cb(GtkWidget *event_box, GdkEventButton *event, MathButtons *buttons)
 {
-    math_display_toggle_bit(buttons->priv->display, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(event_box), "bit_index")));
+    math_equation_toggle_bit(buttons->priv->equation, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(event_box), "bit_index")));
     return TRUE;
 }
 
@@ -1068,9 +1068,9 @@ void
 set_superscript_cb(GtkWidget *widget, MathButtons *buttons)
 {
     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
-       math_display_set_number_mode(buttons->priv->display, SUPERSCRIPT);
-    else if (math_display_get_number_mode(buttons->priv->display) == SUPERSCRIPT)
-       math_display_set_number_mode(buttons->priv->display, NORMAL);
+       math_equation_set_number_mode(buttons->priv->equation, SUPERSCRIPT);
+    else if (math_equation_get_number_mode(buttons->priv->equation) == SUPERSCRIPT)
+       math_equation_set_number_mode(buttons->priv->equation, NORMAL);
 }
 
 
@@ -1079,9 +1079,9 @@ void
 set_subscript_cb(GtkWidget *widget, MathButtons *buttons)
 {
     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
-       math_display_set_number_mode(buttons->priv->display, SUBSCRIPT);
-    else if (math_display_get_number_mode(buttons->priv->display) == SUBSCRIPT)
-       math_display_set_number_mode(buttons->priv->display, NORMAL);
+       math_equation_set_number_mode(buttons->priv->equation, SUBSCRIPT);
+    else if (math_equation_get_number_mode(buttons->priv->equation) == SUBSCRIPT)
+       math_equation_set_number_mode(buttons->priv->equation, NORMAL);
 }
 
 
@@ -1109,12 +1109,12 @@ bitfield_changed_cb(MathEquation *equation, MathButtons *buttons)
 
 
 static void
-number_mode_changed_cb(MathDisplay *display, MathButtons *buttons)
+number_mode_changed_cb(MathEquation *equation, MathButtons *buttons)
 {
     GList *i;
     NumberMode mode;
   
-    mode = math_display_get_number_mode(display);
+    mode = math_equation_get_number_mode(equation);
 
     for (i = buttons->priv->superscript_toggles; i; i = i->next) {
         GtkWidget *widget = i->data;
@@ -1138,10 +1138,10 @@ math_buttons_set_property (GObject      *object,
     self = MATH_BUTTONS (object);
 
     switch (prop_id) {
-    case PROP_DISPLAY:
-        self->priv->display = g_value_get_object (value);
-        g_signal_connect(self->priv->display, "number-mode-changed", G_CALLBACK(number_mode_changed_cb), self);
-        g_signal_connect(math_display_get_equation(self->priv->display), "bitfield-changed", G_CALLBACK(bitfield_changed_cb), self);
+    case PROP_EQUATION:
+        self->priv->equation = g_value_get_object (value);
+        g_signal_connect(self->priv->equation, "number-mode-changed", G_CALLBACK(number_mode_changed_cb), self);
+        g_signal_connect(self->priv->equation, "bitfield-changed", G_CALLBACK(bitfield_changed_cb), self);
         break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1161,8 +1161,8 @@ math_buttons_get_property (GObject    *object,
     self = MATH_BUTTONS (object);
 
     switch (prop_id) {
-    case PROP_DISPLAY:
-        g_value_set_object (value, self->priv->display);
+    case PROP_EQUATION:
+        g_value_set_object (value, self->priv->equation);
         break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1182,11 +1182,11 @@ math_buttons_class_init (MathButtonsClass *klass)
     g_type_class_add_private (klass, sizeof (MathButtonsPrivate));
 
     g_object_class_install_property (object_class,
-                                     PROP_DISPLAY,
-                                     g_param_spec_object ("display",
-                                                          "display",
-                                                          "Display being controlled",
-                                                          math_display_get_type(),
+                                     PROP_EQUATION,
+                                     g_param_spec_object ("equation",
+                                                          "equation",
+                                                          "Equation being controlled",
+                                                          math_equation_get_type(),
                                                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 }
 
diff --git a/src/math-buttons.h b/src/math-buttons.h
index be05e2b..1257014 100644
--- a/src/math-buttons.h
+++ b/src/math-buttons.h
@@ -21,7 +21,7 @@
 
 #include <glib-object.h>
 #include <gtk/gtk.h>
-#include "math-display.h"
+#include "math-equation.h"
 
 G_BEGIN_DECLS
 
@@ -49,7 +49,7 @@ typedef enum {
 
 GType math_buttons_get_type();
 
-MathButtons *math_buttons_new(MathDisplay *display);
+MathButtons *math_buttons_new(MathEquation *equation);
 
 void math_buttons_set_mode(MathButtons *buttons, ButtonMode mode);
 
diff --git a/src/math-display.c b/src/math-display.c
index 13984dd..9724576 100644
--- a/src/math-display.c
+++ b/src/math-display.c
@@ -28,29 +28,12 @@ enum {
     PROP_EQUATION
 };
 
-enum {
-    NUMBER_MODE_CHANGED,
-    LAST_SIGNAL
-};
-static guint signals[LAST_SIGNAL] = { 0, };
-
 struct MathDisplayPrivate
 {
     MathEquation *equation;
 
-    NumberMode number_mode;
-    gboolean can_super_minus;
-
     GtkWidget *display_item;           /* Calculator display. */
-    GtkTextBuffer *display_buffer;     /* Buffer used in display */
     GtkTextBuffer *info_buffer;        /* Buffer used in info messages */
-
-    GdkAtom clipboard_atom;
-    GdkAtom primary_atom;
-    char *shelf;                       /* PUT selection shelf contents. */
-
-    /* Last text entered */
-    char *last_text;
 };
 
 G_DEFINE_TYPE (MathDisplay, math_display, GTK_TYPE_VBOX);
@@ -71,207 +54,6 @@ math_display_get_equation(MathDisplay *display)
 }
 
 
-gchar *
-math_display_get_text(MathDisplay *display)
-{
-    GtkTextIter start, end;
-    gtk_text_buffer_get_bounds(display->priv->display_buffer, &start, &end);
-    return gtk_text_buffer_get_text(display->priv->display_buffer, &start, &end, FALSE);
-}
-
-
-void
-math_display_set_number_mode(MathDisplay *display, NumberMode mode)
-{
-    if (display->priv->number_mode == mode)
-        return;
-
-    display->priv->can_super_minus = mode == SUPERSCRIPT;
-
-    display->priv->number_mode = mode;
-    g_signal_emit(display, signals[NUMBER_MODE_CHANGED], 0);
-}
-
-
-NumberMode
-math_display_get_number_mode(MathDisplay *display)
-{
-    return display->priv->number_mode;
-}
-
-
-static void
-do_button(MathDisplay *display, int function, gpointer arg)
-{
-    GtkTextIter start, end;
-    gint cursor_start, cursor_end;
-  
-    /* Can't enter superscript minus after entering digits */
-    if (function == FN_TEXT && (strstr("�¹²³������", (char *)arg) != NULL || strcmp("�", (char *)arg) == 0))
-        display->priv->can_super_minus = FALSE;
-
-    /* Disable super/subscript mode when finished entering */
-    if (function == FN_CALCULATE ||
-        function == FN_CLEAR ||
-        (function == FN_TEXT && strstr("â?»â?°Â¹Â²Â³â?´â?µâ?¶â?·â?¸â?¹â??â??â??â??â??â??â??â??â??â??", (char *)arg) == NULL)) {
-        math_display_set_number_mode(display, NORMAL);
-    }
-
-    if (gtk_text_buffer_get_selection_bounds(display->priv->display_buffer, &start, &end)) {
-        cursor_start = gtk_text_iter_get_offset(&start);
-        cursor_end = gtk_text_iter_get_offset(&end);
-    }
-    else {
-        g_object_get(G_OBJECT(display->priv->display_buffer), "cursor-position", &cursor_start, NULL);
-        if (cursor_start == gtk_text_buffer_get_char_count(display->priv->display_buffer))
-            cursor_start = -1;
-        cursor_end = cursor_start;
-    }
-
-    /* Some keyboards don't have a '^' button so convert two multiplies to one '^' */
-    if (cursor_start == cursor_end &&
-        function == FN_TEXT && display->priv->last_text != NULL &&
-        strcmp((char *)arg, "Ã?") == 0 && strcmp(display->priv->last_text, "Ã?") == 0) {
-        do_button(display, FN_BACKSPACE, NULL);
-        do_button(display, FN_TEXT, "^");
-    }
-    else {
-        display_do_function(display->priv->equation, function, arg, cursor_start, cursor_end);
-        if (function == FN_TEXT)
-            display->priv->last_text = (char *)arg;
-        else
-            display->priv->last_text = NULL;
-    }
-}
-
-
-void
-math_display_store(MathDisplay *display, const gchar *name)
-{
-    do_button(display, FN_STORE, (gpointer)name);
-}
-
-
-void
-math_display_recall(MathDisplay *display, const gchar *name)
-{
-    do_button(display, FN_RECALL, (gpointer)name);
-}
-
-
-void
-math_display_insert(MathDisplay *display, const gchar *text)
-{
-    do_button(display, FN_TEXT, (gpointer) text);
-}
-
-
-void
-math_display_insert_digit(MathDisplay *display, unsigned int digit)
-{
-    static const char *subscript_digits[] = {"â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", NULL};
-    static const char *superscript_digits[] = {"�", "¹", "²", "³", "�", "�", "�", "�", "�", "�", NULL};
-
-    if (display->priv->number_mode == NORMAL || digit >= 10)
-        math_display_insert(display, math_equation_get_digit_text(display->priv->equation, digit));
-    else if (display->priv->number_mode == SUPERSCRIPT)
-        math_display_insert(display, superscript_digits[digit]);
-    else if (display->priv->number_mode == SUBSCRIPT)
-        math_display_insert(display, subscript_digits[digit]);
-}
-
-
-void
-math_display_insert_numeric_point(MathDisplay *display)
-{
-    math_display_insert(display, math_equation_get_numeric_point_text(display->priv->equation));
-}
-
-
-void
-math_display_insert_exponent(MathDisplay *display)
-{
-    math_display_insert(display, "Ã?10");
-    math_display_set_number_mode(display, SUPERSCRIPT);
-}
-
-
-void
-math_display_insert_character(MathDisplay *display, const char *character)
-{
-    do_button(display, FN_INSERT_CHARACTER, (gpointer)character);
-}
-
-
-void
-math_display_insert_subtract(MathDisplay *display)
-{
-    if (display->priv->number_mode == SUPERSCRIPT && display->priv->can_super_minus) {
-        math_display_insert(display, "â?»");
-        display->priv->can_super_minus = FALSE;
-    }
-    else {
-        math_display_insert(display, "â??");
-        math_display_set_number_mode(display, NORMAL);
-    }
-}
-
-
-void
-math_display_solve(MathDisplay *display)
-{
-    do_button(display, FN_CALCULATE, NULL);
-}
-
-
-void
-math_display_factorize(MathDisplay *display)
-{
-    do_button(display, FN_FACTORIZE, NULL);
-}
-
-
-void
-math_display_clear(MathDisplay *display)
-{
-    do_button(display, FN_CLEAR, NULL);  
-}
-
-
-void
-math_display_shift(MathDisplay *display, gint count)
-{
-    do_button(display, FN_SHIFT, GINT_TO_POINTER(count));
-}
-
-
-void
-math_display_toggle_bit(MathDisplay *display, guint bit)
-{
-    do_button(display, FN_TOGGLE_BIT, GINT_TO_POINTER(bit));
-}
-
-
-void
-math_display_copy(MathDisplay *display)
-{
-    gchar *string = NULL;
-    GtkTextIter start, end;
-
-    if (gtk_text_buffer_get_selection_bounds(display->priv->display_buffer, &start, &end) == TRUE)
-        string = gtk_text_buffer_get_text(display->priv->display_buffer, &start, &end, FALSE);
-    else
-        string = math_display_get_text(display);
-
-    if (display->priv->shelf != NULL)
-        g_free(display->priv->shelf);
-    display->priv->shelf = g_locale_from_utf8(string, strlen(string), NULL, NULL, NULL);
-    g_free(string);
-
-    gtk_clipboard_set_text(gtk_clipboard_get(display->priv->clipboard_atom), display->priv->shelf, -1);
-}
-
-
 static gboolean
 check_for_localized_numeric_point(MathDisplay *display, int keyval)
 {
@@ -315,115 +97,115 @@ main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, GCalctoolUI *ui)
         switch(event->keyval)
         {
         case GDK_b:
-            math_display_set_base(display, 2);
+            math_equation_set_base(display->priv->equation, 2);
             return TRUE;
         case GDK_d:
-            math_display_set_base(display, 10);
+            math_equation_set_base(display->priv->equation, 10);
             return TRUE;
         case GDK_e:
-            math_display_insert_exponent(display);
+            math_equation_insert_exponent(display->priv->equation);
             return TRUE;
         case GDK_f:
-            math_display_factorize(display);
+            math_equation_factorize(display->priv->equation);
             return TRUE;
         case GDK_h:
-            math_display_set_base(display, 16);
+            math_equation_set_base(display->priv->equation, 16);
             return TRUE;
         case GDK_i:
-            math_display_insert(display, "�¹");
+            math_equation_insert(display->priv->equation, "�¹");
             return TRUE;
         case GDK_o:
-            math_display_set_base(display, 8);
+            math_equation_set_base(display->priv->equation, 8);
             return TRUE;
         case GDK_p:
-            math_display_insert(display, "Ï?");
+            math_equation_insert(display->priv->equation, "Ï?");
             return TRUE;
         case GDK_r:
-            math_display_insert(display, "â??");
+            math_equation_insert(display->priv->equation, "â??");
             return TRUE;
         case GDK_u:
-            math_display_insert(display, "µ");
+            math_equation_insert(display->priv->equation, "µ");
             return TRUE;
         }
     }
-    if (state == GDK_CONTROL_MASK || display->priv->number_mode == SUPERSCRIPT) {
+    if (state == GDK_CONTROL_MASK || math_equation_get_number_mode(display->priv->equation) == SUPERSCRIPT) {
         switch(event->keyval)
         {
         case GDK_0:
-            math_display_insert(display, "â?°");
+            math_equation_insert(display->priv->equation, "â?°");
             return TRUE;
         case GDK_1:
-            math_display_insert(display, "¹");
+            math_equation_insert(display->priv->equation, "¹");
             return TRUE;
         case GDK_2:
-            math_display_insert(display, "²");
+            math_equation_insert(display->priv->equation, "²");
             return TRUE;
         case GDK_3:
-            math_display_insert(display, "³");
+            math_equation_insert(display->priv->equation, "³");
             return TRUE;
         case GDK_4:
-            math_display_insert(display, "â?´");
+            math_equation_insert(display->priv->equation, "â?´");
             return TRUE;
         case GDK_5:
-            math_display_insert(display, "â?µ");
+            math_equation_insert(display->priv->equation, "â?µ");
             return TRUE;
         case GDK_6:
-            math_display_insert(display, "â?¶");
+            math_equation_insert(display->priv->equation, "â?¶");
             return TRUE;
         case GDK_7:
-            math_display_insert(display, "â?·");
+            math_equation_insert(display->priv->equation, "â?·");
             return TRUE;
         case GDK_8:
-            math_display_insert(display, "â?¸");
+            math_equation_insert(display->priv->equation, "â?¸");
             return TRUE;
         case GDK_9:
-            math_display_insert(display, "â?¹");
+            math_equation_insert(display->priv->equation, "â?¹");
             return TRUE;
         }
     }
-    else if (state == GDK_MOD1_MASK || display->priv->number_mode == SUBSCRIPT) {
+    else if (state == GDK_MOD1_MASK || math_equation_get_number_mode(display->priv->equation) == SUBSCRIPT) {
         switch(event->keyval)
         {
         case GDK_0:
-            math_display_insert(display, "â??");
+            math_equation_insert(display->priv->equation, "â??");
             return TRUE;
         case GDK_1:
-            math_display_insert(display, "â??");
+            math_equation_insert(display->priv->equation, "â??");
             return TRUE;
         case GDK_2:
-            math_display_insert(display, "â??");
+            math_equation_insert(display->priv->equation, "â??");
             return TRUE;
         case GDK_3:
-            math_display_insert(display, "â??");
+            math_equation_insert(display->priv->equation, "â??");
             return TRUE;
         case GDK_4:
-            math_display_insert(display, "â??");
+            math_equation_insert(display->priv->equation, "â??");
             return TRUE;
         case GDK_5:
-            math_display_insert(display, "â??");
+            math_equation_insert(display->priv->equation, "â??");
             return TRUE;
         case GDK_6:
-            math_display_insert(display, "â??");
+            math_equation_insert(display->priv->equation, "â??");
             return TRUE;
         case GDK_7:
-            math_display_insert(display, "â??");
+            math_equation_insert(display->priv->equation, "â??");
             return TRUE;
         case GDK_8:
-            math_display_insert(display, "â??");
+            math_equation_insert(display->priv->equation, "â??");
             return TRUE;
         case GDK_9:
-            math_display_insert(display, "â??");
+            math_equation_insert(display->priv->equation, "â??");
             return TRUE;
         }
     }
 
     /* Delete in display */
     if (event->keyval == GDK_Delete && state == 0 && (event->state & GDK_SHIFT_MASK) == 0) {
-        do_button(display, FN_DELETE, NULL);
+        math_equation_delete(display->priv->equation);
         return TRUE;
     }
     if (event->keyval == GDK_BackSpace && state == 0 && (event->state & GDK_SHIFT_MASK) == 0) {
-        do_button(display, FN_BACKSPACE, NULL);
+        math_equation_backspace(display->priv->equation);
         return TRUE;
     }
 
@@ -431,7 +213,7 @@ main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, GCalctoolUI *ui)
     if ((event->keyval == GDK_Escape && state == 0) ||
         (event->keyval == GDK_BackSpace && state == GDK_CONTROL_MASK) ||
         (event->keyval == GDK_Delete && state == GDK_SHIFT_MASK)) {
-        math_display_clear(display);
+        math_equation_clear(display->priv->equation);
         return TRUE;
     }
 
@@ -439,7 +221,7 @@ main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, GCalctoolUI *ui)
     if ((event->keyval == GDK_Return && state == 0) ||
         (event->keyval == GDK_KP_Enter && state == 0)) {
         if (gtk_widget_has_focus(display->priv->display_item)) {
-            math_display_solve(display);
+            math_equation_solve(display->priv->equation);
             return TRUE;
         }
         else {
@@ -449,7 +231,7 @@ main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, GCalctoolUI *ui)
 
     if (state == GDK_CONTROL_MASK && event->keyval == GDK_minus) 
     {
-        math_display_insert(display, "â?»");
+        math_equation_insert(display->priv->equation, "â?»");
         return TRUE;
     }
 
@@ -459,24 +241,24 @@ main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, GCalctoolUI *ui)
     // FIXME: event->string deprecated
 
     if (strcmp(event->string, "-") == 0 || strcmp(event->string, "â??") == 0) {
-        math_display_insert_subtract(display);
+        math_equation_insert_subtract(display->priv->equation);
         return TRUE;
     }
 
     for (i = 0; conversions[i]; i++) {
         if (strcmp(event->string, conversions[i]) == 0) {
-            math_display_insert(display, conversion_values[i]);
+            math_equation_insert(display->priv->equation, conversion_values[i]);
             return TRUE;
         }
     }
     if (strcmp(event->string, ".") == 0) {
-        math_display_insert_numeric_point(display);
+        math_equation_insert_numeric_point(display->priv->equation);
         return TRUE;
     }
 
     /* Some keyboards use this keyval for '^' (e.g. German) */
     if (event->keyval == GDK_dead_circumflex) {
-        math_display_insert(display, "^");
+        math_equation_insert(display->priv->equation, "^");
         return TRUE;
     }
 
@@ -489,7 +271,7 @@ main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, GCalctoolUI *ui)
         // FIXME: Should open right shift menu (programming mode)
         return TRUE;
     case '\n':
-        math_display_solve(display);
+        math_equation_solve(display->priv->equation);
         return TRUE;
     }
   
@@ -498,7 +280,7 @@ main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, GCalctoolUI *ui)
         return FALSE;
 
     if (event->string[0] != '\0') {
-        math_display_insert(display, event->string);
+        math_equation_insert(display->priv->equation, event->string);
         return TRUE;
     }
 
@@ -510,52 +292,7 @@ main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, GCalctoolUI *ui)
 static void
 popup_paste_cb(GtkWidget *menu, MathDisplay *display)
 {
-    math_display_paste(display);
-}
-
-
-// FIXME: Kill this
-static void
-for_each_menu(GtkWidget *widget, MathDisplay *display)
-{
-    /* Find the "Paste" entry and activate it (see bug #317786).
-     * It is disabled because the GtkEntry is not marked as editable.
-     */
-    if (strcmp(G_OBJECT_TYPE_NAME(widget), "GtkImageMenuItem") == 0) {
-        GtkWidget *label = gtk_bin_get_child(GTK_BIN(widget));
-
-         if (strcmp(gtk_label_get_text(GTK_LABEL(label)), _("Paste")) == 0) {
-            if (gtk_clipboard_wait_is_text_available(gtk_clipboard_get(display->priv->clipboard_atom))) {
-                gtk_widget_set_sensitive(GTK_WIDGET(widget), TRUE);
-                g_signal_connect(GTK_OBJECT(widget), "activate",
-                                 G_CALLBACK(popup_paste_cb), display);
-            }
-        }
-    }
-}
-
-
-// FIXME: Kill this
-static void
-buffer_populate_popup_cb(GtkTextView *textview, GtkMenu *menu, MathDisplay *display)
-{
-    gtk_container_foreach(GTK_CONTAINER(menu), (GtkCallback)for_each_menu, display);
-}
-
-
-static void
-on_paste(GtkClipboard *clipboard, const gchar *text, MathDisplay *display)
-{
-    if (text != NULL)
-        do_button(display, FN_PASTE, (gpointer) text);
-}
-
-
-void
-math_display_paste(MathDisplay *display)
-{
-    gtk_clipboard_request_text(gtk_clipboard_get(display->priv->clipboard_atom),
-                               (GtkClipboardTextReceivedFunc)on_paste, display);
+    math_equation_paste(display->priv->equation);
 }
 
 
@@ -563,7 +300,7 @@ static gboolean
 middle_click_paste_cb(GtkWidget *widget, GdkEventButton *event, MathDisplay *display)
 {
     if (event->button == 2)
-        math_display_paste(display);
+        math_equation_paste(display->priv->equation);
 
     return FALSE;
 }
@@ -572,64 +309,55 @@ middle_click_paste_cb(GtkWidget *widget, GdkEventButton *event, MathDisplay *dis
 static void
 paste_cb(GtkWidget *widget, MathDisplay *display)
 {
-    math_display_paste(display);
+    math_equation_paste(display->priv->equation);
 }
 
 
-void
-math_display_set_base(MathDisplay *display, gint base)
+static void
+status_changed_cb(MathEquation *equation, MathDisplay *display)
 {
-    /* If has a number already in a base, then solve and convert it */
-    if (!display_is_result(display->priv->equation) && display_is_number_with_base(display->priv->equation))
-        math_display_solve(display);
-
-    if (display_is_result(display->priv->equation)) {
-        if (base == 2)
-            display_convert(display->priv->equation, BIN);
-        else if (base == 8)
-            display_convert(display->priv->equation, OCT);
-        else if (base == 16)
-            display_convert(display->priv->equation, HEX);
-        else
-            display_convert(display->priv->equation, DEC);
-    }
-    else {
-        if (base == 2)
-            math_display_insert(display, "â??");
-        else if (base == 8)
-            math_display_insert(display, "â??");
-        else if (base == 16)
-            math_display_insert(display, "â??â??");
-    }
+    gtk_text_buffer_set_text(display->priv->info_buffer, math_equation_get_status(equation), -1);
 }
 
 
 static void
-display_changed_cb(MathEquation *equation, MathDisplay *display)
+create_gui(MathDisplay *display)
 {
-    GtkTextIter iter;
-    GtkAdjustment *adj;
-    const gchar *str;
-    gint cursor;
-  
-    str = math_equation_get_text(equation);
-    cursor = math_equation_get_cursor(equation);
+    GtkWidget *vbox, *info_view;
+    PangoFontDescription *font_desc;
 
-    gtk_text_buffer_set_text(display->priv->display_buffer, str, -1);
+    display->priv->display_item = gtk_text_view_new_with_buffer(GTK_TEXT_BUFFER(display->priv->equation));
+    gtk_text_view_set_editable(GTK_TEXT_VIEW(display->priv->display_item), FALSE);
+    gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(display->priv->display_item), 8);
+    gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(display->priv->display_item), 2);
+    gtk_text_view_set_right_margin(GTK_TEXT_VIEW(display->priv->display_item), 6);
+    gtk_text_view_set_justification(GTK_TEXT_VIEW(display->priv->display_item), GTK_JUSTIFY_RIGHT);
+    g_signal_connect(display->priv->display_item, "button-release-event", G_CALLBACK(middle_click_paste_cb), display);
+    g_signal_connect(display->priv->display_item, "paste-clipboard", G_CALLBACK(paste_cb), display);
+    gtk_box_pack_start(GTK_BOX(display), display->priv->display_item, TRUE, TRUE, 0);
 
-    if (cursor < 0)
-        gtk_text_buffer_get_end_iter(display->priv->display_buffer, &iter);
-    else
-        gtk_text_buffer_get_iter_at_offset(display->priv->display_buffer, &iter, cursor);
-    gtk_text_buffer_place_cursor(display->priv->display_buffer, &iter);
-    gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(display->priv->display_item), &iter, 0.0, TRUE, 1.0, 0.0);
-}
+    gtk_widget_ensure_style(display->priv->display_item);
+    font_desc = pango_font_description_copy(gtk_widget_get_style(display->priv->display_item)->font_desc);
+    pango_font_description_set_size(font_desc, 16 * PANGO_SCALE);
+    gtk_widget_modify_font(display->priv->display_item, font_desc);
+    pango_font_description_free(font_desc);
+    gtk_widget_set_name(display->priv->display_item, "displayitem");
+    atk_object_set_role(gtk_widget_get_accessible(display->priv->display_item), ATK_ROLE_EDITBAR);
+  
+    info_view = gtk_text_view_new();
+    gtk_widget_set_can_focus(info_view, TRUE); // FIXME: This should be FALSE but it locks the cursor inside the main view for some reason
+    gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(info_view), FALSE); // FIXME: Just here so when incorrectly gets focus doesn't look editable
+    gtk_text_view_set_editable(GTK_TEXT_VIEW(info_view), FALSE);
+    gtk_text_view_set_justification(GTK_TEXT_VIEW(info_view), GTK_JUSTIFY_RIGHT);
+    gtk_text_view_set_right_margin(GTK_TEXT_VIEW(info_view), 6);
+    gtk_box_pack_start(GTK_BOX(display), info_view, FALSE, TRUE, 0);
+    display->priv->info_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(info_view));
 
+    gtk_widget_show(info_view);
+    gtk_widget_show(display->priv->display_item);
 
-static void
-status_changed_cb(MathEquation *equation, MathDisplay *display)
-{
-    gtk_text_buffer_set_text(display->priv->info_buffer, math_equation_get_status(equation), -1);
+    g_signal_connect(display->priv->equation, "status-changed", G_CALLBACK(status_changed_cb), display);
+    status_changed_cb(display->priv->equation, display);
 }
 
 
@@ -646,9 +374,7 @@ math_display_set_property(GObject      *object,
     switch (prop_id) {
     case PROP_EQUATION:
         self->priv->equation = g_value_get_object (value);
-        g_signal_connect(self->priv->equation, "display-changed", G_CALLBACK(display_changed_cb), self);      
-        g_signal_connect(self->priv->equation, "status-changed", G_CALLBACK(status_changed_cb), self);
-        status_changed_cb(self->priv->equation, self);
+        create_gui(self);
         break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -695,15 +421,6 @@ math_display_class_init (MathDisplayClass *klass)
                                                         "Equation being displayed",
                                                         math_equation_get_type(),
                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-    signals[NUMBER_MODE_CHANGED] =
-        g_signal_new ("number-mode-changed",
-                      G_TYPE_FROM_CLASS (klass),
-                      G_SIGNAL_RUN_LAST,
-                      G_STRUCT_OFFSET (MathDisplayClass, number_mode_changed),
-                      NULL, NULL,
-                      g_cclosure_marshal_VOID__VOID,
-                      G_TYPE_NONE, 0);
 }
 
 /* FIXME
@@ -722,44 +439,5 @@ math_display_class_init (MathDisplayClass *klass)
 static void 
 math_display_init(MathDisplay *display)
 {
-    GtkWidget *vbox, *info_view;
-    PangoFontDescription *font_desc;
-
     display->priv = G_TYPE_INSTANCE_GET_PRIVATE (display, math_display_get_type(), MathDisplayPrivate);
-
-    display->priv->primary_atom = gdk_atom_intern("PRIMARY", FALSE);
-    display->priv->clipboard_atom = gdk_atom_intern("CLIPBOARD", FALSE);
-
-    display->priv->display_item = gtk_text_view_new();
-    gtk_text_view_set_editable(GTK_TEXT_VIEW(display->priv->display_item), FALSE);
-    gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(display->priv->display_item), 8);
-    gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(display->priv->display_item), 2);
-    gtk_text_view_set_right_margin(GTK_TEXT_VIEW(display->priv->display_item), 6);
-    gtk_text_view_set_justification(GTK_TEXT_VIEW(display->priv->display_item), GTK_JUSTIFY_RIGHT);
-    g_signal_connect(display->priv->display_item, "populate-popup", G_CALLBACK(buffer_populate_popup_cb), display); // FIXME
-    g_signal_connect(display->priv->display_item, "button-release-event", G_CALLBACK(middle_click_paste_cb), display);
-    g_signal_connect(display->priv->display_item, "paste-clipboard", G_CALLBACK(paste_cb), display);
-    gtk_box_pack_start(GTK_BOX(display), display->priv->display_item, TRUE, TRUE, 0);
-
-    display->priv->display_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(display->priv->display_item));
-
-    gtk_widget_ensure_style(display->priv->display_item);
-    font_desc = pango_font_description_copy(gtk_widget_get_style(display->priv->display_item)->font_desc);
-    pango_font_description_set_size(font_desc, 16 * PANGO_SCALE);
-    gtk_widget_modify_font(display->priv->display_item, font_desc);
-    pango_font_description_free(font_desc);
-    gtk_widget_set_name(display->priv->display_item, "displayitem");
-    atk_object_set_role(gtk_widget_get_accessible(display->priv->display_item), ATK_ROLE_EDITBAR);
-  
-    info_view = gtk_text_view_new();
-    gtk_widget_set_can_focus(info_view, TRUE); // FIXME: This should be FALSE but it locks the cursor inside the main view for some reason
-    gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(info_view), FALSE); // FIXME: Just here so when incorrectly gets focus doesn't look editable
-    gtk_text_view_set_editable(GTK_TEXT_VIEW(info_view), FALSE);
-    gtk_text_view_set_justification(GTK_TEXT_VIEW(info_view), GTK_JUSTIFY_RIGHT);
-    gtk_text_view_set_right_margin(GTK_TEXT_VIEW(info_view), 6);
-    gtk_box_pack_start(GTK_BOX(display), info_view, FALSE, TRUE, 0);
-    display->priv->info_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(info_view));
-
-    gtk_widget_show(info_view);
-    gtk_widget_show(display->priv->display_item);
 }
diff --git a/src/math-display.h b/src/math-display.h
index 22bba61..548509a 100644
--- a/src/math-display.h
+++ b/src/math-display.h
@@ -39,39 +39,10 @@ typedef struct
 typedef struct
 {
     GtkVBoxClass parent_class;
-
-    void (*number_mode_changed)(MathDisplay *display);
 } MathDisplayClass;
 
-typedef enum {
-    NORMAL,
-    SUPERSCRIPT,
-    SUBSCRIPT
-} NumberMode;
-
 GType math_display_get_type();
 MathDisplay *math_display_new(MathEquation *equation);
-
 MathEquation *math_display_get_equation(MathDisplay *display);
 
-void math_display_set_base(MathDisplay *display, gint base);
-void math_display_set_number_mode(MathDisplay *display, NumberMode mode);
-gchar *math_display_get_text(MathDisplay *display);
-
-void math_display_copy(MathDisplay *display);
-void math_display_paste(MathDisplay *display);
-void math_display_store(MathDisplay *display, const gchar *name);
-void math_display_recall(MathDisplay *display, const gchar *name);
-void math_display_insert(MathDisplay *display, const gchar *text);
-void math_display_insert_digit(MathDisplay *display, guint digit);
-void math_display_insert_numeric_point(MathDisplay *display);
-void math_display_insert_subtract(MathDisplay *display);
-void math_display_insert_exponent(MathDisplay *display);
-void math_display_insert_character(MathDisplay *display, const gchar *character);
-void math_display_solve(MathDisplay *display);
-void math_display_factorize(MathDisplay *display);
-void math_display_clear(MathDisplay *display);
-void math_display_shift(MathDisplay *display, gint count);
-void math_display_toggle_bit(MathDisplay *display, guint bit);
-
 #endif /* MATH_DISPLAY_H */
diff --git a/src/math-equation.c b/src/math-equation.c
index 17d33d9..2f617ba 100644
--- a/src/math-equation.c
+++ b/src/math-equation.c
@@ -38,28 +38,84 @@
 enum {
     STATUS_CHANGED,
     BITFIELD_CHANGED,
-    DISPLAY_CHANGED,
+    NUMBER_MODE_CHANGED,
     LAST_SIGNAL
 };
 static guint signals[LAST_SIGNAL] = { 0, };
 
 #define MAX_DIGITS 200
+#define UNDO_HISTORY_LENGTH 16  /* Arithmetic mode undo history length */
+#define MAX_DISPLAY 512
+
+/* Expression mode state */
+typedef struct {
+    MPNumber ans;           /* Previously calculated answer */
+    char *expression;       /* Expression entered by user */
+    int ans_start, ans_end; /* Start and end characters for ans variable in expression */
+    int cursor;
+} MathEquationState;
+
+/* Circular list of Arithmetic Precedence Mode states*/
+typedef struct {
+  unsigned int begin;
+  unsigned int end;
+  unsigned int current;
+  MathEquationState e[UNDO_HISTORY_LENGTH];  /* Expression mode state */
+} MathEquationHistory;
 
 struct MathEquationPrivate
 {
-    gchar *status;
-    guint64 bitfield;
-    gboolean bitfield_enabled;
-    char localized[MAX_DIGITS];
-    gint cursor;
+    gchar *status;            /* ??? */
+
+    guint64 bitfield;           // FIXME: Move into ui-buttons.c
+    gboolean bitfield_enabled;  // FIXME: Move into ui-buttons.c
+    char localized[MAX_DIGITS]; // FIXME: Obsolete now a TextBuffer
+    gint cursor;                // FIXME: Obsolete now a TextBuffer
+
+    int show_tsep;            /* Set if the thousands separator should be shown. */
+    int show_zeroes;          /* Set if trailing zeroes should be shown. */
+    DisplayFormat format;     /* Number display mode. */
+    int accuracy;             /* Number of digits to show */
+    int word_size;            /* ??? */
+    MPAngleUnit angle_unit;   /* ??? */
+    NumberMode number_mode;   /* ??? */
+    gboolean can_super_minus; /* TRUE if entering minus can generate a superscript minus */
 
     const char *digits[16];   /* Localized digit values */
     const char *radix;        /* Locale specific radix string. */
     const char *tsep;         /* Locale specific thousands separator. */
     int tsep_count;           /* Number of digits between separator. */
+
+    char *last_text;          /* Last text entered */
+
+    MathEquationHistory h;    /* History of expression mode states */
+
+    GdkAtom clipboard_atom;   /* ??? */
+    GdkAtom primary_atom;     /* ??? */
+    char *shelf;              /* PUT selection shelf contents. */
 };
 
-G_DEFINE_TYPE (MathEquation, math_equation, G_TYPE_OBJECT);
+G_DEFINE_TYPE (MathEquation, math_equation, GTK_TYPE_TEXT_BUFFER);
+
+/* Available functions */
+//FIXME: Obsolete
+enum
+{
+    FN_TEXT,
+    FN_CALCULATE,
+    FN_CLEAR,
+    FN_BACKSPACE,
+    FN_DELETE,
+    FN_TOGGLE_BIT,
+    FN_SHIFT,
+    FN_FACTORIZE,
+    FN_STORE,
+    FN_RECALL,
+    FN_UNDO,
+    FN_REDO,
+    FN_PASTE,
+    FN_INSERT_CHARACTER
+};
 
 MathEquation *
 math_equation_new()
@@ -135,10 +191,232 @@ math_equation_get_cursor(MathEquation *equation)
 }
 
 
+void
+math_equation_set_number_mode(MathEquation *equation, NumberMode mode)
+{
+    if (equation->priv->number_mode == mode)
+        return;
+
+    equation->priv->can_super_minus = mode == SUPERSCRIPT;
+
+    equation->priv->number_mode = mode;
+    g_signal_emit(equation, signals[NUMBER_MODE_CHANGED], 0);
+}
+
+
+NumberMode
+math_equation_get_number_mode(MathEquation *equation)
+{
+    return equation->priv->number_mode;
+}
+
+
+static void display_do_function(MathEquation *equation, int function, gpointer arg, int cursor_start, int cursor_end);
+
+static void
+do_button(MathEquation *equation, int function, gpointer arg)
+{
+    GtkTextIter start, end;
+    gint cursor_start, cursor_end;
+  
+    /* Can't enter superscript minus after entering digits */
+    if (function == FN_TEXT && (strstr("�¹²³������", (char *)arg) != NULL || strcmp("�", (char *)arg) == 0))
+        equation->priv->can_super_minus = FALSE;
+
+    /* Disable super/subscript mode when finished entering */
+    if (function == FN_CALCULATE ||
+        function == FN_CLEAR ||
+        (function == FN_TEXT && strstr("â?»â?°Â¹Â²Â³â?´â?µâ?¶â?·â?¸â?¹â??â??â??â??â??â??â??â??â??â??", (char *)arg) == NULL)) {
+        math_equation_set_number_mode(equation, NORMAL);
+    }
+
+    if (gtk_text_buffer_get_selection_bounds(GTK_TEXT_BUFFER(equation), &start, &end)) {
+        cursor_start = gtk_text_iter_get_offset(&start);
+        cursor_end = gtk_text_iter_get_offset(&end);
+    }
+    else {
+        g_object_get(G_OBJECT(equation), "cursor-position", &cursor_start, NULL);
+        if (cursor_start == gtk_text_buffer_get_char_count(GTK_TEXT_BUFFER(equation)))
+            cursor_start = -1;
+        cursor_end = cursor_start;
+    }
+
+    /* Some keyboards don't have a '^' button so convert two multiplies to one '^' */
+    if (cursor_start == cursor_end &&
+        function == FN_TEXT && equation->priv->last_text != NULL &&
+        strcmp((char *)arg, "Ã?") == 0 && strcmp(equation->priv->last_text, "Ã?") == 0) {
+        do_button(equation, FN_BACKSPACE, NULL);
+        do_button(equation, FN_TEXT, "^");
+    }
+    else {
+        display_do_function(equation, function, arg, cursor_start, cursor_end);
+        if (function == FN_TEXT)
+            equation->priv->last_text = (char *)arg;
+        else
+            equation->priv->last_text = NULL;
+    }
+}
+
+
+void
+math_equation_copy(MathEquation *equation)
+{
+    gchar *string = NULL;
+    GtkTextIter start, end;
+
+    if (gtk_text_buffer_get_selection_bounds(GTK_TEXT_BUFFER(equation), &start, &end) == TRUE)
+        string = gtk_text_buffer_get_text(GTK_TEXT_BUFFER(equation), &start, &end, FALSE);
+    else
+        string = equation->priv->localized;
+
+    if (equation->priv->shelf != NULL)
+        g_free(equation->priv->shelf);
+    equation->priv->shelf = g_locale_from_utf8(string, strlen(string), NULL, NULL, NULL);
+    g_free(string);
+
+    gtk_clipboard_set_text(gtk_clipboard_get(equation->priv->clipboard_atom), equation->priv->shelf, -1);
+}
+
+
+static void
+on_paste(GtkClipboard *clipboard, const gchar *text, MathEquation *equation)
+{
+    if (text != NULL)
+        do_button(equation, FN_PASTE, (gpointer) text);
+}
+
+
+void
+math_equation_paste(MathEquation *equation)
+{
+    gtk_clipboard_request_text(gtk_clipboard_get(equation->priv->clipboard_atom),
+                               (GtkClipboardTextReceivedFunc)on_paste, equation);
+}
+
+
+void
+math_equation_store(MathEquation *equation, const gchar *name)
+{
+    do_button(equation, FN_STORE, (gpointer)name);
+}
+
+
+void
+math_equation_recall(MathEquation *equation, const gchar *name)
+{
+    do_button(equation, FN_RECALL, (gpointer)name);
+}
+
+
+void
+math_equation_insert(MathEquation *equation, const gchar *text)
+{
+    do_button(equation, FN_TEXT, (gpointer) text);
+}
+
+
+void
+math_equation_insert_digit(MathEquation *equation, unsigned int digit)
+{
+    static const char *subscript_digits[] = {"â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", NULL};
+    static const char *superscript_digits[] = {"�", "¹", "²", "³", "�", "�", "�", "�", "�", "�", NULL};
+
+    if (equation->priv->number_mode == NORMAL || digit >= 10)
+        math_equation_insert(equation, math_equation_get_digit_text(equation, digit));
+    else if (equation->priv->number_mode == SUPERSCRIPT)
+        math_equation_insert(equation, superscript_digits[digit]);
+    else if (equation->priv->number_mode == SUBSCRIPT)
+        math_equation_insert(equation, subscript_digits[digit]);
+}
+
+
+void
+math_equation_insert_numeric_point(MathEquation *equation)
+{
+    math_equation_insert(equation, math_equation_get_numeric_point_text(equation));
+}
+
+
+void
+math_equation_insert_exponent(MathEquation *equation)
+{
+    math_equation_insert(equation, "Ã?10");
+    math_equation_set_number_mode(equation, SUPERSCRIPT);
+}
+
+
+void
+math_equation_insert_character(MathEquation *equation, const char *character)
+{
+    do_button(equation, FN_INSERT_CHARACTER, (gpointer)character);
+}
+
+
+void
+math_equation_insert_subtract(MathEquation *equation)
+{
+    if (equation->priv->number_mode == SUPERSCRIPT && equation->priv->can_super_minus) {
+        math_equation_insert(equation, "â?»");
+        equation->priv->can_super_minus = FALSE;
+    }
+    else {
+        math_equation_insert(equation, "â??");
+        math_equation_set_number_mode(equation, NORMAL);
+    }
+}
+
+
+void
+math_equation_solve(MathEquation *equation)
+{
+    do_button(equation, FN_CALCULATE, NULL);
+}
+
+
+void
+math_equation_factorize(MathEquation *equation)
+{
+    do_button(equation, FN_FACTORIZE, NULL);
+}
+
+
+void math_equation_delete(MathEquation *equation)
+{
+    do_button(equation, FN_DELETE, NULL);  
+}
+
+
+void math_equation_backspace(MathEquation *equation)
+{
+    do_button(equation, FN_BACKSPACE, NULL);  
+}
+
+
+void
+math_equation_clear(MathEquation *equation)
+{
+    do_button(equation, FN_CLEAR, NULL);  
+}
+
+
+void
+math_equation_shift(MathEquation *equation, gint count)
+{
+    do_button(equation, FN_SHIFT, GINT_TO_POINTER(count));
+}
+
+
+void
+math_equation_toggle_bit(MathEquation *equation, guint bit)
+{
+    do_button(equation, FN_TOGGLE_BIT, GINT_TO_POINTER(bit));
+}
+
+
 static MathEquationState *
-get_state(MathEquation *display)
+get_state(MathEquation *equation)
 {
-    return &(display->h.e[display->h.current]);
+    return &(equation->priv->h.e[equation->priv->h.current]);
 }
 
 
@@ -148,7 +426,7 @@ get_state(MathEquation *display)
 
 /* Add in the thousand separators characters if required */
 static void
-localize_expression(MathEquation *display, char *dest, const char *src, int dest_length, int *cursor)
+localize_expression(MathEquation *equation, char *dest, const char *src, int dest_length, int *cursor)
 {
     GString *output;
     const char *c, *d;
@@ -177,9 +455,9 @@ localize_expression(MathEquation *display, char *dest, const char *src, int dest
             g_string_append_unichar(output, g_utf8_get_char(c));
 
             /* Insert separator after nth digit */
-            if (display->show_tsep && display->format == DEC &&
-                !after_radix && digit_count > 1 && digit_count % display->priv->tsep_count == 1) {
-                g_string_append(output, display->priv->tsep);
+            if (equation->priv->show_tsep && equation->priv->format == DEC &&
+                !after_radix && digit_count > 1 && digit_count % equation->priv->tsep_count == 1) {
+                g_string_append(output, equation->priv->tsep);
                 if (new_cursor > read_cursor) {
                     new_cursor++;
                 }
@@ -191,7 +469,7 @@ localize_expression(MathEquation *display, char *dest, const char *src, int dest
         else if (*c == '.') {
             digit_count = -1;
             after_radix = TRUE;
-            g_string_append(output, display->priv->radix);
+            g_string_append(output, equation->priv->radix);
             // FIXME: Handle cursor if radix is more than one character?
         }
         /* Reset when encountering other characters (e.g. '+') */
@@ -211,31 +489,112 @@ localize_expression(MathEquation *display, char *dest, const char *src, int dest
 }
 
 
-void
-display_clear(MathEquation *display)
+static MPNumber *
+display_get_answer(MathEquation *equation)
+{
+    return &get_state(equation)->ans;
+}
+
+
+static int
+display_get_cursor(MathEquation *equation)
+{
+    return get_state(equation)->cursor;
+}
+
+
+static gboolean
+display_is_result(MathEquation *equation)
 {
     MathEquationState *state;
 
-    state = get_state(display);
-    display_set_string(display, "", -1);
+    state = get_state(equation);
+    if (state->ans_start == 0 && state->ans_end == g_utf8_strlen(state->expression, -1))
+        return TRUE;
+
+    return FALSE;
+}
+
+
+static void
+display_make_text(MathEquation *equation, char *localized, int length, int *cursor)
+{
+    char *str;
+    MathEquationState *e;
+
+    e = get_state(equation);
+
+    /* Substitute answer register */
+    if (display_is_result(equation)) {
+        char temp[MAX_DIGITS];
+        display_make_number(equation, temp, MAX_DIGITS, &e->ans);
+        str = strdup(temp);
+    }
+    else
+        str = strdup(e->expression);
+
+    localize_expression(equation, localized, str, length, cursor);
+    free(str);
+}
+
+
+static void
+display_refresh(MathEquation *equation)
+{
+    GtkTextIter iter;
+
+    equation->priv->cursor = display_get_cursor(equation);
+    display_make_text(equation, equation->priv->localized, MAX_DIGITS, &equation->priv->cursor);
+    gtk_text_buffer_set_text(GTK_TEXT_BUFFER(equation), equation->priv->localized, -1);
+    if (equation->priv->cursor < 0)
+        gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(equation), &iter);
+    else
+        gtk_text_buffer_get_iter_at_offset(GTK_TEXT_BUFFER(equation), &iter, equation->priv->cursor);
+    gtk_text_buffer_place_cursor(GTK_TEXT_BUFFER(equation), &iter);
+}
+
+
+static void
+display_set_string(MathEquation *equation, const char *value, int cursor)
+{
+    MathEquationState *e;
+
+    if (value[0] == '\0')
+        cursor = -1;
+
+    e = get_state(equation);
+    free(e->expression);
+    e->expression = strdup(value);
+    e->cursor = cursor;
+
+    display_refresh(equation);
+}
+
+static void
+display_clear(MathEquation *equation)
+{
+    MathEquationState *state;
+
+    state = get_state(equation);
+    display_set_string(equation, "", -1);
     state->ans_start = -1;
     state->ans_end = -1;
 }
 
 
 static const char *
-get_text(MathEquation *display)
+get_text(MathEquation *equation)
 {
-    return get_state(display)->expression;
+    return get_state(equation)->expression;
 }
 
 
 static char *
-get_expression(MathEquation *display)
+get_expression(MathEquation *equation)
 {
     MathEquationState *state;
 
-    state = get_state(display);
+    state = get_state(equation);
     if(state->ans_start >= 0)
         return g_strdup_printf("%.*sans%s", state->ans_start, state->expression, g_utf8_offset_to_pointer(state->expression, state->ans_end));
     else
@@ -243,12 +602,12 @@ get_expression(MathEquation *display)
 }
 
 
-gboolean
-display_get_integer(MathEquation *display, gint64 *value)
+static gboolean
+display_get_integer(MathEquation *equation, gint64 *value)
 {
     MPNumber t, min, max;
 
-    if (!display_is_usable_number(display, &t))
+    if (!display_is_usable_number(equation, &t))
         return FALSE;
 
     mp_set_from_integer(G_MININT64, &min);
@@ -261,12 +620,12 @@ display_get_integer(MathEquation *display, gint64 *value)
 }
 
 
-gboolean
-display_get_unsigned_integer(MathEquation *display, guint64 *value)
+static gboolean
+display_get_unsigned_integer(MathEquation *equation, guint64 *value)
 {
     MPNumber t, max;
 
-    if (!display_is_usable_number(display, &t))
+    if (!display_is_usable_number(equation, &t))
         return FALSE;
   
     mp_set_from_unsigned_integer(G_MAXUINT64, &max);
@@ -279,129 +638,60 @@ display_get_unsigned_integer(MathEquation *display, guint64 *value)
 }
 
 
-MPNumber *
-display_get_answer(MathEquation *display)
-{
-    return &get_state(display)->ans;
-}
-
-
-int
-display_get_cursor(MathEquation *display)
-{
-    return get_state(display)->cursor;
-}
-
-
 // FIXME: Looses accuracy
 void
-display_set_number(MathEquation *display, const MPNumber *x)
+display_set_number(MathEquation *equation, const MPNumber *x)
 {
     char text[MAX_DISPLAY];
     int enabled;
     guint64 bit_value;
 
-    display_make_number(display, text, MAX_DISPLAY, x);
-    display_set_string(display, text, -1);
+    display_make_number(equation, text, MAX_DISPLAY, x);
+    display_set_string(equation, text, -1);
 
-    enabled = display_get_unsigned_integer(display, &bit_value);
-    math_equation_set_bitfield(display, enabled, bit_value);
+    enabled = display_get_unsigned_integer(equation, &bit_value);
+    math_equation_set_bitfield(equation, enabled, bit_value);
 }
 
 
 void
-display_set_answer(MathEquation *display)
+display_set_answer(MathEquation *equation)
 {
     MathEquationState *state;
     char text[MAX_DISPLAY];
 
-    state = get_state(display);
-    display_make_number(display, text, MAX_DISPLAY, &state->ans);
-    display_set_string(display, text, -1);
+    state = get_state(equation);
+    display_make_number(equation, text, MAX_DISPLAY, &state->ans);
+    display_set_string(equation, text, -1);
     state->ans_start = 0;
     state->ans_end = g_utf8_strlen(text, -1);
 }
 
 
 static void
-display_make_text(MathEquation *display, char *localized, int length, int *cursor)
+display_set_cursor(MathEquation *equation, int cursor)
 {
-    char *str;
     MathEquationState *e;
 
-    e = get_state(display);
-
-    /* Substitute answer register */
-    if (display_is_result(display)) {
-        char temp[MAX_DIGITS];
-        display_make_number(display, temp, MAX_DIGITS, &e->ans);
-        str = strdup(temp);
-    }
-    else
-        str = strdup(e->expression);
-
-    localize_expression(display, localized, str, length, cursor);
-    free(str);
-}
-
-
-static void
-display_refresh(MathEquation *equation)
-{
-    equation->priv->cursor = display_get_cursor(equation);
-    display_make_text(equation, equation->priv->localized, MAX_DIGITS, &equation->priv->cursor);
-    g_signal_emit(equation, signals[DISPLAY_CHANGED], 0);
-}
-
-
-void
-display_set_string(MathEquation *display, const char *value, int cursor)
-{
-    MathEquationState *e;
-
-    if (value[0] == '\0')
-        cursor = -1;
-
-    e = get_state(display);
-    free(e->expression);
-    e->expression = strdup(value);
+    e = get_state(equation);
     e->cursor = cursor;
-
-    display_refresh(display);
+    display_refresh(equation);
 }
 
 
-void
-display_set_cursor(MathEquation *display, int cursor)
-{
-    MathEquationState *e;
-
-    e = get_state(display);
-    e->cursor = cursor;
-    display_refresh(display);
-}
-
-
-void
-display_set_error(MathEquation *display, const char *message)
-{
-    math_equation_set_status(display, message);
-}
-
-
-void
-display_convert(MathEquation *display, DisplayFormat format)
+static void
+display_convert(MathEquation *equation, DisplayFormat format)
 {
     DisplayFormat old_format;
 
-    if (!display_is_result (display))
+    if (!display_is_result (equation))
         return;
 
     /* FIXME: A bit hacky... */
-    old_format = display->format;
-    display->format = format;
-    display_set_answer(display);
-    display->format = old_format;
+    old_format = equation->priv->format;
+    equation->priv->format = format;
+    display_set_answer(equation);
+    equation->priv->format = old_format;
 }
 
 
@@ -413,94 +703,94 @@ copy_state(MathEquationState *dst, MathEquationState *src)
 }
 
 
-void
-display_clear_stack(MathEquation *display)
+static void
+display_clear_stack(MathEquation *equation)
 {
-    int i = display->h.begin;
-    while (i != display->h.end) {
-        if (i != display->h.current) {
-            free(display->h.e[i].expression);
-            display->h.e[i].expression = NULL;
+    int i = equation->priv->h.begin;
+    while (i != equation->priv->h.end) {
+        if (i != equation->priv->h.current) {
+            free(equation->priv->h.e[i].expression);
+            equation->priv->h.e[i].expression = NULL;
         }
         i = ((i + 1) % UNDO_HISTORY_LENGTH);
     }
-    display->h.begin = display->h.end = display->h.current;
+    equation->priv->h.begin = equation->priv->h.end = equation->priv->h.current;
 }
 
 
-void
-display_push(MathEquation *display)
+static void
+display_push(MathEquation *equation)
 {
     int c;
 
-    if (display->h.current != display->h.end) {
-        int i = display->h.current;
+    if (equation->priv->h.current != equation->priv->h.end) {
+        int i = equation->priv->h.current;
 
         do {
             i = ((i + 1) % UNDO_HISTORY_LENGTH);
-            free(display->h.e[i].expression);
-            display->h.e[i].expression = strdup("ans"); // FIXME: Use actual number
-            display->h.e[i].ans_start = -1;
-            display->h.e[i].ans_end = -1;
-        } while (i != display->h.end);
+            free(equation->priv->h.e[i].expression);
+            equation->priv->h.e[i].expression = strdup("ans"); // FIXME: Use actual number
+            equation->priv->h.e[i].ans_start = -1;
+            equation->priv->h.e[i].ans_end = -1;
+        } while (i != equation->priv->h.end);
     }
 
-    display->h.end = display->h.current;
+    equation->priv->h.end = equation->priv->h.current;
 
-    c = display->h.current;
-    display->h.end = display->h.current = ((display->h.current + 1) % UNDO_HISTORY_LENGTH);
-    if (display->h.current == display->h.begin) {
-        free(display->h.e[display->h.begin].expression);
-        display->h.e[display->h.begin].expression = NULL;
-        display->h.begin = ((display->h.begin + 1) % UNDO_HISTORY_LENGTH);
+    c = equation->priv->h.current;
+    equation->priv->h.end = equation->priv->h.current = ((equation->priv->h.current + 1) % UNDO_HISTORY_LENGTH);
+    if (equation->priv->h.current == equation->priv->h.begin) {
+        free(equation->priv->h.e[equation->priv->h.begin].expression);
+        equation->priv->h.e[equation->priv->h.begin].expression = NULL;
+        equation->priv->h.begin = ((equation->priv->h.begin + 1) % UNDO_HISTORY_LENGTH);
     }
 
-    copy_state(&(display->h.e[display->h.current]), &(display->h.e[c]));
+    copy_state(&(equation->priv->h.e[equation->priv->h.current]), &(equation->priv->h.e[c]));
 }
 
 
-void
-display_pop(MathEquation *display)
+static void
+display_pop(MathEquation *equation)
 {
-    if (display->h.current != display->h.begin) {
-        display->h.current = ((display->h.current - 1) % UNDO_HISTORY_LENGTH);
-        math_equation_set_status(display, "");
+    if (equation->priv->h.current != equation->priv->h.begin) {
+        equation->priv->h.current = ((equation->priv->h.current - 1) % UNDO_HISTORY_LENGTH);
+        math_equation_set_status(equation, "");
     } else {
-        math_equation_set_status(display, _("No undo history"));
+        math_equation_set_status(equation, _("No undo history"));
     }
 
-    display_refresh(display);
+    display_refresh(equation);
 }
 
 
-void
-display_unpop(MathEquation *display)
+static void
+display_unpop(MathEquation *equation)
 {
-    if (display->h.current != display->h.end) {
-        display->h.current = ((display->h.current + 1) % UNDO_HISTORY_LENGTH);
-        math_equation_set_status(display, "");
+    if (equation->priv->h.current != equation->priv->h.end) {
+        equation->priv->h.current = ((equation->priv->h.current + 1) % UNDO_HISTORY_LENGTH);
+        math_equation_set_status(equation, "");
     } else {
-        math_equation_set_status(display, _("No redo steps"));
+        math_equation_set_status(equation, _("No redo steps"));
     }
-    get_state(display)->cursor = -1;
-    display_refresh(display);
+    get_state(equation)->cursor = -1;
+    display_refresh(equation);
 }
 
 
-gboolean
-display_is_undo_step(MathEquation *display)
+static gboolean
+display_is_undo_step(MathEquation *equation)
 {
-    return(display->h.current != display->h.begin);
+    return(equation->priv->h.current != equation->priv->h.begin);
 }
 
 
-void
-display_insert(MathEquation *display, int cursor_start, int cursor_end, const char *text)
+static void
+display_insert(MathEquation *equation, int cursor_start, int cursor_end, const char *text)
 {
     MathEquationState *state;   
     char buf[MAX_DISPLAY];
 
-    state = get_state(display);
+    state = get_state(equation);
 
     /* If inside ans variable then modify number */
     if (state->ans_start >= 0 && cursor_start >= state->ans_start && cursor_start <= state->ans_end) {
@@ -509,8 +799,8 @@ display_insert(MathEquation *display, int cursor_start, int cursor_end, const ch
     }
 
     if (cursor_start < 0) {
-        snprintf(buf, MAX_DISPLAY, "%s%s", get_text(display), text);
-        display_set_string(display, buf, -1);
+        snprintf(buf, MAX_DISPLAY, "%s%s", get_text(equation), text);
+        display_set_string(equation, buf, -1);
     } else {
         GString *new_text;
         const char *c;
@@ -525,7 +815,7 @@ display_insert(MathEquation *display, int cursor_start, int cursor_end, const ch
         }
 
         cursor = 0;
-        for (c = display->priv->localized; *c; c = g_utf8_next_char(c), cursor++) {
+        for (c = equation->priv->localized; *c; c = g_utf8_next_char(c), cursor++) {
             gboolean use = TRUE;
 
             /* Ignore selected part */
@@ -533,7 +823,7 @@ display_insert(MathEquation *display, int cursor_start, int cursor_end, const ch
                 use = FALSE;
 
             /* Ignore thousands separators (if one exists) */
-            if (display->priv->tsep[0] != '\0' && strncmp(c, display->priv->tsep, strlen(display->priv->tsep)) == 0)
+            if (equation->priv->tsep[0] != '\0' && strncmp(c, equation->priv->tsep, strlen(equation->priv->tsep)) == 0)
                 use = FALSE;
 
             /* Copy existing text */
@@ -549,112 +839,99 @@ display_insert(MathEquation *display, int cursor_start, int cursor_end, const ch
                 new_cursor += g_utf8_strlen(text, -1);
             }
         }
-        display_set_string(display, new_text->str, new_cursor);
+        display_set_string(equation, new_text->str, new_cursor);
         g_string_free(new_text, TRUE);
     }
 
 }
 
 
-void
-display_insert_number(MathEquation *display, int cursor_start, int cursor_end, const MPNumber *value)
+static void
+display_insert_number(MathEquation *equation, int cursor_start, int cursor_end, const MPNumber *value)
 {
     char text[MAX_DISPLAY];
-    display_make_number(display, text, MAX_DISPLAY, value);
-    display_insert(display, cursor_start, cursor_end, text);
+    display_make_number(equation, text, MAX_DISPLAY, value);
+    display_insert(equation, cursor_start, cursor_end, text);
 }
 
 
-void
-display_backspace(MathEquation *display, int cursor_start, int cursor_end)
+static gboolean
+display_is_empty(MathEquation *equation)
+{
+    return strcmp(get_text(equation), "") == 0;
+}
+
+
+static void
+display_backspace(MathEquation *equation, int cursor_start, int cursor_end)
 {
     int cursor;
 
     /* Can't delete empty display */
-    if (display_is_empty(display))
+    if (display_is_empty(equation))
         return;
 
-    cursor = display_get_cursor(display);
+    cursor = display_get_cursor(equation);
 
     /* If cursor is at end of the line then delete the last character preserving accuracy */
     if (cursor_start < 0) {
         int len;
-        len = g_utf8_strlen(display->priv->localized, -1);
-        display_insert(display, len - 1, len, "");
+        len = g_utf8_strlen(equation->priv->localized, -1);
+        display_insert(equation, len - 1, len, "");
     } else if (cursor_start != cursor_end) {
-        display_insert(display, cursor_start, cursor_end, "");
+        display_insert(equation, cursor_start, cursor_end, "");
     } else if (cursor_start > 0) {
-        display_insert(display, cursor_start - 1, cursor_start, "");
+        display_insert(equation, cursor_start - 1, cursor_start, "");
     }
 
 }
 
-void
-display_delete(MathEquation *display, int cursor_start, int cursor_end)
+static void
+display_delete(MathEquation *equation, int cursor_start, int cursor_end)
 {
     /* Delete selected block */
     if (cursor_start != cursor_end)
-        display_insert(display, cursor_start, cursor_end, "");
+        display_insert(equation, cursor_start, cursor_end, "");
     else if (cursor_start >= 0)
-        display_insert(display, cursor_start, cursor_start + 1, "");
+        display_insert(equation, cursor_start, cursor_start + 1, "");
 }
 
 
 gboolean
-display_is_empty(MathEquation *display)
+display_is_usable_number(MathEquation *equation, MPNumber *z)
 {
-    return strcmp(get_text(display), "") == 0;
-}
-
-
-gboolean
-display_is_result(MathEquation *display)
-{
-    MathEquationState *state;
-
-    state = get_state(display);
-    if (state->ans_start == 0 && state->ans_end == g_utf8_strlen(state->expression, -1))
-        return TRUE;
-
-    return FALSE;
-}
-
-
-gboolean
-display_is_usable_number(MathEquation *display, MPNumber *z)
-{
-    if (display_is_empty(display)) {
+    if (display_is_empty(equation)) {
         mp_set_from_integer(0, z);
         return TRUE;
-    } else if (display_is_result(display)) {
-        mp_set_from_mp(display_get_answer(display), z);
+    } else if (display_is_result(equation)) {
+        mp_set_from_mp(display_get_answer(equation), z);
         return TRUE;
     } else {
-        return mp_set_from_string(get_text(display), z) == 0;
+        return mp_set_from_string(get_text(equation), z) == 0;
     }
 }
 
 
-gboolean
-display_is_number_with_base(MathEquation *display)
+static gboolean
+display_is_number_with_base(MathEquation *equation)
 {
     MPNumber t;
     const char *text;
     const char *sub_digits[] = { "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", NULL };
     int i;
 
-    if (display_is_empty(display))
+    if (display_is_empty(equation))
         return FALSE;
 
-    if (display_is_result(display))
-        return (display->format == BIN || display->format == OCT || display->format == HEX);
+    if (display_is_result(equation))
+        return (equation->priv->format == BIN || equation->priv->format == OCT || equation->priv->format == HEX);
 
     /* See if it has a subscript suffix */
-    text = get_text(display);
+    text = get_text(equation);
     text += strlen (text);
     for (i = 0; sub_digits[i] != NULL; i++) {
         if (strcmp (text - strlen (sub_digits[i]), sub_digits[i]) == 0)
-            return mp_set_from_string(get_text(display), &t) == 0;
+            return mp_set_from_string(get_text(equation), &t) == 0;
     }
 
     return FALSE;
@@ -662,58 +939,86 @@ display_is_number_with_base(MathEquation *display)
 
 
 void
-display_set_accuracy(MathEquation *display, int accuracy)
+math_equation_set_accuracy(MathEquation *equation, int accuracy)
+{
+    equation->priv->accuracy = accuracy;
+    get_state(equation)->cursor = -1;
+    display_refresh(equation);
+}
+
+
+void
+math_equation_set_show_thousands_separator(MathEquation *equation, gboolean visible)
 {
-    display->accuracy = accuracy;
-    get_state(display)->cursor = -1;
-    display_refresh(display);
+    equation->priv->show_tsep = visible;
+    display_set_cursor(equation, -1);
+    display_refresh(equation);
 }
 
 
 void
-display_set_show_thousands_separator(MathEquation *display, gboolean visible)
+math_equation_set_show_trailing_zeroes(MathEquation *equation, gboolean visible)
 {
-    display->show_tsep = visible;
-    display_set_cursor(display, -1);
-    display_refresh(display);
+    equation->priv->show_zeroes = visible;
+    get_state(equation)->cursor = -1;
+    display_refresh(equation);
 }
 
 
 void
-display_set_show_trailing_zeroes(MathEquation *display, gboolean visible)
+math_equation_set_format(MathEquation *equation, DisplayFormat format)
 {
-    display->show_zeroes = visible;
-    get_state(display)->cursor = -1;
-    display_refresh(display);
+    equation->priv->format = format;
+    get_state(equation)->cursor = -1;
+    display_refresh(equation);
 }
 
 
 void
-display_set_format(MathEquation *display, DisplayFormat format)
+math_equation_set_word_size(MathEquation *equation, int word_size)
 {
-    display->format = format;
-    get_state(display)->cursor = -1;
-    display_refresh(display);
+    equation->priv->word_size = word_size;
 }
 
 
 void
-display_set_word_size(MathEquation *display, int word_size)
+math_equation_set_angle_unit(MathEquation *equation, MPAngleUnit angle_unit)
 {
-    display->word_size = word_size;
+    equation->priv->angle_unit = angle_unit;
 }
 
 
 void
-display_set_angle_unit(MathEquation *display, MPAngleUnit angle_unit)
+math_equation_set_base(MathEquation *equation, gint base)
 {
-    display->angle_unit = angle_unit;
+    /* If has a number already in a base, then solve and convert it */
+    if (!display_is_result(equation) && display_is_number_with_base(equation))
+        math_equation_solve(equation);
+
+    if (display_is_result(equation)) {
+        if (base == 2)
+            display_convert(equation, BIN);
+        else if (base == 8)
+            display_convert(equation, OCT);
+        else if (base == 16)
+            display_convert(equation, HEX);
+        else
+            display_convert(equation, DEC);
+    }
+    else {
+        if (base == 2)
+            math_equation_insert(equation, "â??");
+        else if (base == 8)
+            math_equation_insert(equation, "â??");
+        else if (base == 16)
+            math_equation_insert(equation, "â??â??");
+    }
 }
 
 
 /* Convert engineering or scientific number in the given base. */
 static void
-make_eng_sci(MathEquation *display, char *target, int target_len, const MPNumber *x, int base_)
+make_eng_sci(MathEquation *equation, char *target, int target_len, const MPNumber *x, int base_)
 {
     char fixed[MAX_DIGITS], *c;
     MPNumber t, z, base, base3, base10, base10inv, mantissa;
@@ -723,7 +1028,7 @@ make_eng_sci(MathEquation *display, char *target, int target_len, const MPNumber
 
     string = g_string_sized_new(target_len);
 
-    eng = display->format == ENG;
+    eng = equation->priv->format == ENG;
 
     mp_abs(x, &z);
     if (mp_is_negative(x))
@@ -760,7 +1065,7 @@ make_eng_sci(MathEquation *display, char *target, int target_len, const MPNumber
         }
     }
 
-    mp_cast_to_string(&mantissa, base_, display->accuracy, !display->show_zeroes, fixed, MAX_DIGITS);
+    mp_cast_to_string(&mantissa, base_, equation->priv->accuracy, !equation->priv->show_zeroes, fixed, MAX_DIGITS);
     g_string_append(string, fixed);
     g_string_append_printf(string, "Ã?10");
     if (exponent < 0) {
@@ -778,26 +1083,26 @@ make_eng_sci(MathEquation *display, char *target, int target_len, const MPNumber
 
 /* Convert MP number to character string. */
 void
-display_make_number(MathEquation *display, char *target, int target_len, const MPNumber *x)
+display_make_number(MathEquation *equation, char *target, int target_len, const MPNumber *x)
 {
-    switch(display->format) {
+    switch(equation->priv->format) {
     case DEC:
-        mp_cast_to_string(x, 10, display->accuracy, !display->show_zeroes, target, target_len);
+        mp_cast_to_string(x, 10, equation->priv->accuracy, !equation->priv->show_zeroes, target, target_len);
         break;
     case BIN:
-        mp_cast_to_string(x, 2, display->accuracy, !display->show_zeroes, target, target_len);
+        mp_cast_to_string(x, 2, equation->priv->accuracy, !equation->priv->show_zeroes, target, target_len);
         break;
     case OCT:
-        mp_cast_to_string(x, 8, display->accuracy, !display->show_zeroes, target, target_len);
+        mp_cast_to_string(x, 8, equation->priv->accuracy, !equation->priv->show_zeroes, target, target_len);
         break;
     case HEX:
-        mp_cast_to_string(x, 16, display->accuracy, !display->show_zeroes, target, target_len);
+        mp_cast_to_string(x, 16, equation->priv->accuracy, !equation->priv->show_zeroes, target, target_len);
         break;
     case SCI:
-        make_eng_sci(display, target, target_len, x, 10);
+        make_eng_sci(equation, target, target_len, x, 10);
         break;
     case ENG:
-        make_eng_sci(display, target, target_len, x, 10);
+        make_eng_sci(equation, target, target_len, x, 10);
         break;
     }
 }
@@ -828,7 +1133,7 @@ get_variable(const char *name, MPNumber *z, void *data)
 {
     char *c, *lower_name;
     int result = 1;
-    MathEquation *display = data;
+    MathEquation *equation = data;
     MPNumber *t;
 
     lower_name = strdup(name);
@@ -838,7 +1143,7 @@ get_variable(const char *name, MPNumber *z, void *data)
     if (strcmp(lower_name, "rand") == 0)
         mp_set_from_random(z);
     else if (strcmp(lower_name, "ans") == 0)
-        mp_set_from_mp(display_get_answer(display), z);
+        mp_set_from_mp(display_get_answer(equation), z);
     else {
         t = register_get_value(name);
         if (t)
@@ -879,25 +1184,25 @@ convert(const MPNumber *x, const char *x_units, const char *z_units, MPNumber *z
 
 
 static int
-parse(MathEquation *display, const char *text, MPNumber *z, char **error_token)
+parse(MathEquation *equation, const char *text, MPNumber *z, char **error_token)
 {
     MPEquationOptions options;
 
     memset(&options, 0, sizeof(options));
-    options.wordlen = display->word_size;
-    options.angle_units = display->angle_unit;
+    options.wordlen = equation->priv->word_size;
+    options.angle_units = equation->priv->angle_unit;
     options.variable_is_defined = variable_is_defined;
     options.get_variable = get_variable;
     options.set_variable = set_variable;
     options.convert = convert;
-    options.callback_data = display;
+    options.callback_data = equation;
 
     return mp_equation_parse(text, &options, z, error_token);
 }
 
 
 static void
-do_paste(MathEquation *display, int cursor_start, int cursor_end, const char *text)
+do_paste(MathEquation *equation, int cursor_start, int cursor_end, const char *text)
 {
     const char *input;
     char c, *output, *clean_text;
@@ -911,14 +1216,14 @@ do_paste(MathEquation *display, int cursor_start, int cursor_end, const char *te
         /* If the clipboard buffer contains any occurances of the "thousands
          * separator", remove them.
          */
-        if (display->priv->tsep[0] != '\0' && strncmp(input, display->priv->tsep, strlen(display->priv->tsep)) == 0) {
-            input += strlen(display->priv->tsep) - 1;
+        if (equation->priv->tsep[0] != '\0' && strncmp(input, equation->priv->tsep, strlen(equation->priv->tsep)) == 0) {
+            input += strlen(equation->priv->tsep) - 1;
             continue;
         }
 
         /* Replace radix with "." */
-        else if (strncmp(input, display->priv->radix, strlen(display->priv->radix)) == 0) {
-            input += strlen(display->priv->radix) - 1;
+        else if (strncmp(input, equation->priv->radix, strlen(equation->priv->radix)) == 0) {
+            input += strlen(equation->priv->radix) - 1;
             c = '.';
         }
 
@@ -956,12 +1261,12 @@ do_paste(MathEquation *display, int cursor_start, int cursor_end, const char *te
     }
     *output++ = '\0';
 
-    display_insert(display, cursor_start, cursor_end, clean_text);
+    display_insert(equation, cursor_start, cursor_end, clean_text);
 }
 
 
 static void
-do_insert_character(MathEquation *display, const unsigned char *text)
+do_insert_character(MathEquation *equation, const unsigned char *text)
 {
     MPNumber value;
     int i = 0;
@@ -975,24 +1280,24 @@ do_insert_character(MathEquation *display, const unsigned char *text)
             break;
         }
     }
-    display_set_number(display, &value);
+    display_set_number(equation, &value);
 }
 
 
 /* Perform bitwise shift on display value. */
 static void
-do_shift(MathEquation *display, int count)
+do_shift(MathEquation *equation, int count)
 {
     MPNumber z;
 
-    if (!display_is_usable_number(display, &z)) {
+    if (!display_is_usable_number(equation, &z)) {
         /* Translators: This message is displayed in the status bar when a bit
            shift operation is performed and the display does not contain a number */
-        math_equation_set_status(display, _("No sane value to bitwise shift"));
+        math_equation_set_status(equation, _("No sane value to bitwise shift"));
     }
     else {
-        mp_shift(&z, count, display_get_answer(display));
-        display_set_answer(display);
+        mp_shift(&z, count, display_get_answer(equation));
+        display_set_answer(equation);
     }
 }
 
@@ -1025,19 +1330,19 @@ do_factorize(MathEquation *equation)
 
 
 static void
-do_sto(MathEquation *display, const char *name)
+do_sto(MathEquation *equation, const char *name)
 {
     MPNumber t;
 
-    if (!display_is_usable_number(display, &t))
-        math_equation_set_status(display, _("No sane value to store"));
+    if (!display_is_usable_number(equation, &t))
+        math_equation_set_status(equation, _("No sane value to store"));
     else
         register_set_value(name, &t);
 }
 
 
-void
-display_do_function(MathEquation *display, int function, gpointer arg, int cursor_start, int cursor_end)
+static void
+display_do_function(MathEquation *equation, int function, gpointer arg, int cursor_start, int cursor_end)
 {
     MPNumber *ans;
     int enabled;
@@ -1045,63 +1350,63 @@ display_do_function(MathEquation *display, int function, gpointer arg, int curso
 
     switch (function) {
         case FN_UNDO:
-            display_pop(display);
+            display_pop(equation);
             return;
 
         case FN_REDO:
-            display_unpop(display);
+            display_unpop(equation);
             return;
 
         default:
             break;
     }
 
-    display_push(display);
+    display_push(equation);
 
-    display_set_cursor(display, cursor_start);
-    ans = display_get_answer(display);
+    display_set_cursor(equation, cursor_start);
+    ans = display_get_answer(equation);
 
-    math_equation_set_status(display, "");
+    math_equation_set_status(equation, "");
 
     switch (function) {
         case FN_CLEAR:
-            display_clear(display);
+            display_clear(equation);
             break;
 
         case FN_SHIFT:
-            do_shift(display, GPOINTER_TO_INT (arg));
+            do_shift(equation, GPOINTER_TO_INT (arg));
             break;
 
         case FN_FACTORIZE:
-            do_factorize(display);
+            do_factorize(equation);
             break;
 
         case FN_PASTE:
-            do_paste(display, cursor_start, cursor_end, (const char *)arg);
+            do_paste(equation, cursor_start, cursor_end, (const char *)arg);
             return;
 
         case FN_INSERT_CHARACTER:
-            do_insert_character(display, (const unsigned char *)arg);
+            do_insert_character(equation, (const unsigned char *)arg);
             return;
 
         case FN_STORE:
-            do_sto(display, (const char *)arg);
+            do_sto(equation, (const char *)arg);
             return;
 
         case FN_RECALL:
-            display_insert(display, cursor_start, cursor_end, (const char *)arg);
+            display_insert(equation, cursor_start, cursor_end, (const char *)arg);
             break;
 
         case FN_BACKSPACE:
-            display_backspace(display, cursor_start, cursor_end);
+            display_backspace(equation, cursor_start, cursor_end);
             break;
 
         case FN_DELETE:
-            display_delete(display, cursor_start, cursor_end);
+            display_delete(equation, cursor_start, cursor_end);
             break;
 
         case FN_TOGGLE_BIT:
-            if (display_get_unsigned_integer(display, &bit_value)) {
+            if (display_get_unsigned_integer(equation, &bit_value)) {
                 char buf[MAX_DISPLAY];
                 MPNumber MP;
 
@@ -1110,7 +1415,7 @@ display_do_function(MathEquation *display, int function, gpointer arg, int curso
                 /* FIXME: Convert to string since we don't support setting MP numbers from 64 bit integers */
                 snprintf(buf, MAX_DISPLAY, "%" G_GUINT64_FORMAT, bit_value);
                 mp_set_from_string(buf, &MP);
-                display_set_number(display, &MP);
+                display_set_number(equation, &MP);
             }
             break;
 
@@ -1119,14 +1424,14 @@ display_do_function(MathEquation *display, int function, gpointer arg, int curso
              * this result */
             /* TODO: Work out why two undo steps are required and why
              * the cursor must be taken from the first undo */
-            if (display_is_result(display)) {
-                display_pop(display);
-                if (display_is_undo_step(display)) {
-                    display_pop(display);
+            if (display_is_result(equation)) {
+                display_pop(equation);
+                if (display_is_undo_step(equation)) {
+                    display_pop(equation);
                 }
 
             /* Do nothing */
-            } else if (display_is_empty(display)) {
+            } else if (display_is_empty(equation)) {
                 ;
 
             /* Solve the equation */
@@ -1136,8 +1441,8 @@ display_do_function(MathEquation *display, int function, gpointer arg, int curso
                 const char *message = NULL;
                 char *text, *error_token;
 
-                text = get_expression (display);
-                result = parse(display,
+                text = get_expression (equation);
+                result = parse(equation,
                                text,
                                &z,
                                &error_token);
@@ -1146,7 +1451,7 @@ display_do_function(MathEquation *display, int function, gpointer arg, int curso
                 switch (result) {
                     case PARSER_ERR_NONE:
                         mp_set_from_mp(&z, ans);
-                        display_set_answer(display);
+                        display_set_answer(equation);
                         break;
 
                     case PARSER_ERR_OVERFLOW:
@@ -1181,21 +1486,21 @@ display_do_function(MathEquation *display, int function, gpointer arg, int curso
                         break;
                 }
                 if (message)
-                    math_equation_set_status(display, message);
+                    math_equation_set_status(equation, message);
             }
             break;
 
         case FN_TEXT:
             /* Start new equation when entering digits after existing result */
-            if(display_is_result(display) && g_unichar_isdigit(g_utf8_get_char((char*)arg)))
-                display_clear(display);
+            if(display_is_result(equation) && g_unichar_isdigit(g_utf8_get_char((char*)arg)))
+                display_clear(equation);
 
-            display_insert(display, cursor_start, cursor_end, (const char *)arg);
+            display_insert(equation, cursor_start, cursor_end, (const char *)arg);
             break;
     }
 
-    enabled = display_get_unsigned_integer(display, &bit_value);
-    math_equation_set_bitfield(display, enabled, bit_value);
+    enabled = display_get_unsigned_integer(equation, &bit_value);
+    math_equation_set_bitfield(equation, enabled, bit_value);
 }
 
 
@@ -1222,11 +1527,11 @@ math_equation_class_init (MathEquationClass *klass)
                       NULL, NULL,
                       g_cclosure_marshal_VOID__VOID,
                       G_TYPE_NONE, 0);
-    signals[DISPLAY_CHANGED] =
-        g_signal_new ("display-changed",
+    signals[NUMBER_MODE_CHANGED] =
+        g_signal_new ("number-mode-changed",
                       G_TYPE_FROM_CLASS (klass),
                       G_SIGNAL_RUN_LAST,
-                      G_STRUCT_OFFSET (MathEquationClass, display_changed),
+                      G_STRUCT_OFFSET (MathEquationClass, number_mode_changed),
                       NULL, NULL,
                       g_cclosure_marshal_VOID__VOID,
                       G_TYPE_NONE, 0);
@@ -1260,17 +1565,20 @@ math_equation_init(MathEquation *equation)
     equation->priv->tsep = get_tsep();     /* Locale specific thousands separator. */
     equation->priv->tsep_count = get_tsep_count();
 
+    equation->priv->primary_atom = gdk_atom_intern("PRIMARY", FALSE);
+    equation->priv->clipboard_atom = gdk_atom_intern("CLIPBOARD", FALSE);
+
     equation->priv->status = g_strdup("");
-    equation->show_zeroes = FALSE;
-    equation->show_tsep = FALSE;
-    equation->format = DEC;
-    equation->accuracy = 9;
-    equation->word_size = 32;
-    equation->angle_unit = MP_DEGREES;
+    equation->priv->show_zeroes = FALSE;
+    equation->priv->show_tsep = FALSE;
+    equation->priv->format = DEC;
+    equation->priv->accuracy = 9;
+    equation->priv->word_size = 32;
+    equation->priv->angle_unit = MP_DEGREES;
 
     for (i = 0; i < UNDO_HISTORY_LENGTH; i++) {
-        equation->h.e[i].expression = strdup("");
-        equation->h.e[i].ans_start = -1;
-        equation->h.e[i].ans_end = -1;
+        equation->priv->h.e[i].expression = strdup("");
+        equation->priv->h.e[i].ans_start = -1;
+        equation->priv->h.e[i].ans_end = -1;
     }
 }
diff --git a/src/math-equation.h b/src/math-equation.h
index d14b644..ea60df9 100644
--- a/src/math-equation.h
+++ b/src/math-equation.h
@@ -17,10 +17,11 @@
  *  02111-1307, USA.
  */
 
-#ifndef DISPLAY_H
-#define DISPLAY_H
+#ifndef MATH_EQUATION_H
+#define MATH_EQUATION_H
 
 #include <glib-object.h>
+#include <gtk/gtk.h>
 #include "mp.h"
 
 G_BEGIN_DECLS
@@ -29,68 +30,29 @@ G_BEGIN_DECLS
 
 typedef struct MathEquationPrivate MathEquationPrivate;
 
-#define UNDO_HISTORY_LENGTH 16  /* Arithmetic mode undo history length */
-#define MAX_DISPLAY 512
-
-/* Expression mode state */
-typedef struct {
-    MPNumber ans;           /* Previously calculated answer */
-    char *expression;       /* Expression entered by user */
-    int ans_start, ans_end; /* Start and end characters for ans variable in expression */
-    int cursor;
-} MathEquationState;
-
-/* Circular list of Arithmetic Precedence Mode states*/
-typedef struct {
-  unsigned int begin;
-  unsigned int end;
-  unsigned int current;
-  MathEquationState e[UNDO_HISTORY_LENGTH];  /* Expression mode state */
-} MathEquationHistory;
-
-/* Number display mode. */
-typedef enum { DEC, BIN, OCT, HEX, SCI, ENG } DisplayFormat;
-
 typedef struct
 {
-    GObject parent_instance;
+    GtkTextBuffer parent_instance;
     MathEquationPrivate *priv;
-    MathEquationHistory h;    /* History of expression mode states */
-    int show_tsep;         /* Set if the thousands separator should be shown. */
-    int show_zeroes;       /* Set if trailing zeroes should be shown. */
-    DisplayFormat format;  /* Number display mode. */
-    int accuracy;          /* Number of digits to show */
-    int word_size;
-    MPAngleUnit angle_unit;
 } MathEquation;
 
 typedef struct
 {
-    GObjectClass parent_class;
+    GtkTextBufferClass parent_class;
 
     void (*status_changed)(MathEquation *display);  
     void (*bitfield_changed)(MathEquation *display);
-    void (*display_changed)(MathEquation *display);
+    void (*number_mode_changed)(MathEquation *display);
 } MathEquationClass;
 
-/* Available functions */
-enum
-{
-    FN_TEXT,
-    FN_CALCULATE,
-    FN_CLEAR,
-    FN_BACKSPACE,
-    FN_DELETE,
-    FN_TOGGLE_BIT,
-    FN_SHIFT,
-    FN_FACTORIZE,
-    FN_STORE,
-    FN_RECALL,
-    FN_UNDO,
-    FN_REDO,
-    FN_PASTE,
-    FN_INSERT_CHARACTER
-};
+/* Number display mode. */
+typedef enum { DEC, BIN, OCT, HEX, SCI, ENG } DisplayFormat;
+
+typedef enum {
+    NORMAL,
+    SUPERSCRIPT,
+    SUBSCRIPT
+} NumberMode;
 
 GType math_equation_get_type();
 MathEquation *math_equation_new();
@@ -100,50 +62,43 @@ const gchar *math_equation_get_numeric_point_text(MathEquation *equation);
 
 void math_equation_set_status(MathEquation *equation, const gchar *status);
 const gchar *math_equation_get_status(MathEquation *equation);
+
 gboolean math_equation_get_bitfield_enabled(MathEquation *equation);
 guint64 math_equation_get_bitfield(MathEquation *equation);
-const gchar *math_equation_get_text(MathEquation *equation);
-gint math_equation_get_cursor(MathEquation *equation);
-
-void display_set_accuracy(MathEquation *display, int accuracy);
-void display_set_show_thousands_separator(MathEquation *display, gboolean visible);
-void display_set_show_trailing_zeroes(MathEquation *display, gboolean visible);
-void display_set_format(MathEquation *display, DisplayFormat format);
-void display_set_word_size(MathEquation *display, int word_size);
-void display_set_angle_unit(MathEquation *display, MPAngleUnit angle_unit);
-void display_clear(MathEquation *);
-
-gboolean display_get_integer(MathEquation *display, gint64 *value);
-gboolean display_get_unsigned_integer(MathEquation *display, guint64 *value);
-MPNumber *display_get_answer(MathEquation *);
-int display_get_cursor(MathEquation *);
-
-void display_set_number(MathEquation *display, const MPNumber *);
-void display_set_answer(MathEquation *display);
-void display_set_string(MathEquation *display, const char *, int);
-void display_set_cursor(MathEquation *display, int);
-void display_set_error(MathEquation *display, const char *);
-
-void display_convert(MathEquation *display, DisplayFormat format);
-
-void display_clear_stack(MathEquation *);
-void display_push(MathEquation *);
-void display_pop(MathEquation *);
-void display_unpop(MathEquation *);
-gboolean display_is_undo_step(MathEquation *display);
-
-void display_insert(MathEquation *display, int, int, const char *);
-void display_insert_number(MathEquation *display, int, int, const MPNumber *);
-void display_backspace(MathEquation *, int, int);
-void display_delete(MathEquation *, int, int);
-
-gboolean display_is_empty(MathEquation *);
-gboolean display_is_result(MathEquation *);
-gboolean display_is_usable_number(MathEquation *display, MPNumber *);
-gboolean display_is_number_with_base(MathEquation *display);
-
-void display_make_number(MathEquation *display, char *target, int target_len, const MPNumber *x);
-
-void display_do_function(MathEquation *display, int function, gpointer arg, int cursor_start, int cursor_end);
-
-#endif /* DISPLAY_H */
+
+void math_equation_set_number_mode(MathEquation *equation, NumberMode mode);
+NumberMode math_equation_get_number_mode(MathEquation *equation);
+
+//FIXME: Make get_
+void math_equation_set_accuracy(MathEquation *equation, int accuracy);
+void math_equation_set_show_thousands_separator(MathEquation *equation, gboolean visible);
+void math_equation_set_show_trailing_zeroes(MathEquation *equation, gboolean visible);
+void math_equation_set_format(MathEquation *equation, DisplayFormat format);
+void math_equation_set_word_size(MathEquation *equation, int word_size);
+void math_equation_set_angle_unit(MathEquation *equation, MPAngleUnit angle_unit);
+void math_equation_set_base(MathEquation *equation, gint base);
+
+void math_equation_copy(MathEquation *equation);
+void math_equation_paste(MathEquation *equation);
+void math_equation_store(MathEquation *equation, const gchar *name);
+void math_equation_recall(MathEquation *equation, const gchar *name);
+void math_equation_insert(MathEquation *equation, const gchar *text);
+void math_equation_insert_digit(MathEquation *equation, guint digit);
+void math_equation_insert_numeric_point(MathEquation *equation);
+void math_equation_insert_subtract(MathEquation *equation);
+void math_equation_insert_exponent(MathEquation *equation);
+void math_equation_insert_character(MathEquation *equation, const gchar *character);
+void math_equation_solve(MathEquation *equation);
+void math_equation_factorize(MathEquation *equation);
+void math_equation_delete(MathEquation *equation);
+void math_equation_backspace(MathEquation *equation);
+void math_equation_clear(MathEquation *equation);
+void math_equation_shift(MathEquation *equation, gint count);
+void math_equation_toggle_bit(MathEquation *equation, guint bit);
+
+//FIXME: Obsolete
+void display_set_number(MathEquation *equation, const MPNumber *);
+gboolean display_is_usable_number(MathEquation *equation, MPNumber *);
+void display_make_number(MathEquation *equation, char *target, int target_len, const MPNumber *x);
+
+#endif /* MATH_EQUATION_H */
diff --git a/src/ui-preferences.c b/src/ui-preferences.c
index dfbb81a..a70cf5a 100644
--- a/src/ui-preferences.c
+++ b/src/ui-preferences.c
@@ -79,7 +79,7 @@ angle_unit_combobox_changed_cb(GtkWidget *combo, PreferencesDialog *dialog)
     gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter);
     gtk_tree_model_get(model, &iter, 1, &value, -1);
     for (i = 0; unit_map[i].value != NULL && strcmp(unit_map[i].value, value) != 0; i++);
-    display_set_angle_unit(ui_get_equation(dialog->ui), unit_map[i].units);
+    math_equation_set_angle_unit(ui_get_equation(dialog->ui), unit_map[i].units);
 
     set_resource(R_TRIG, value);
 }
@@ -112,7 +112,7 @@ display_format_combobox_changed_cb(GtkWidget *combo, PreferencesDialog *dialog)
     gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter);
     gtk_tree_model_get(model, &iter, 1, &value, -1);
     for (i = 0; mode_map[i].value != NULL && strcmp(mode_map[i].value, value) != 0; i++);
-    display_set_format(ui_get_equation(dialog->ui), mode_map[i].format);
+    math_equation_set_format(ui_get_equation(dialog->ui), mode_map[i].format);
 
     set_resource(R_DISPLAY, value);
 }
@@ -129,7 +129,7 @@ word_size_combobox_changed_cb(GtkWidget *combo, PreferencesDialog *dialog)
     model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo));
     gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter);
     gtk_tree_model_get(model, &iter, 1, &value, -1);
-    display_set_word_size(ui_get_equation(dialog->ui), value);
+    math_equation_set_word_size(ui_get_equation(dialog->ui), value);
 
     set_int_resource(R_WORDLEN, value);
 }
@@ -142,7 +142,7 @@ decimal_places_spin_change_value_cb(GtkWidget *spin, PreferencesDialog *dialog)
     gint value = 0;
 
     value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin));
-    display_set_accuracy(ui_get_equation(dialog->ui), value);
+    math_equation_set_accuracy(ui_get_equation(dialog->ui), value);
 
     set_int_resource(R_ACCURACY, value);
 }
@@ -155,7 +155,7 @@ thousands_separator_check_toggled_cb(GtkWidget *check, PreferencesDialog *dialog
     gboolean value;
 
     value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check));
-    display_set_show_thousands_separator(ui_get_equation(dialog->ui), value);
+    math_equation_set_show_thousands_separator(ui_get_equation(dialog->ui), value);
     set_boolean_resource(R_TSEP, value);
 }
 
@@ -167,7 +167,7 @@ trailing_zeroes_check_toggled_cb(GtkWidget *check, PreferencesDialog *dialog)
     gboolean value;
 
     value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check));
-    display_set_show_trailing_zeroes(ui_get_equation(dialog->ui), value);
+    math_equation_set_show_trailing_zeroes(ui_get_equation(dialog->ui), value);
     set_boolean_resource(R_ZEROES, value);
 }
 
diff --git a/src/ui.c b/src/ui.c
index 2ede3f5..7828de2 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -151,7 +151,7 @@ G_MODULE_EXPORT
 void
 copy_cb(GtkWidget *widget, GCalctoolUI *ui)
 {
-    math_display_copy(ui->priv->display);
+    math_equation_copy(ui->priv->equation);
 }
 
 
@@ -159,7 +159,7 @@ G_MODULE_EXPORT
 void
 paste_cb(GtkWidget *widget, GCalctoolUI *ui)
 {
-    math_display_paste(ui->priv->display);
+    math_equation_paste(ui->priv->equation);
 }
 
 
@@ -347,7 +347,7 @@ ui_init(GCalctoolUI *ui)
     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), GTK_WIDGET(ui->priv->display));
     gtk_widget_show(GTK_WIDGET(ui->priv->display));
 
-    ui->priv->buttons = math_buttons_new(ui->priv->display);
+    ui->priv->buttons = math_buttons_new(ui->priv->equation);
     gtk_box_pack_start(GTK_BOX(GET_WIDGET(ui->priv->ui, "window_vbox")), GTK_WIDGET(ui->priv->buttons), TRUE, TRUE, 0);
     gtk_widget_show(GTK_WIDGET(ui->priv->buttons));
 



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