[gcalctool/gcalctool-newui] Made parse UTF-8 aware



commit 30c96c67a293bc925841d013b6f907930481a44a
Author: Robert Ancell <robert ancell gmail com>
Date:   Sun May 31 10:40:28 2009 +0200

    Made parse UTF-8 aware
---
 src/display.c            |   60 +++++++++++++++++++++++++++++++---------
 src/display.h            |    2 +-
 src/gtk.c                |   68 +++++++++++++++++++++++++++++++++++++--------
 src/mp-convert.c         |    4 +++
 src/mp-equation-lexer.l  |   12 +++++++-
 src/mp-equation-parser.y |   36 ++++++++++++++++++------
 src/unittest.c           |   11 +++++++
 7 files changed, 156 insertions(+), 37 deletions(-)

diff --git a/src/display.c b/src/display.c
index df4a9ca..bda956b 100644
--- a/src/display.c
+++ b/src/display.c
@@ -428,25 +428,28 @@ display_is_undo_step(GCDisplay *display)
 }
 
 void
-display_insert(GCDisplay *display, int cursor, const char *text)
+display_insert(GCDisplay *display, int cursor_start, int cursor_end, const char *text)
 {
     char buf[MAX_DISPLAY];
     const gchar *currentText;
     
-    if (cursor < 0) {
-        SNPRINTF(buf, MAX_DISPLAY, "%s%s", display_get_text(display), text);
+    currentText = display_get_text(display);    
+    
+    if (cursor_start < 0) {
+        SNPRINTF(buf, MAX_DISPLAY, "%s%s", currentText, text);
     } else {
-        currentText = display_get_text(display);
-        SNPRINTF(buf, MAX_DISPLAY, "%.*s%s%s", cursor, currentText, text, currentText + cursor);
-        cursor += strlen(text);
+        SNPRINTF(buf, MAX_DISPLAY, "%.*s%s%s", cursor_start, currentText, text, currentText + cursor_end);
+        cursor_start += strlen(text);
     }
-    display_set_string(display, buf, cursor);
+    display_set_string(display, buf, cursor_start);
 }
 
 void
 display_insert_at_cursor(GCDisplay *display, const char *text)
 {
-    display_insert(display, display_get_cursor(display), text);
+    int cursor;
+    cursor = display_get_cursor(display);
+    display_insert(display, cursor, cursor, text);
 }
 
 void
@@ -454,13 +457,15 @@ display_insert_number(GCDisplay *display, int cursor, const MPNumber *value)
 {
     char text[MAX_DISPLAY];
     display_make_number(display, text, MAX_DISPLAY, value, v->base, FALSE);
-    display_insert(display, cursor, text);
+    display_insert(display, cursor, cursor, text);
 }
 
 void
 display_insert_number_at_cursor(GCDisplay *display, const MPNumber *value)
 {
-    display_insert_number(display, display_get_cursor(display), value);
+    int cursor;
+    cursor = display_get_cursor(display);
+    display_insert_number(display, cursor, value);
 }
 
 
@@ -633,11 +638,40 @@ display_solve(GCDisplay *display)
     const char *text;
     int error;
     MPNumber result;
-    const char *message = NULL;
-    char result_text[MAXLINE];
-
+    const char *message = NULL, *c;
+    char *o, *clean_text, result_text[MAXLINE];
+    
     text = display_get_text(display);
+    clean_text = malloc(sizeof(char) * (strlen(text) + 1 + 100)); // FIXME: Needs to be growable e.g. Sqrt
+    for(c = text, o = clean_text; *c; c++) {
+        struct substitution
+        {
+            const char *a, *b;
+        } *s;
+        static struct substitution substitutions[] =
+        {
+            {"µ", "u"},
+            {NULL, NULL}
+        };
+        
+        for(s = substitutions; s->a != NULL; s++) {
+            if(strncmp(c, s->a, strlen(s->a)) == 0) {
+                strcpy(o, s->b);
+                c += strlen(s->a) - 1;
+                o += strlen(s->b);
+                break;
+            }
+        }
+        if(s->a == NULL) {
+            //assert((*c & 0x80) == 0);
+            *o = *c;
+            o++;
+        }
+    }
+    *o = '\0';
+    
     error = mp_equation_parse(text, &result);
+    free(clean_text);
     
     switch (error) {
     case 0:
diff --git a/src/display.h b/src/display.h
index fc14e98..d240998 100644
--- a/src/display.h
+++ b/src/display.h
@@ -81,7 +81,7 @@ void display_pop(GCDisplay *);
 void display_unpop(GCDisplay *);
 gboolean display_is_undo_step(GCDisplay *display);
 
-void display_insert(GCDisplay *display, int, const char *);
+void display_insert(GCDisplay *display, int, int, const char *);
 void display_insert_at_cursor(GCDisplay *display, const char *);
 void display_insert_number(GCDisplay *display, int, const MPNumber *);
 void display_insert_number_at_cursor(GCDisplay *display, const MPNumber *value);
diff --git a/src/gtk.c b/src/gtk.c
index 7ee643a..f4a6c72 100644
--- a/src/gtk.c
+++ b/src/gtk.c
@@ -167,7 +167,8 @@ typedef struct {
 
     GtkWidget *equation_view;
     GtkTextBuffer *equation_buffer;
-    GtkWidget *history_vbox;    
+    GtkWidget *history_vbox;
+    GtkWidget *history_scroll;
 
     GtkWidget *register_dialog;
     GtkWidget *register_entries[MAX_REGISTERS];
@@ -449,6 +450,7 @@ get_cursor(void)
     pos = gtk_text_iter_get_offset(&iter);
 
     /* Convert the last position to -1 */
+    // FIXME: -1 may now be obsolete
     if (pos == gtk_text_buffer_get_char_count(X.equation_buffer))
         return -1;
     else
@@ -604,6 +606,7 @@ ui_add_result(const char *equation, const char *result)
 {
     GtkWidget *result_box, *equation_label, *result_label, *alignment;
     gchar text[MAXLINE];
+    GtkAdjustment *adjustment;
     
     result_box = gtk_vbox_new(FALSE, 3);
 
@@ -624,6 +627,11 @@ ui_add_result(const char *equation, const char *result)
     gtk_box_pack_start(GTK_BOX(X.history_vbox), result_box, FALSE, TRUE, 0);
     
     gtk_widget_show_all(result_box);
+    
+    while(gtk_events_pending())
+        gtk_main_iteration();
+    adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(X.history_scroll));
+    gtk_adjustment_set_value(adjustment, gtk_adjustment_get_upper(adjustment) - gtk_adjustment_get_page_size(adjustment));
 }
 
 
@@ -1449,6 +1457,45 @@ menu_pos_func(GtkMenu *menu, gint *x, gint *y,
 }
 
 
+static void
+insert(const char *text)
+{
+    GtkTextIter start, end;
+    if(gtk_text_buffer_get_selection_bounds(X.equation_buffer, &start, &end))
+        display_insert(&v->display, gtk_text_iter_get_offset(&start), gtk_text_iter_get_offset(&end), text);
+    else
+        display_insert(&v->display, get_cursor(), get_cursor(), text);        
+}
+
+
+static void
+backspace()
+{
+    GtkTextIter start, end;
+    if(gtk_text_buffer_get_selection_bounds(X.equation_buffer, &start, &end)) {
+        display_insert(&v->display, gtk_text_iter_get_offset(&start), gtk_text_iter_get_offset(&end), "");
+    }
+    else {
+        display_set_cursor(&v->display, get_cursor()); // FIXME: set_cursor may now be obsolete
+        display_backspace(&v->display);
+    }
+}
+
+
+static void
+delete()
+{
+    GtkTextIter start, end;
+    if(gtk_text_buffer_get_selection_bounds(X.equation_buffer, &start, &end)) {
+        display_insert(&v->display, gtk_text_iter_get_offset(&start), gtk_text_iter_get_offset(&end), "");
+    }
+    else {
+        display_set_cursor(&v->display, get_cursor()); // FIXME: set_cursor may now be obsolete
+        display_delete(&v->display);
+    }
+}
+
+
 G_MODULE_EXPORT
 void
 button_cb(GtkWidget *widget)
@@ -1456,7 +1503,7 @@ button_cb(GtkWidget *widget)
     const gchar *text;
     
     text = (const gchar *)g_object_get_data(G_OBJECT(widget), "equation_text");
-    display_insert(&v->display, get_cursor(), text);
+    insert(text);
 }
 
 
@@ -1465,7 +1512,7 @@ void
 inverse_cb(GtkWidget *widget)
 {
     // FIXME: Do in display.c - invert sine operations
-    display_insert(&v->display, get_cursor(), "^-1");
+    insert("^-1");
 }
 
 
@@ -1738,9 +1785,7 @@ G_MODULE_EXPORT
 gboolean
 equation_entry_key_press_event_cb(GtkWidget *widget, GdkEventKey *event)
 {
-    printf("!!!%d %d '%s'\n", event->state, event->keyval, event->string);
-    
-    //Make display convert 2â??=2, 3â??=â?? 4â??=â??
+    //Make display convert _2â??=2, _3â??=â?? _4â??=â??
     //Make display trim multiple spaces
     //Make display not allow spaces at start of equation
     //Make display convert "sin (" to "sin("
@@ -1765,13 +1810,13 @@ equation_entry_key_press_event_cb(GtkWidget *widget, GdkEventKey *event)
         else if(strcmp(event->string, "u") == 0)
             text = "µ"; // FIXME: Do inside display_insert when connected to a number
 
-        display_insert(&v->display, get_cursor(), text);
+        insert(text);
         return TRUE;
     }
     
     if(event->keyval == GDK_r && (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK)
     {
-        display_insert(&v->display, get_cursor(), "â??");
+        insert("â??");
         return TRUE;
     }
     
@@ -1785,10 +1830,8 @@ equation_entry_key_press_event_cb(GtkWidget *widget, GdkEventKey *event)
     case GDK_BackSpace:
         if(event->state & GDK_CONTROL_MASK)
             display_clear(&v->display);
-        else
-        {
-            display_set_cursor(&v->display, get_cursor());
-            display_backspace(&v->display);
+        else {
+            backspace();
         }
         return TRUE;
     case GDK_Escape:
@@ -1872,6 +1915,7 @@ create_main_window()
     X.equation_view    = GET_WIDGET("equation_entry");
     X.equation_buffer  = gtk_text_view_get_buffer(GTK_TEXT_VIEW(X.equation_view));
     X.history_vbox     = GET_WIDGET("history_vbox");
+    X.history_scroll   = GET_WIDGET("history_scroll");
     X.bas_panel        = GET_WIDGET("core_panel");
     X.prog_panel       = GET_WIDGET("programming_panel");
     X.fin_panel        = GET_WIDGET("financial_panel");
diff --git a/src/mp-convert.c b/src/mp-convert.c
index d0e9cf4..1b8aacf 100644
--- a/src/mp-convert.c
+++ b/src/mp-convert.c
@@ -621,6 +621,10 @@ mp_set_from_string(const char *str, int base, MPNumber *MPval)
         negate = 1;
         optr++;
     }
+    else if (strncmp(optr, "â??", strlen("â??")) == 0) {
+        negate = 1;
+        optr += strlen("â??");
+    }
 
     /* Convert integer part */
     mp_set_from_integer(0, MPval);
diff --git a/src/mp-equation-lexer.l b/src/mp-equation-lexer.l
index 6bc7971..0938973 100644
--- a/src/mp-equation-lexer.l
+++ b/src/mp-equation-lexer.l
@@ -38,7 +38,7 @@
 %}
 
 DECIMAL	"."|","
-SIGN	"+"|"-" 
+SIGN	"+"|"-"|"â??"
 CHARACTER [a-z]|[A-Z]
 BIN     [0-1]
 OCT     [0-7]
@@ -52,7 +52,12 @@ BIN_NUM{BIN}+|{BIN}*{DECIMAL}{BIN}*
 
 %%
 
-"abs"|"Abs"|"ABS" {return tABS;}
+"+" {return tADD;}
+"-"|"â??" {return tSUBTRACT;}
+"*"|"Ã?" {return tMULTIPLY;}
+"/"|"÷" {return tDIVIDE;}
+"abs"|"Abs"|"ABS" {return tABS_FUNC;}
+"|" {return tABS;}
 "acosh"|"Acosh"|"ACOSH" {return tACOSH;}
 "acos"|"Acos"|"ACOS" {return tACOS;}
 "and"|"And"|"AND" {return tAND;}
@@ -81,6 +86,9 @@ BIN_NUM{BIN}+|{BIN}*{DECIMAL}{BIN}*
 "sinh"|"Sinh"|"SINH" {return tSINH;}
 "sin"|"Sin"|"SIN" {return tSIN;}
 "sqrt"|"Sqrt"|"SQRT" {return tSQRT;}
+"â??" {return tROOT;}
+"â??" {return tROOT3;}
+"â??" {return tROOT4;}
 "sto"|"Sto"|"STO" {return tSTO;}
 "tanh"|"Tanh"|"TANH" {return tTANH;}
 "tan"|"Tan"|"TAN" {return tTAN;}
diff --git a/src/mp-equation-parser.y b/src/mp-equation-parser.y
index 8f62e21..937ad95 100644
--- a/src/mp-equation-parser.y
+++ b/src/mp-equation-parser.y
@@ -43,7 +43,14 @@
   int integer;
 }
 
