[gcalctool/gcalctool-newui2] ...



commit 8e523e28a3c914342e346b974ebbb76cf7e67008
Author: Robert Ancell <robert ancell gmail com>
Date:   Fri Jun 26 20:47:15 2009 +1000

    ...

 data/gcalctool.ui        |    7 +-
 src/display.c            |   36 +++----
 src/functions.c          |   11 ++-
 src/functions.h          |    7 +-
 src/gtk.c                |  247 ++++++++++++++++++++++------------------------
 src/mp-binary.c          |   13 ++-
 src/mp-convert.c         |  191 +++++++++++++----------------------
 src/mp-equation-lexer.l  |   94 ++++++++++-------
 src/mp-equation-parser.y |   50 ++++------
 src/mp-trigonometric.c   |    2 +-
 src/mp.h                 |    4 +-
 src/register.c           |    4 +-
 src/unittest.c           |   13 ++-
 13 files changed, 319 insertions(+), 360 deletions(-)
---
diff --git a/data/gcalctool.ui b/data/gcalctool.ui
index 271f450..1b2b7bb 100644
--- a/data/gcalctool.ui
+++ b/data/gcalctool.ui
@@ -2929,7 +2929,7 @@
               </packing>
             </child>
             <child>
-              <object class="GtkButton" id="calc_1s_button">
+              <object class="GtkButton" id="calc_ones_complement_button">
                 <property name="label" translatable="yes" comments="1's complement">ones</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
@@ -2948,7 +2948,7 @@
               </packing>
             </child>
             <child>
-              <object class="GtkButton" id="calc_2s_button">
+              <object class="GtkButton" id="calc_twos_complement_button">
                 <property name="label" translatable="yes" comments="2's complement">twos</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
@@ -3094,6 +3094,7 @@
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
                 <property name="focus_on_click">False</property>
+                <signal name="clicked" handler="button_cb"/>
                 <child>
                   <object class="GtkLabel" id="base_2_label">
                     <property name="visible">True</property>
@@ -3117,6 +3118,7 @@
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
                 <property name="focus_on_click">False</property>
+                <signal name="clicked" handler="button_cb"/>
                 <child>
                   <object class="GtkLabel" id="base_8_label">
                     <property name="visible">True</property>
@@ -3138,6 +3140,7 @@
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
                 <property name="focus_on_click">False</property>
+                <signal name="clicked" handler="button_cb"/>
                 <child>
                   <object class="GtkLabel" id="base_16_label">
                     <property name="visible">True</property>
