[gcalctool/gcalctool-newui] Made parse UTF-8 aware
- From: Robert Ancell <rancell src gnome org>
- To: svn-commits-list gnome org
- Subject: [gcalctool/gcalctool-newui] Made parse UTF-8 aware
- Date: Sun, 31 May 2009 04:40:51 -0400 (EDT)
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]