+//FIXME:%token tPOSITIVE
+//FIXME:%token tNEGATIVE
+%token tADD
+%token tSUBTRACT
+%token tMULTIPLY
+%token tDIVIDE
 %token tABS
+%token tABS_FUNC
 %token tACOS
 %token tACOSH
 %token tAND
@@ -73,6 +80,9 @@
 %token tRCL
 %token tSIN
 %token tSINH
+%token tROOT
+%token tROOT3
+%token tROOT4
 %token tSQRT
 %token tSTO
 %token tTAN
@@ -89,8 +99,8 @@
 %type  <int_t> exp rcl value term reg func number parenthesis
 
 %start statement
-%left '+' '-'
-%left '*' '/'
+%left tADD tSUBTRACT
+%left tMULTIPLY tDIVIDE
 %left MED
 %left LNEG
 %left NEG
@@ -140,9 +150,13 @@ value:
 
 exp: 
   term {mp_set_from_mp(&$1, &$$);}
+  
+| exp tROOT exp {MPNumber t; mp_sqrt(&$3, &t); mp_multiply(&$1, &t, &$$);}
+| exp tROOT3 exp {MPNumber t; mp_root(&$3, 3, &t); mp_multiply(&$1, &t, &$$);}
+| exp tROOT4 exp {MPNumber t; mp_root(&$3, 4, &t); mp_multiply(&$1, &t, &$$);}
 