diff --git a/src/display.c b/src/display.c
index 5341f2d..1fa3690 100644
--- a/src/display.c
+++ b/src/display.c
@@ -673,7 +673,7 @@ void
 make_eng_sci(GCDisplay *display, char *target, int target_len, const MPNumber *MPnumber, int base)
 {
     static char digits[] = "0123456789ABCDEF";   
-    char fixed[MAX_DIGITS], *optr;
+    char fixed[MAX_DIGITS];
     MPNumber MP1, MPatmp, MPval;
     MPNumber MP1base, MP3base, MP10base;
     int i, dval, len;
@@ -681,17 +681,17 @@ make_eng_sci(GCDisplay *display, char *target, int target_len, const MPNumber *M
     int ddig;                   /* Number of digits in exponent. */
     int eng = 0;                /* Set if this is an engineering number. */
     int exp = 0;                /* Exponent */
+    GString *string;
+    
+    string = g_string_sized_new(target_len);
     
     if (display->format == ENG) {
         eng = 1;
     }
-    optr = target;
     mp_abs(MPnumber, &MPval);
     mp_set_from_integer(0, &MP1);
-    if (mp_is_less_than(MPnumber, &MP1)) {
-        strcpy(optr, "â??");
-        optr += strlen("â??");
-    }
+    if (mp_is_less_than(MPnumber, &MP1))
+        g_string_append(string, "â??");
     mp_set_from_mp(&MPval, &MPmant);
 
     mp_set_from_integer(base, &MP1base);
@@ -729,39 +729,35 @@ make_eng_sci(GCDisplay *display, char *target, int target_len, const MPNumber *M
  
     mp_cast_to_string(&MPmant, base, v->accuracy, !v->display.show_zeroes, fixed, MAX_DIGITS);
     len = strlen(fixed);
-    for (i = 0; i < len; i++) {
-        *optr++ = fixed[i];
-    }
+    for (i = 0; i < len; i++)
+        g_string_append_c(string, fixed[i]);
  
-    *optr++ = 'e';
+    g_string_append(string, "Ã?10^");
  
     if (exp < 0) {
         exp = -exp;
-        strcpy(optr, "â??");
-        optr += strlen("â??");
+        g_string_append(string, "â??");
     } else {
-        *optr++ = '+';
+        g_string_append(string, "+");        
     }
  
-    mp_set_from_string("0.5", 10, &MP1);
+    mp_set_from_string("0.5", &MP1);
     mp_add_integer(&MP1, exp, &MPval);
     mp_set_from_integer(1, &MP1);
     for (ddig = 0; mp_is_greater_equal(&MPval, &MP1); ddig++) {
         mp_divide(&MPval, &MP1base, &MPval);
     }
  
-    if (ddig == 0) {
-        *optr++ = '0';
-    }
- 
     while (ddig-- > 0) {
         mp_multiply(&MPval, &MP1base, &MPval);
         dval = mp_cast_to_int(&MPval);
-        *optr++ = digits[dval];
+        g_string_append_c(string, digits[dval]);
         dval = -dval;
         mp_add_integer(&MPval, dval, &MPval);
     }
-    *optr++  = '\0';
+    
+    strncpy(target, string->str, target_len);
+    g_string_free(string, TRUE);
 }
 
 
diff --git a/src/functions.c b/src/functions.c
index 75d0b57..9609fd0 100644
--- a/src/functions.c
+++ b/src/functions.c
@@ -71,6 +71,9 @@ static Function functions[NFUNCTIONS] = {
 { FN_NUMERIC_POINT,     ".", NUMBER },
 { FN_EULERS_NUMBER,     "e", 0},
 { FN_PI,                "Ï?", 0},
+{ FN_BASE2,             "â??", 0},
+{ FN_BASE8,             "â??", 0},
+{ FN_BASE16,            "â??â??", 0},
 { FN_SUPER_0,           "â?°", 0 },
 { FN_SUPER_1,           "¹", 0 },
 { FN_SUPER_2,           "²", 0 },    
@@ -122,8 +125,8 @@ static Function functions[NFUNCTIONS] = {
 { FN_ABSOLUTE_VALUE,    "|", 0 },
 { FN_TRUNC,             "trunc", 0 },
 { FN_MODULUS_DIVIDE,    "mod", 0 },
-{ FN_1S_COMPLEMENT,     "ones", 0 },
-{ FN_2S_COMPLEMENT,     "twos", 0 },
+{ FN_ONES_COMPLEMENT,   "ones", 0 },
+{ FN_TWOS_COMPLEMENT,   "twos", 0 },
 { FN_EXPONENTIAL,       "Ã?10^", 0 },
 { FN_NOT,               "~", 0 },
 { FN_OR,                "or", 0 },
@@ -367,7 +370,7 @@ do_expression(int function, int arg, int cursor_start, int cursor_end)
         case FN_CLEAR:
             display_clear(&v->display);
             ui_set_error_state(FALSE);
-            mp_set_from_string("0", 10, ans);
+            mp_set_from_string("0", ans);
             break;
 
         case FN_SHIFT:
@@ -429,7 +432,7 @@ do_expression(int function, int arg, int cursor_start, int cursor_end)
     
                 /* FIXME: Convert to string since we don't support setting MP numbers from 64 bit integers */
                 SNPRINTF(buf, MAX_DISPLAY, "%llu", bit_value);
-                mp_set_from_string(buf, 10, &MP);
+                mp_set_from_string(buf, &MP);
                 display_set_number(&v->display, &MP);
             }
             break;
diff --git a/src/functions.h b/src/functions.h
index eecd69c..11e8893 100644
--- a/src/functions.h
+++ b/src/functions.h
@@ -34,6 +34,9 @@ enum
     FN_NUMERIC_POINT,
     FN_EULERS_NUMBER,
     FN_PI,
+    FN_BASE2,
+    FN_BASE8,
+    FN_BASE16,
     FN_SUPER_0, FN_SUPER_1, FN_SUPER_2, FN_SUPER_3,
     FN_SUPER_4, FN_SUPER_5, FN_SUPER_6, FN_SUPER_7,
     FN_SUPER_8, FN_SUPER_9, FN_SUPER_MINUS,
@@ -66,8 +69,8 @@ enum
     FN_ABSOLUTE_VALUE,
     FN_TRUNC,
     FN_MODULUS_DIVIDE,
-    FN_1S_COMPLEMENT,
-    FN_2S_COMPLEMENT,
+    FN_ONES_COMPLEMENT,
+    FN_TWOS_COMPLEMENT,
     FN_EXPONENTIAL,
     FN_NOT,
     FN_OR,
diff --git a/src/gtk.c b/src/gtk.c
index 3bca412..185adc1 100644
--- a/src/gtk.c
+++ b/src/gtk.c
@@ -20,6 +20,8 @@
  *  02111-1307, USA.
  */
 
+//â?°Â¹Â²Â³â?´â?µâ?¶â?·â?¸â?¹â?»â??â??â??â??â??â??â??â??â??â??â??
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -98,18 +100,6 @@ static char *finc_dialog_fields[FINC_NUM_DIALOGS][5] = {
     {"term_pmt",  "term_fv",     "term_pint",  NULL,         NULL},
 };
 
-/*  This table shows the keyboard values that are currently being used:
- *
- *           |  a b c d e f g h i j k l m n o p q r s t u v w x y z
- *-----------+-----------------------------------------------------
- *  Lower:   |  a b c d e f g h i j k l m n o p q r s t u v w x   z
- *  Upper:   |  A   C D E F G H I J K   M N O P Q R S T     W X Y Z
- *  Numeric: |  0 1 2 3 4 5 6 7 8 9
- *  Other:   |  @ . + - * / = % ( ) # < > [   { | & ~ ^ ? ! :
- *           |  BackSpace Delete Return
- *-----------+-----------------------------------------------------
- */
-    
 static struct button_widget button_widgets[] = {
     {FN_0,                  "0",
     { 0,     0,        0,             0 },
@@ -152,36 +142,48 @@ static struct button_widget button_widgets[] = {
     { GDK_9, GDK_KP_9, GDK_KP_Page_Up, GDK_R9, 0 }},
 
     {FN_A,                  "a",
-    { 0,     0 },
-    { GDK_a, 0 }},
+    { 0,     0,     0 },
+    { GDK_a, GDK_A, 0 }},
 
     {FN_B,                  "b",
-    { 0,     0 },
-    { GDK_b, 0 }},
+    { 0,     0,     0 },
+    { GDK_b, GDK_B, 0 }},
 
     {FN_C,                  "c",
-    { 0,     0 },
-    { GDK_c, 0 }},
+    { 0,     0,     0 },
+    { GDK_c, GDK_C, 0 }},
 
     {FN_D,                  "d",
-    { 0,     0 },
-    { GDK_d, 0 }},
+    { 0,     0,     0 },
+    { GDK_d, GDK_D, 0 }},
 
     {FN_E,                  "e",
-    { 0,     0 },
-    { GDK_e, 0 }},
+    { 0,     0,     0 },
+    { GDK_e, GDK_E, 0 }},
 
     {FN_F,                  "f",
-    { 0,     0 },
-    { GDK_f, 0 }},
+    { 0,     0,     0 },
+    { GDK_f, GDK_F, 0 }},
+    
+    {FN_BASE2,              "base_2",
+    { 0 },
+    { 0 }},
+
+    {FN_BASE8,              "base_8",
+    { 0 },
+    { 0 }},
+
+    {FN_BASE16,             "base_16",
+    { 0 },
+    { 0 }},
     
     {FN_PI,                 "pi",
-    { 0,     0 },
-    { 0,     0 }},
+    { GDK_CONTROL_MASK, 0 },
+    { GDK_p,            0 }},
 
     {FN_EULERS_NUMBER,      "eulers_number",
-    { 0,     0 },
-    { 0,     0 }},
+    { 0 },
+    { 0 }},
 
     {FN_CLEAR,              "clear",
     { 0,              GDK_SHIFT_MASK, GDK_CONTROL_MASK, 0 },
@@ -196,12 +198,12 @@ static struct button_widget button_widgets[] = {
     { GDK_greater, 0 }},
 
     {FN_STORE,              "store",
-    { 0,     0 },
-    { GDK_S, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_RECALL,             "recall",
-    { 0,     0 },
-    { GDK_R, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_NUMERIC_POINT,      "numeric_point",
     { 0,          0,              0,             0,                0 },
@@ -236,148 +238,148 @@ static struct button_widget button_widgets[] = {
     { GDK_slash, GDK_division, GDK_KP_Divide, GDK_R5, 0 }},
 
     {FN_INTEGER,            "integer_portion",
-    { 0,     0 },
-    { GDK_i, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_PERCENTAGE,         "percentage",
     { 0,           0 },
     { GDK_percent, 0 }},
 
     {FN_ROOT,               "root",
-    { 0,     0 },
-    { GDK_s, 0 }},
+    { GDK_CONTROL_MASK, 0 },
+    { GDK_r,            0 }},
 
     {FN_INVERSE,            "inverse",
-    { 0,     0 },
-    { GDK_r, 0 }},
+    { GDK_CONTROL_MASK, 0 },
+    { GDK_i,            0 }},
 
     {FN_ABSOLUTE_VALUE,     "abs",
-    { 0,     0 },
-    { GDK_u, 0 }},
+    { 0,       0 },
+    { GDK_bar, 0 }},
 
     {FN_TRUNC,              "trunc",
-    { 0,                0 },
-    { GDK_bracketleft, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_MODULUS_DIVIDE,     "modulus_divide",
-    { 0,     0 },
-    { GDK_M, 0 }},
+    { 0 },
+    { 0 }},
 
-    {FN_1S_COMPLEMENT,      "1s",
-    { 0,     0 },
-    { GDK_z, 0 }},
+    {FN_ONES_COMPLEMENT,    "ones_complement",
+    { 0 },
+    { 0 }},
 
-    {FN_2S_COMPLEMENT,      "2s",
-    { 0,     0 },
-    { GDK_Z, 0 }},
+    {FN_TWOS_COMPLEMENT,    "twos_complement",
+    { 0 },
+    { 0 }},
 
     {FN_EXPONENTIAL,        "exponential",
-    { 0,     0 },
-    { GDK_E, 0 }},
+    { GDK_CONTROL_MASK, 0 },
+    { GDK_e,            0 }},
 
     {FN_FACTORIAL,          "factorial",
     { 0,          0 },
     { GDK_exclam, 0 }},
 
     {FN_RANDOM,             "random",
-    { 0,            0 },
-    { GDK_question, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_NOT,                "not",
-    { 0,              0 },
-    { GDK_asciitilde, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_OR,                 "or",
-    { 0,       0 },
-    { GDK_bar, 0 }},
+    { GDK_CONTROL_MASK, 0 },
+    { GDK_bar,          0 }},
 
     {FN_AND,                "and",
-    { 0,             0 },
-    { GDK_ampersand, 0 }},
+    { GDK_CONTROL_MASK, 0 },
+    { GDK_ampersand,    0 }},
 
     {FN_XOR,                "xor",
-    { 0,     0 },
-    { GDK_x, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_XNOR,               "xnor",
-    { 0,             0 },
-    { GDK_braceleft, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_SIN,                "sine",
-    { 0,     0 },
-    { GDK_k, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_SINH,               "hyperbolic_sine",
-    { 0,     0 },
-    { GDK_K, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_COS,                "cosine",
-    { 0,     0 },
-    { GDK_j, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_COSH,               "hyperbolic_cosine",
-    { 0,     0 },
-    { GDK_J, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_TAN,                "tangent",
-    { 0,     0 },
-    { GDK_w, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_TANH,               "hyperbolic_tangent",
-    { 0,     0 },
-    { GDK_W, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_NATURAL_LOGARITHM,  "natural_logarithm",
-    { 0,     0 },
-    { GDK_n, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_LOGARITHM,          "logarithm",
-    { 0,     0 },
-    { GDK_g, 0 }},
+    { 0 },
+    { 0 }},
 
     {FN_X_POW_Y,            "x_pow_y",
-    { 0,     0,         0,               0 },
-    { GDK_o, GDK_caret, GDK_asciicircum, 0 }},
+    { 0,         0,               0 },
+    { GDK_caret, GDK_asciicircum, 0 }},
 
     { 0,                    "finc_compounding_term",
-    { 0,     0 },
-    { GDK_m, 0 }},
+    { 0 },
+    { 0 }},
 
     { 0,                    "finc_double_declining_depreciation",
-    { 0,     0 },
-    { GDK_D, 0 }},
+    { 0 },
+    { 0 }},
 
     { 0,                    "finc_future_value",
-    { 0,     0 },
-    { GDK_v, 0 }},
+    { 0 },
+    { 0 }},
 
     { 0,                    "finc_gross_profit_margin",
-    { 0,     0 },
-    { GDK_I, 0 }},
+    { 0 },
+    { 0 }},
 
     { 0,                    "finc_periodic_payment",
-    { 0,     0 },
-    { GDK_P, 0 }},
+    { 0 },
+    { 0 }},
 
     { 0,                    "finc_present_value",
-    { 0,     0 },
-    { GDK_p, 0 }},
+    { 0 },
+    { 0 }},
 
     { 0,                    "finc_periodic_interest_rate",
-    { 0,     0 },
-    { GDK_T, 0 }},
+    { 0 },
+    { 0 }},
 
     { 0,                    "finc_straight_line_depreciation",
-    { 0,     0 },
-    { GDK_l, 0 }},
+    { 0 },
+    { 0 }},
 
     { 0,                    "finc_sum_of_the_years_digits_depreciation",
-    { 0,     0 },
-    { GDK_Y, 0 }},
+    { 0 },
+    { 0 }},
 
     { 0,                    "finc_term",
-    { 0,     0 },
-    { GDK_t, 0 }}
+    { 0 },
+    { 0 }}
 };
 #define NBUTTONS (sizeof(button_widgets) / sizeof(struct button_widget))
 