-| exp '+' exp {mp_add(&$1, &$3, &$$);}
-| exp '-' exp {mp_subtract(&$1, &$3, &$$);}
+| 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)) {
@@ -184,8 +198,12 @@ exp:
 term:
   number {mp_set_from_mp(&$1, &$$);}
 | rcl {mp_set_from_mp(&$1, &$$);}
-| term '/' term {mp_divide(&$1, &$3, &$$);}
-| term '*' term {mp_multiply(&$1, &$3, &$$);}
+| tROOT exp {mp_sqrt(&$2, &$$);}
+| tROOT3 exp {mp_root(&$2, 3, &$$);}
+| tROOT4 exp {mp_root(&$2, 4, &$$);}
+| term tDIVIDE term {mp_divide(&$1, &$3, &$$);}
+| term tMULTIPLY term {mp_multiply(&$1, &$3, &$$);}
+| tABS term tABS {mp_abs(&$2, &$$);} 
 | 'e' '^' term {mp_epowy(&$3, &$$);} 
 | term '!' {mp_factorial(&$1, &$$);}
 | term '%' {mp_divide_integer(&$1, 100, &$$);}
@@ -197,8 +215,8 @@ term:
     }
     mp_not(&$2, _mp_equation_get_extra(yyscanner)->wordlen, &$$);
 }
-| '-' term %prec NEG {mp_invert_sign(&$2, &$$);}
-| '+' term %prec POS {mp_set_from_mp(&$2, &$$);}
+| tSUBTRACT term %prec NEG {mp_invert_sign(&$2, &$$);}
+| tADD term %prec POS {mp_set_from_mp(&$2, &$$);}
 | term '^' term {mp_xpowy(&$1, &$3, &$$);}
 
 | func {mp_set_from_mp(&$1, &$$);}
@@ -221,7 +239,7 @@ func:
 | tSQRT term %prec HIGH {mp_sqrt(&$2, &$$);}
 | tLN term %prec HIGH {mp_ln(&$2, &$$);}
 | tRAND %prec HIGH {mp_set_from_random(&$$);}
-| tABS term %prec HIGH {mp_abs(&$2, &$$);}
+| 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, &$$);}
diff --git a/src/unittest.c b/src/unittest.c
index 8052a0f..ccf3621 100644
--- a/src/unittest.c
+++ b/src/unittest.c
@@ -118,12 +118,14 @@ test_parser()
     test("4+1", "5", 0);
     test("40000+0.001", "40000.001", 0);
     test("0.001+40000", "40000.001", 0);
+    test("2â??3", "-1", 0);
     test("2-3", "-1", 0);
     test("3-2", "1", 0);
     test("1-0.9-0.1", "0", 0);   
     test("40000-0.001", "39999.999", 0);
     test("0.001-40000", "-39999.999", 0);
     test("40000000-40000000", "0", 0);