@@ -1200,7 +1202,7 @@ finc_response_cb(GtkWidget *widget, gint response_id)
         }
         entry = GET_FINC_WIDGET(finc_dialog_fields[dialog][i]);
         // FIXME: Have to delocalize the input
-        mp_set_from_string(gtk_entry_get_text(GTK_ENTRY(entry)), 10, &arg[i]);
+        mp_set_from_string(gtk_entry_get_text(GTK_ENTRY(entry)), &arg[i]);
         gtk_entry_set_text(GTK_ENTRY(entry), "0");
     }
     gtk_widget_grab_focus(GET_FINC_WIDGET(finc_dialog_fields[dialog][0]));
@@ -1506,13 +1508,13 @@ main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event)
 {
     int i, j, state;
     GtkWidget *button;
+    const char *allowed_input = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*/^|!%";
     
-    printf("'%s'\n", event->string);
-
     /* Only look at the modifiers we use */
     state = event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK);
     
     // FIXME: Convert event to character
+    // FIXME: Or safer to intercept characters as they enter the text input (handles input methods)
     
     if (check_for_localized_numeric_point(event->keyval) == TRUE) {
         event->state = 0;
@@ -1520,41 +1522,42 @@ main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event)
     }
     
     /* Accuracy shortcuts */
-    if (state == GDK_CONTROL_MASK) {
+    if (state == GDK_CONTROL_MASK || state == GDK_MOD1_MASK) {
+        gboolean do_sub = state == GDK_MOD1_MASK;
         switch (event->keyval) {
             case GDK_0:
-                do_button(event->state & GDK_SHIFT_MASK ? FN_SUB_0 : FN_SUPER_0, 0);
+                do_button(do_sub ? FN_SUB_0 : FN_SUPER_0, 0);
                 return TRUE;
             case GDK_1:
-                do_button(event->state & GDK_SHIFT_MASK ? FN_SUB_1 : FN_SUPER_1, 0);
+                do_button(do_sub ? FN_SUB_1 : FN_SUPER_1, 0);
                 return TRUE;
             case GDK_2:
-                do_button(event->state & GDK_SHIFT_MASK ? FN_SUB_2 : FN_SUPER_2, 0);
+                do_button(do_sub ? FN_SUB_2 : FN_SUPER_2, 0);
                 return TRUE;
             case GDK_3:
-                do_button(event->state & GDK_SHIFT_MASK ? FN_SUB_3 : FN_SUPER_3, 0);
+                do_button(do_sub ? FN_SUB_3 : FN_SUPER_3, 0);
                 return TRUE;
             case GDK_4:
-                do_button(event->state & GDK_SHIFT_MASK ? FN_SUB_4 : FN_SUPER_4, 0);
+                do_button(do_sub ? FN_SUB_4 : FN_SUPER_4, 0);
                 return TRUE;
             case GDK_5:
-                do_button(event->state & GDK_SHIFT_MASK ? FN_SUB_5 : FN_SUPER_5, 0);
+                do_button(do_sub ? FN_SUB_5 : FN_SUPER_5, 0);
                 return TRUE;
             case GDK_6:
-                do_button(event->state & GDK_SHIFT_MASK ? FN_SUB_6 : FN_SUPER_6, 0);
+                do_button(do_sub ? FN_SUB_6 : FN_SUPER_6, 0);
                 return TRUE;
             case GDK_7:
-                do_button(event->state & GDK_SHIFT_MASK ? FN_SUB_7 : FN_SUPER_7, 0);
+                do_button(do_sub ? FN_SUB_7 : FN_SUPER_7, 0);
                 return TRUE;
             case GDK_8:
-                do_button(event->state & GDK_SHIFT_MASK ? FN_SUB_8 : FN_SUPER_8, 0);
+                do_button(do_sub ? FN_SUB_8 : FN_SUPER_8, 0);
                 return TRUE;
             case GDK_9:
-                do_button(event->state & GDK_SHIFT_MASK ? FN_SUB_9 : FN_SUPER_9, 0);
+                do_button(do_sub ? FN_SUB_9 : FN_SUPER_9, 0);
                 return TRUE;
             case GDK_minus:
             case GDK_KP_Subtract:
-                do_button(event->state & GDK_SHIFT_MASK ? FN_SUB_MINUS : FN_SUPER_MINUS, 0);
+                do_button(do_sub ? FN_SUB_MINUS : FN_SUPER_MINUS, 0);
                 return TRUE;
         }
     }
@@ -1582,16 +1585,6 @@ main_window_key_press_cb(GtkWidget *widget, GdkEventKey *event)
 
     for (i = 0; i < NBUTTONS; i++) {
         button = X.buttons[i];
-        
-        /* Check if function is available */
-        if (!GTK_WIDGET_IS_SENSITIVE(button))
-            continue;
-        
-        /* In basic mode only allow buttons that the user can see */
-        if (X.mode == BASIC &&
-            (!GTK_WIDGET_VISIBLE(gtk_widget_get_parent(button)) ||
-             !GTK_WIDGET_VISIBLE(button)))
-            continue;
 
         // FIXME: This is a bit hacky - needs to be rethought
         for (j = 0; button_widgets[i].accelerator_keys[j] != 0; j++) {
diff --git a/src/mp-binary.c b/src/mp-binary.c
index e9b10b7..153a4bd 100644
--- a/src/mp-binary.c
+++ b/src/mp-binary.c
@@ -19,13 +19,13 @@ static int hex_to_int(char digit)
 static void
 mp_bitwise(const MPNumber *x, const MPNumber *y, int (*bitwise_operator)(int, int), MPNumber *z, int wordlen)
 {
-    char text1[MAX_DIGITS], text2[MAX_DIGITS], text_out[MAX_DIGITS];
+    char text1[MAX_DIGITS], text2[MAX_DIGITS], text_out[MAX_DIGITS], text_out2[MAX_DIGITS];
     int offset1, offset2, offset_out;
    
     mp_cast_to_string(x, 16, 0, 0, text1, MAX_DIGITS);
     mp_cast_to_string(y, 16, 0, 0, text2, MAX_DIGITS);
-    offset1 = strlen(text1) - 1;
-    offset2 = strlen(text2) - 1;
+    offset1 = strlen(text1) - 1 - strlen("â??â??");
+    offset2 = strlen(text2) - 1 - strlen("â??â??");
     offset_out = wordlen / 4 - 1;
     if (offset_out <= 0) {
         offset_out = offset1 > offset2 ? offset1 : offset2;
@@ -50,7 +50,8 @@ mp_bitwise(const MPNumber *x, const MPNumber *y, int (*bitwise_operator)(int, in
         text_out[offset_out] = digits[bitwise_operator(v1, v2)];
     }
    
-    mp_set_from_string(text_out, 16, z);
+    snprintf(text_out2, MAX_DIGITS, "%sâ??â??", text_out);
+    mp_set_from_string(text_out2, z);
 }
 
 
@@ -116,10 +117,10 @@ mp_mask(const MPNumber *x, int wordlen, MPNumber *z)
     
     /* Convert to a hexadecimal string and use last characters */
     mp_cast_to_string(x, 16, 0, 0, text, MAX_DIGITS);
-    len = strlen(text);
+    len = strlen(text) - strlen("â??â??");
     offset = wordlen / 4;
     offset = len > offset ? len - offset: 0;
-    mp_set_from_string(text + offset, 16, z);
+    mp_set_from_string(text + offset, z);
 }
 
 
diff --git a/src/mp-convert.c b/src/mp-convert.c
index c7d1a3f..0a01914 100644
--- a/src/mp-convert.c
+++ b/src/mp-convert.c
@@ -479,29 +479,19 @@ mp_cast_to_double(const MPNumber *x)
  * maximum number of digits specified.
  */
 void
-mp_cast_to_string(const MPNumber *MPnumber, int base, int accuracy, int trim_zeroes, char *buffer, int buffer_length)
+mp_cast_to_string(const MPNumber *x, int base, int accuracy, int trim_zeroes, char *buffer, int buffer_length)
 {
     static char digits[] = "0123456789ABCDEF";
-    char *optr, *start, *end, *stopper, *last_non_zero;
     MPNumber number, integer_component, fractional_component, MPbase, temp;
-    int i;
-   
-    optr = buffer;
-    stopper = buffer + buffer_length - 1;
-
-    /* Insert sign */
-    if (mp_is_negative(MPnumber)) {
-        if (optr + strlen("â??") >= stopper) {
-            mperr(_("Number too big to represent"));
-            *optr = '\0';
-            return;
-        }
-        strcpy(optr, "â??");
-        optr += strlen("â??");
-        mp_abs(MPnumber, &number);
-    } else  {
-        mp_set_from_mp(MPnumber, &number);	
-    }
+    int i, last_non_zero;
+    GString *string;
+    
+    string = g_string_sized_new(buffer_length);
+
+    if (mp_is_negative(x))
+        mp_abs(x, &number);
+    else
+        mp_set_from_mp(x, &number);
    
     /* Add rounding factor */
     mp_set_from_integer(base, &MPbase);
@@ -515,7 +505,6 @@ mp_cast_to_string(const MPNumber *MPnumber, int base, int accuracy, int trim_zer
     mp_fractional_component(&number, &fractional_component);  
 
     /* Write out the integer component least significant digit to most */
-    start = optr;
     mp_set_from_mp(&integer_component, &temp);
     do {
         MPNumber t, t2, t3;
@@ -527,29 +516,13 @@ mp_cast_to_string(const MPNumber *MPnumber, int base, int accuracy, int trim_zer
         mp_subtract(&temp, &t2, &t3);
         mp_integer_component(&t3, &t3);
 
-        if (optr == stopper) {
-            mperr(_("Number too big to represent"));
-            *optr = '\0';
-            return;
-        }
-        *optr++ = digits[mp_cast_to_int(&t3)];
+        g_string_prepend_c(string, digits[mp_cast_to_int(&t3)]);
        
         mp_set_from_mp(&t, &temp);
     } while (!mp_is_zero(&temp));
-   
-    /* Reverse digits */
-    end = optr - 1;
-    while(start < end) {
-        char t;
-        t = *start;
-        *start = *end;
-        *end = t;
-        start++;
-        end--;
-    }
-   
-    last_non_zero = optr;
-    *optr++ = '.';
+
+    last_non_zero = string->len;
+    g_string_append_c(string, '.');
    
     /* Write out the fractional component */
     mp_set_from_mp(&fractional_component, &temp);
@@ -561,29 +534,40 @@ mp_cast_to_string(const MPNumber *MPnumber, int base, int accuracy, int trim_zer
         mp_integer_component(&temp, &digit);
         d = mp_cast_to_int(&digit);
        
-        if (optr == stopper) {
-            mperr(_("Number too big to represent"));
-            *optr = '\0';
-            return;
-        }        
-        *optr++ = digits[d];
+        g_string_append_c(string, digits[d]);
 
         if(d != 0)
-            last_non_zero = optr;
+            last_non_zero = string->len;
         mp_subtract(&temp, &digit, &temp);
     }
 
     /* Strip trailing zeroes */
     if (trim_zeroes || accuracy == 0)
-       optr = last_non_zero;
-
-    *optr = '\0';
+        g_string_truncate(string, last_non_zero);
     
     /* Remove negative sign if the number was rounded down to zero */
-    if (strcmp(buffer, "â??0") == 0) {
-        buffer[0] = '0';
-        buffer[1] = '\0';
+    if (mp_is_negative(x) && strcmp(string->str, "0") != 0)
+        g_string_prepend(string, "â??");
+
+    switch(base)
+    {
+    case 2:
+        g_string_append(string, "â??");
+        break;
+    case 8:
+        g_string_append(string, "â??");
+        break;
+    default:
+    case 10:
+        break;
+    case 16:
+        g_string_append(string, "â??â??");
+        break;
     }
+    
+    // FIXME: Check for truncation
+    strncpy(buffer, string->str, buffer_length);
+    g_string_free(string, TRUE);
 }
 
 
@@ -606,97 +590,64 @@ char_val(char chr, int base)
 }
 
 
-/* Convert string into an MP number, in the given base
- */
+/* Convert string into an MP number */
 void
-mp_set_from_string(const char *str, int base, MPNumber *MPval)
+mp_set_from_string(const char *str, MPNumber *MPval)
 {
-    const char *optr;
-    int inum;
-    int negate = 0;
-
-    optr = str;
-
-    /* Remove leading whitespace */
-    while (isspace(*optr)) {
-        optr++;
+    int i, base, negate = 0;
+    const char *c, *end;
+    const char *base_suffixes[] = {"â??", "â??", "â??â??", NULL};
+    int base_values[] = {2, 8, 16, 10};
+    
+    /* Find the base */
+    end = str;
+    while (*end != '\0')
+        end++;
+    for (i = 0; base_suffixes[i] != NULL; i++) {
+        if (end - strlen(base_suffixes[i]) < str)
+            continue;
+        if (strcmp(end - strlen(base_suffixes[i]), base_suffixes[i]) == 0)
+            break;
     }
+    base = base_values[i];
 
-    /* Check if this is a negative number. */
-    if (*optr == '-') {
+    /* Check if this is a negative number */
+    c = str;
+    if (*c == '-') {
         negate = 1;
-        optr++;
-    } else if (strncmp(optr, "â??", strlen("â??")) == 0) {
+        c++;
+    } else if (strncmp(c, "â??", strlen("â??")) == 0) {
         negate = 1;
-        optr += strlen("â??");
+        c += strlen("â??");
     }
-
+    
     /* Convert integer part */
     mp_set_from_integer(0, MPval);
-    while ((inum = char_val(*optr, base)) >= 0) {
+    while ((i = char_val(*c, base)) >= 0) {
         mp_multiply_integer(MPval, base, MPval);
-        mp_add_integer(MPval, inum, MPval);
-        optr++;
+        mp_add_integer(MPval, i, MPval);
+        c++;
     }
    
     /* Convert fractional part */
-    if (*optr == '.') {
+    if (*c == '.') {
         MPNumber numerator, denominator;
        
-        optr++;
+        c++;
 
         mp_set_from_integer(0, &numerator);
         mp_set_from_integer(1, &denominator);
-        while ((inum = char_val(*optr, base)) >= 0) {
+        while ((i = char_val(*c, base)) >= 0) {
             mp_multiply_integer(&denominator, base, &denominator);
             mp_multiply_integer(&numerator, base, &numerator);
-            mp_add_integer(&numerator, inum, &numerator);
-            optr++;
+            mp_add_integer(&numerator, i, &numerator);
+            c++;
         }
         mp_divide(&numerator, &denominator, &numerator);
         mp_add(MPval, &numerator, MPval);
     }
    
-    /* Convert exponential part */
-    if (*optr == 'e' || *optr == 'E') {
-        int negate = 0;
-        MPNumber MPbase, MPexponent, temp;
-
-        optr++;       
-
-        /* Get sign */
-        if (*optr == '-') {
-            negate = 1;
-            optr++;
-        } else if (strncmp(optr, "â??", strlen("â??")) == 0) {
-            negate = 1;
-            optr += strlen("â??");
-        } else if (*optr == '+') {
-            optr++;
-        }
-
-        /* Get magnitude */
-        mp_set_from_integer(0, &MPexponent);
-        while ((inum = char_val(*optr, base)) >= 0) {
-            mp_multiply_integer(&MPexponent, base, &MPexponent);
-            mp_add_integer(&MPexponent, inum, &MPexponent);
-            optr++;
-        }
-        if (negate) {
-            mp_invert_sign(&MPexponent, &MPexponent);
-        }
-
-        mp_set_from_integer(base, &MPbase);       
-        mp_pwr(&MPbase, &MPexponent, &temp);
-        mp_multiply(MPval, &temp, MPval);
-    }
-
-    /* Strip trailing whitespace */
-    while (isspace(*optr)) {
-        optr++;
-    }
-   
-    if (*optr != '\0') {
+    if (c != end) {
        // FIXME: Error decoding
     }
  
diff --git a/src/mp-equation-lexer.l b/src/mp-equation-lexer.l
index d9462db..e5edb3e 100644
--- a/src/mp-equation-lexer.l
+++ b/src/mp-equation-lexer.l
@@ -10,6 +10,7 @@
 /*  $Header: /cvs/gnome/gcalctool/gcalctool/ce_tokeniser.l,v 1.16 2006/12/15 15:27:37 richb Exp $
  *
  *  Copyright (C) 2004-2008 Sami Pietila
+ *  Copyright (C) 2008-2009 Robert Ancell
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -35,18 +36,57 @@
 #include "calctool.h"
 #include "mp-equation.h"
 #include "mp-equation-parser.h"
+
+static int super_atoi(const char *data)
+{
+   int i, value = 0;
+   const char *digits[11] = {"�", "¹", "²", "³", "�", "�", "�", "�", "�", "�", NULL};
+   
+   while(*data != '\0') {
+      for(i = 0; digits[i] != NULL && strncmp(data, digits[i], strlen(digits[i])) != 0; i++);
+      if(digits[i] == NULL)
+         return 0;
+      value = value * 10 + i;
+      data += strlen(digits[i]);
+   }
+   
+   return value;
+}
+
+static int sub_atoi(const char *data)
+{
+   int i, value = 0;
+   const char *digits[11] = {"â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", NULL};
+
+   while(*data != '\0') {
+      for(i = 0; digits[i] != NULL && strncmp(data, digits[i], strlen(digits[i])) != 0; i++);
+      if(digits[i] == NULL)
+         return 0;
+      data += strlen(digits[i]);
+      value = value * 10 + i;
+   }
+   
+   return value;
+}
 %}
 
-DECIMAL	"."|","
-SIGN	"+"|"-"|"â??"
-BIN     [0-1]
-OCT     [0-7]
-DEC     [0-9]
-HEX     [0-9]|[A-F]|[a-f]
-HEX_NUM {HEX}+|{HEX}*{DECIMAL}{HEX}*
-DEC_NUM{DEC}+|{DEC}*{DECIMAL}{DEC}*
-OCT_NUM{OCT}+|{OCT}*{DECIMAL}{OCT}*
-BIN_NUM{BIN}+|{BIN}*{DECIMAL}{BIN}*
+DECIMAL	     "."|","
+BIN          [0-1]
+BIN_SUFFIX   "â??"
+OCT          [0-7]
+OCT_SUFFIX   "â??"
+DEC          [0-9]
+HEX          [0-9]|[A-F]|[a-f]
+HEX_SUFFIX   "â??â??"
+SUPER_DIGITS "�"|"¹"|"²"|"³"|"�"|"�"|"�"|"�"|"�"|"�"
+SUB_DIGITS   "â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"
+
+HEX_NUM {HEX}+{HEX_SUFFIX}|{HEX}*{DECIMAL}{HEX}+{HEX_SUFFIX}
+DEC_NUM {DEC}+|{DEC}*{DECIMAL}{DEC}+
+OCT_NUM {OCT}+{OCT_SUFFIX}|{OCT}*{DECIMAL}{OCT}+{OCT_SUFFIX}
+BIN_NUM {BIN}+{BIN_SUFFIX}|{BIN}*{DECIMAL}{BIN}+{BIN_SUFFIX}
+SUP_NUM {SUPER_DIGITS}+
+SUB_NUM {SUB_DIGITS}+
 
 %%
 
@@ -70,14 +110,12 @@ BIN_NUM{BIN}+|{BIN}*{DECIMAL}{BIN}*
 "tanh�¹"|"atanh"|"Atanh"|"ATANH" {return tATANH;}
 "â?§"|"and"|"And"|"AND" {return tAND;}
 "ans"|"Ans"|"ANS" {return tANS;}
-"chs"|"Chs"|"CHS" {return tCHS;}
 "clr"|"Clr"|"CLR" {return tCLR;}
 "eng"|"Eng"|"ENG" {return tEXP;}
 "frac"|"Frac"|"FRAC" {return tFRAC;}
 "int"|"Int"|"INT" {return tINT;}
 "ln"|"Ln"|"LN" {return tLN;}
-"log"|"Log"|"LOG" {return tLOG10;}
-"logâ??"|"Logâ??"|"log_2"|"Log_2"|"LOG_2" {return tLOG2;}
+"log"|"Log"|"LOG" {return tLOG;}
 "mod"|"Mod"|"MOD" {return tMOD;}
 "¬"|"~" {return tNOT;}
 "â?¨"|"or"|"Or"|"OR" {return tOR;}
@@ -87,8 +125,6 @@ BIN_NUM{BIN}+|{BIN}*{DECIMAL}{BIN}*
 "â??"|"sqrt"|"Sqrt"|"SQRT" {return tROOT;}
 "â??"|"cbrt"|"Cbrt"|"CBRT" {return tROOT3;}
 "â??" {return tROOT4;}
-"²" {return tSQUARED;}
-"³" {return tCUBED;}
 "sto"|"Sto"|"STO" {return tSTO;}
 "trunc"|"Trunc"|"TRUNC" {return tTRUNC;}
 "ones" {return t1S;}
@@ -101,35 +137,15 @@ yylval->integer = atoi(yytext+1);
 return tREG;
 }
 
-{BIN_NUM} {
-if (_mp_equation_get_extra(yyscanner)->base != 2) REJECT;
-if (strlen(yytext) > MAX_DIGITS) yyextra->error = -PARSER_ERR_TOO_LONG_NUMBER;
-mp_set_from_string(yytext, _mp_equation_get_extra(yyscanner)->base, &yylval->int_t);
-return tNUMBER;
-}
-
-{OCT_NUM} {
-if (_mp_equation_get_extra(yyscanner)->base != 8) REJECT;
-if (strlen(yytext) > MAX_DIGITS) yyextra->error = -PARSER_ERR_TOO_LONG_NUMBER;
-mp_set_from_string(yytext, _mp_equation_get_extra(yyscanner)->base, &yylval->int_t);
-return tNUMBER;
-}
+{SUP_NUM} { yylval->integer = super_atoi(yytext); return tSUPNUM; }
+{SUB_NUM} { yylval->integer = sub_atoi(yytext); return tSUBNUM; }
 
-{DEC_NUM} {
-if (_mp_equation_get_extra(yyscanner)->base != 10) REJECT;
+{BIN_NUM}|{OCT_NUM}|{DEC_NUM}|{HEX_NUM} {
 if (strlen(yytext) > MAX_DIGITS) yyextra->error = -PARSER_ERR_TOO_LONG_NUMBER;
-mp_set_from_string(yytext, _mp_equation_get_extra(yyscanner)->base, &yylval->int_t);
+mp_set_from_string(yytext, &yylval->int_t);
 return tNUMBER;
 }
 
-{HEX_NUM} {
-if (_mp_equation_get_extra(yyscanner)->base != 16) REJECT;
-if (strlen(yytext) > MAX_DIGITS) yyextra->error = -PARSER_ERR_TOO_LONG_NUMBER;
-mp_set_from_string(yytext, _mp_equation_get_extra(yyscanner)->base, &yylval->int_t);
-return tNUMBER;
-}
-
-
 [ \t\n]
 .        {return *yytext; }
 
diff --git a/src/mp-equation-parser.y b/src/mp-equation-parser.y
index b539d5b..fff7456 100644
--- a/src/mp-equation-parser.y
+++ b/src/mp-equation-parser.y
@@ -3,6 +3,7 @@
 /*  $Header: /cvs/gnome/gcalctool/gcalctool/ce_parser.y,v 1.16 2006/12/08 15:54:43 richb Exp $
  *
  *  Copyright (C) 2004-2008 Sami Pietila
+ *  Copyright (C) 2008-2009 Robert Ancell
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -65,8 +66,7 @@
 %token tFRAC
 %token tINT
 %token tLN
-%token tLOG10
-%token tLOG2
+%token tLOG
 %token tMOD
 %token t1S
 %token t2S
@@ -80,8 +80,6 @@
 %token tROOT
 %token tROOT3
 %token tROOT4
-%token tSQUARED
-%token tCUBED
 %token tSQRT
 %token tSTO
 %token tTAN
@@ -92,10 +90,11 @@
 
 %token <int_t> tNUMBER
 %token <integer> tREG
+%token <integer> tSUBNUM tSUPNUM
 
 %token NEG
 
-%type  <int_t> exp rcl value term reg func number parenthesis
+%type  <int_t> exp rcl value term func number
 
 %start statement
 %left tADD tSUBTRACT tMULTIPLY tDIVIDE
@@ -148,17 +147,13 @@ value:
 
 exp: 
   term {mp_set_from_mp(&$1, &$$);}
-
 | exp tADD term '%' {mp_add_integer(&$3, 100, &$3); mp_divide_integer(&$3, 100, &$3); mp_multiply(&$1, &$3, &$$);}
 | exp tSUBTRACT term '%' {mp_add_integer(&$3, -100, &$3); mp_divide_integer(&$3, -100, &$3); mp_multiply(&$1, &$3, &$$);}
-
 | exp tROOT term {MPNumber t; mp_sqrt(&$3, &t); mp_multiply(&$1, &t, &$$);}
 | exp tROOT3 term {MPNumber t; mp_root(&$3, 3, &t); mp_multiply(&$1, &t, &$$);}
 | exp tROOT4 term {MPNumber t; mp_root(&$3, 4, &t); mp_multiply(&$1, &t, &$$);}
-
 | exp tADD exp {mp_add(&$1, &$3, &$$);}
 | exp tSUBTRACT exp {mp_subtract(&$1, &$3, &$$);}
-
 | exp tMOD exp %prec MED {
     if (!mp_is_integer(&$1) || !mp_is_integer(&$3)) {
 	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_MODULUSOP;
@@ -168,7 +163,6 @@ exp:
       }			   
     }
 }
-
 | exp tAND exp {
     if (!mp_is_natural(&$1) || !mp_is_natural(&$3)) {
 	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
@@ -201,6 +195,7 @@ term:
 | 'e' {mp_get_eulers(&$$);} 
 | tPI {mp_get_pi(&$$);}
 | rcl {mp_set_from_mp(&$1, &$$);}
+| tSUBNUM tROOT term {mp_root(&$3, $1, &$$);}
 | tROOT term {mp_sqrt(&$2, &$$);}
 | tROOT3 term {mp_root(&$2, 3, &$$);}
 | tROOT4 term {mp_root(&$2, 4, &$$);}
@@ -208,8 +203,7 @@ term:
 | term tMULTIPLY term {mp_multiply(&$1, &$3, &$$);}
 | tABS exp tABS {mp_abs(&$2, &$$);} 
 | term '!' {mp_factorial(&$1, &$$);}
-| term tSQUARED {mp_pwr_integer(&$1, 2, &$$);}
-| term tCUBED {mp_pwr_integer(&$1, 3, &$$);}
+| term tSUPNUM {mp_pwr_integer(&$1, $2, &$$);}
 | term '%' {mp_divide_integer(&$1, 100, &$$);}
 | tNOT term %prec LNEG {
     if (!mp_is_natural(&$2)) {
@@ -219,49 +213,41 @@ term:
     }
     mp_not(&$2, _mp_equation_get_extra(yyscanner)->wordlen, &$$);
 }
-| tSUBTRACT term %prec NEG {mp_invert_sign(&$2, &$$);}
-| tADD term %prec POS {mp_set_from_mp(&$2, &$$);}
+| tSUBTRACT term {mp_invert_sign(&$2, &$$);}
+| tADD term {mp_set_from_mp(&$2, &$$);}
 | term '^' term {mp_xpowy(&$1, &$3, &$$);}
-
 | term func {mp_multiply(&$1, &$2, &$$);}
 | func {mp_set_from_mp(&$1, &$$);}
-| reg {mp_set_from_mp(&$1, &$$);}
-
-| parenthesis {mp_set_from_mp(&$1, &$$);}
+| tREG {mp_set_from_mp(register_get_value($1), &$$);}
+| '(' exp ')' {mp_set_from_mp(&$2, &$$);}
 ;
 
-parenthesis:
-  '(' exp ')' {mp_set_from_mp(&$2, &$$);}
-  ;
-
-reg: 
-  tREG {mp_set_from_mp(register_get_value($1), &$$);}
-  ;
-
 func:
-  tLOG10 term %prec HIGH {mp_logarithm(10, &$2, &$$);}
-| tLOG2 term %prec HIGH {mp_logarithm(2, &$2, &$$);}
-| tSQRT term %prec HIGH {mp_sqrt(&$2, &$$);}
+  tLOG term %prec HIGH {mp_logarithm(10, &$2, &$$);}
 | tLN term %prec HIGH {mp_ln(&$2, &$$);}
+| tLOG tSUBNUM term %prec HIGH {mp_logarithm($2, &$3, &$$);}
 | tRAND %prec HIGH {mp_set_from_random(&$$);}
 | tABS_FUNC term %prec HIGH {mp_abs(&$2, &$$);}
 | tFRAC term %prec HIGH {mp_fractional_component(&$2, &$$);}
 | tINT term %prec HIGH {mp_integer_component(&$2, &$$);}
-| tCHS term %prec HIGH {mp_invert_sign(&$2, &$$);}
-
 | tSIN term %prec HIGH {mp_sin(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
 | tCOS term %prec HIGH {mp_cos(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
 | tTAN term %prec HIGH {mp_tan(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
+| tSIN tSUPNUM term %prec HIGH {MPNumber t; mp_sin(&$3, _mp_equation_get_extra(yyscanner)->angle_units, &t); mp_pwr_integer(&t, $2, &$$);}
+| tCOS tSUPNUM term %prec HIGH {MPNumber t; mp_cos(&$3, _mp_equation_get_extra(yyscanner)->angle_units, &t); mp_pwr_integer(&t, $2, &$$);}
+| tTAN tSUPNUM term %prec HIGH {MPNumber t; mp_tan(&$3, _mp_equation_get_extra(yyscanner)->angle_units, &t); mp_pwr_integer(&t, $2, &$$);}
 | tASIN term %prec HIGH {mp_asin(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
 | tACOS term %prec HIGH {mp_acos(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
 | tATAN term %prec HIGH {mp_atan(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
 | tSINH term %prec HIGH {mp_sinh(&$2, &$$);}
 | tCOSH term %prec HIGH {mp_cosh(&$2, &$$);}
 | tTANH term %prec HIGH {mp_tanh(&$2, &$$);}
+| tSINH tSUPNUM term %prec HIGH {MPNumber t; mp_sinh(&$3, &t); mp_pwr_integer(&t, $2, &$$);}
+| tCOSH tSUPNUM term %prec HIGH {MPNumber t; mp_cosh(&$3, &t); mp_pwr_integer(&t, $2, &$$);}
+| tTANH tSUPNUM term %prec HIGH {MPNumber t; mp_tanh(&$3, &t); mp_pwr_integer(&t, $2, &$$);}
 | tASINH term %prec HIGH {mp_asinh(&$2, &$$);}
 | tACOSH term %prec HIGH {mp_acosh(&$2, &$$);}
 | tATANH term %prec HIGH {mp_atanh(&$2, &$$);}
-
 | tTRUNC term %prec HIGH {mp_mask(&$2, _mp_equation_get_extra(yyscanner)->wordlen, &$$);}
 | t1S term %prec HIGH  {
     if (!mp_is_natural(&$2)) {
diff --git a/src/mp-trigonometric.c b/src/mp-trigonometric.c
index ddfaaf7..698d60f 100644
--- a/src/mp-trigonometric.c
+++ b/src/mp-trigonometric.c
@@ -657,7 +657,7 @@ mp_atanh(const MPNumber *x, MPNumber *z)
         mp_subtract(&MP1, x, &MP3);
         mp_divide(&MP2, &MP3, &MP3);
         mp_ln(&MP3, &MP3);
-        mp_set_from_string("0.5", 10, &MP1);
+        mp_set_from_string("0.5", &MP1);
         mp_multiply(&MP1, &MP3, z);
     }
 }
diff --git a/src/mp.h b/src/mp.h
index d435028..f01b7fa 100644
--- a/src/mp.h
+++ b/src/mp.h
@@ -193,8 +193,8 @@ void   mp_set_from_fraction(int numerator, int denominator, MPNumber *z);
 /* Sets z to be a uniform random number in the range [0, 1] */
 void   mp_set_from_random(MPNumber *z);
 
-/* Sets z from a string representation in 'text' in base 'base' */
-void   mp_set_from_string(const char *text, int base, MPNumber *z);
+/* Sets z from a string representation in 'text' */
+void   mp_set_from_string(const char *text, MPNumber *z);
 
 /* Returns x as a native single-precision floating point number */
 float  mp_cast_to_float(const MPNumber *x);
diff --git a/src/register.c b/src/register.c
index 9b2da9f..5ea69a6 100644
--- a/src/register.c
+++ b/src/register.c
@@ -76,14 +76,14 @@ void register_init()
         }
 
         if (nline && vline) {
-            mp_set_from_string(vline, 10, &value);
+            mp_set_from_string(vline, &value);
             register_set_name(i, nline);
             register_set_value(i, &value);
             g_free(nline);
             g_free(vline);
         }
         else {
-            mp_set_from_string(default_registers[i][1], 10, &value);
+            mp_set_from_string(default_registers[i][1], &value);
             register_set_name(i, default_registers[i][0]);
             register_set_value(i, &value);
         }
diff --git a/src/unittest.c b/src/unittest.c
index a3f3f56..1c02e48 100644
--- a/src/unittest.c
+++ b/src/unittest.c
@@ -184,6 +184,8 @@ test_parser()
     test("â??4â??2", "0", 0);
     test("â??8", "2", 0);
     test("â??16", "2", 0);
+    test("â??â??8", "2", 0);
+    test("â??â??â??1024", "2", 0);
     test("â??(2+2)", "2", 0);
     test("2â??4", "4", 0);
     test("2Ã?â??4", "4", 0);
@@ -232,6 +234,7 @@ test_parser()
     test("sin 90", "1", 0);
     test("sin 180", "0", 0);
     test("2 sin 90", "2", 0);
+    test("sin²45", "0.5", 0);
    
     test("cos 0", "1", 0);
     test("cos 45 â?? 1÷â??2", "0", 0);
@@ -239,10 +242,13 @@ test_parser()
     test("cos 90", "0", 0);
     test("cos 180", "â??1", 0);
     test("2 cos 0", "2", 0);
+    test("cos²45", "0.5", 0);
 
     test("tan 0", "0", 0);
     test("tan 10 â?? sin 10÷cos 10", "0", 0);
     test("tan 90", "", -20001);
+    test("tan 10", "0.176326981", 0);    
+    test("tan²10", "0.031091204", 0);
 
     test("cos�¹ 0", "90", 0);
     test("cos�¹ 1", "0", 0);
@@ -277,12 +283,13 @@ test_parser()
     v->ttype = MP_GRADIANS;
     test("sin 100", "1", 0);
 
-    v->base = 16;
     test("3 And 5", "1", 0);
     test("3 Or 5", "7", 0);
     test("3 Xor 5", "6", 0);
-    test("3 Xnor 5", "FFFFFFF9", 0);
-    test("~7A", "FFFFFF85", 0);
+    
+    v->base = 16;
+    test("3 Xnor 5", "FFFFFFF9â??â??", 0);
+    test("~7Aâ??â??", "FFFFFF85â??â??", 0);
 }
 
 



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