+    test("2Ã?3", "6", 0);
     test("2*3", "6", 0);
     test("-2*3", "-6", 0);
     test("2*-3", "-6", 0);
@@ -131,6 +133,7 @@ test_parser()
     //FIXME: Need to update mperr() test("1/2", "0.5", 0);
     //FIXME: Need to update mperr() test("1/0", "", 0);
     //FIXME: Need to update mperr() test("0/0", "", 0);
+    test("6÷3", "2", 0);
     test("6/3", "2", 0);
     test("-6/3", "-2", 0);
     test("6/-3", "-2", 0);
@@ -169,6 +172,12 @@ test_parser()
     test("4^3^2", "262144", 0);
     test("4^(3^2)", "262144", 0);    
     test("(4^3)^2", "4096", 0);
+    test("â??4", "2", 0);
+    test("â??8", "2", 0);
+    test("â??16", "2", 0);
+    test("â??(2+2)", "2", 0);
+    test("2â??4", "4", 0);
+    test("2*â??4", "4", 0);
     test("Sqrt(4)", "2", 0);
     test("Sqrt(2)", "1.414213562", 0);
     test("4^(1/2)", "2", 0);
@@ -187,6 +196,8 @@ test_parser()
     test("Int(-3.2)", "-3", 0);
     test("Frac(-3.2)", "-0.2", 0);
 
+    test("|1|", "1", 0);
+    test("|-1|", "1", 0);    
     test("Abs(1)", "1", 0);
     test("Abs(-1)", "1", 0);
     



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