gcalctool r2094 - trunk/gcalctool
- From: rancell svn gnome org
- To: svn-commits-list gnome org
- Subject: gcalctool r2094 - trunk/gcalctool
- Date: Sat, 17 May 2008 04:08:32 +0100 (BST)
Author: rancell
Date: Sat May 17 03:08:32 2008
New Revision: 2094
URL: http://svn.gnome.org/viewvc/gcalctool?rev=2094&view=rev
Log:
Moved all display code into display.[ch]
Modified:
trunk/gcalctool/calctool.c
trunk/gcalctool/calctool.h
trunk/gcalctool/ce_parser.c
trunk/gcalctool/display.c
trunk/gcalctool/display.h
trunk/gcalctool/functions.c
trunk/gcalctool/functions.h
trunk/gcalctool/get.c
trunk/gcalctool/gtk.c
trunk/gcalctool/lr_parser.c
trunk/gcalctool/lr_tokeniser.l
trunk/gcalctool/mp.c
trunk/gcalctool/mpmath.c
trunk/gcalctool/mpmath.h
trunk/gcalctool/ui.h
trunk/gcalctool/unittest.c
Modified: trunk/gcalctool/calctool.c
==============================================================================
--- trunk/gcalctool/calctool.c (original)
+++ trunk/gcalctool/calctool.c Sat May 17 03:08:32 2008
@@ -31,6 +31,7 @@
#include "display.h"
#include "functions.h"
#include "ui.h"
+#include "mpmath.h"
time_t time();
@@ -715,8 +716,6 @@
for (i = 0; i < MAX_REGISTERS; i++) {
mpcim(&n, v->MPmvals[i]);
}
-
- exp_clear();
}
@@ -724,7 +723,6 @@
main(int argc, char **argv)
{
char *ptr;
- struct exprm_state *e;
v = (Vars) LINT_CAST(calloc(1, sizeof(struct calcVars)));
@@ -739,31 +737,26 @@
v->appname = strdup(argv[0]);
}
+ srand48((long) time((time_t *) 0)); /* Seed random number generator. */
+
+ v->radix = get_radix(); /* Locale specific radix string. */
+ v->tsep = get_tsep(); /* Locale specific thousands separator. */
+ v->tsep_count = get_tsep_count();
+
init_state();
get_options(argc, argv); /* Get command line arguments. */
ui_init(&argc, &argv); /* Initialise UI */
resources_init(); /* Initialise configuration */
-
- v->radix = get_radix(); /* Locale specific radix string. */
- v->tsep = get_tsep(); /* Locale specific thousands separator. */
- v->tsep_count = get_tsep_count();
+ display_init();
init_text(); /* Setup text strings depending upon language. */
read_resources(); /* Read resources from merged database. */
ui_load();
- srand48((long) time((time_t *) 0)); /* Seed random number generator. */
-
do_clear(); /* Initialise and clear display. */
- display_set_number(v->MPdisp_val); /* Output in correct display mode. */
-
- memset(&(v->h), 0, sizeof(struct exprm_state_history)); /* clear expression mode state history*/
- e = get_state();
- e->clear = 1; /* Clear initial state as if clear was pressed */
-
- ui_start(); /* Display the calculator. */
+ ui_start(); /* Display the calculator. */
return(0);
}
Modified: trunk/gcalctool/calctool.h
==============================================================================
--- trunk/gcalctool/calctool.h (original)
+++ trunk/gcalctool/calctool.h Sat May 17 03:08:32 2008
@@ -184,7 +184,6 @@
int ans[MP_SIZE]; /* Previously calculated answer */
char *expression; /* Expression entered by user */
int cursor;
- int clear; /* Clear command issued */
};
/* Circular list of Arithmetic Precedence Mode states*/
Modified: trunk/gcalctool/ce_parser.c
==============================================================================
--- trunk/gcalctool/ce_parser.c (original)
+++ trunk/gcalctool/ce_parser.c Sat May 17 03:08:32 2008
@@ -22,7 +22,6 @@
#include "ce_parser.h"
#include "limits.h"
#include "calctool.h"
-#include "functions.h" /* FIXME: Needed for gc_strdup() */
/* TODO: This file is almost identical to lr-parser. */
@@ -39,7 +38,7 @@
if (strlen(expression)) {
parser_state.i = 0;
- parser_state.buff = gc_strdup(expression);
+ parser_state.buff = strdup(expression);
v->math_error = 0;
ret = ceparse();
free(parser_state.buff);
Modified: trunk/gcalctool/display.c
==============================================================================
--- trunk/gcalctool/display.c (original)
+++ trunk/gcalctool/display.c Sat May 17 03:08:32 2008
@@ -25,19 +25,57 @@
#include "display.h"
-#include "mp.h"
#include "mpmath.h"
#include "functions.h"
#include "ui.h"
+#include "ce_parser.h" // For ce_parse()
-static char digits[] = "0123456789ABCDEF";
+static gboolean
+exp_has_postfix(char *str, char *postfix)
+{
+ int len, plen;
+
+ if (!str) {
+ return FALSE;
+ }
+
+ assert(postfix);
+
+ len = strlen(str);
+ plen = strlen(postfix);
+
+ if (plen > len) {
+ return FALSE;
+ }
+
+ return strcasecmp(str + len - plen, postfix) == 0;
+}
+
+static char *
+str_replace(char *str, char *from, char *to)
+{
+ char output[MAXLINE];
+ int offset = 0;
+ char *c;
+ int flen = strlen(from);
+ int tlen = strlen(to);
+
+ for (c = str; *c && offset < MAXLINE - 1; c++, offset++) {
+ if (strncasecmp(from, c, flen) == 0) {
+ SNPRINTF(output + offset, MAXLINE - offset, to);
+ c += flen - 1;
+ offset += tlen - 1;
+ } else {
+ output[offset] = *c;
+ }
+ }
-static double max_fix[MAXBASES] = {
- 1.298074214e+33, /* Binary. */
- 2.037035976e+90, /* Octal. */
- 1.000000000e+100, /* Decimal */
- 2.582249878e+120 /* Hexadecimal. */
-};
+ if (offset >= MAXLINE)
+ offset = MAXLINE - 1;
+ output[offset] = '\0';
+
+ return strdup(output);
+}
/* Add in the thousand separators characters if required and if we are
* currently in the decimal numeric base, use the "right" radix character.
@@ -135,33 +173,29 @@
}
-static int
-char_val(char chr)
-{
- if (chr >= '0' && chr <= '9') {
- return(chr - '0');
- } else if (chr >= 'a' && chr <= 'f') {
- return(chr - 'a' + 10);
- } else if (chr >= 'A' && chr <= 'F') {
- return(chr - 'A' + 10);
- } else {
- return(-1);
- }
-}
-
-
void
display_clear(int initialise)
{
- v->ltr.pointed = 0;
- v->ltr.toclear = 1;
- do_zero(v->MPdisp_val);
- display_set_number(v->MPdisp_val);
-
- if (initialise == TRUE) {
- v->ltr.noparens = 0;
- ui_set_hyperbolic_state(FALSE); /* Also clears v->hyperbolic. */
- ui_set_inverse_state(FALSE); /* Also clears v->inverse. */
+ switch(v->syntax) {
+ case NPA:
+ v->ltr.pointed = 0;
+ v->ltr.toclear = 1;
+ do_zero(v->MPdisp_val);
+ display_set_number(v->MPdisp_val);
+
+ if (initialise == TRUE) {
+ v->ltr.noparens = 0;
+ ui_set_hyperbolic_state(FALSE); /* Also clears v->hyperbolic. */
+ ui_set_inverse_state(FALSE); /* Also clears v->inverse. */
+ }
+ break;
+
+ case EXPRS:
+ display_set_string("");
+ break;
+
+ default:
+ assert(0);
}
}
@@ -178,297 +212,9 @@
v->ltr.new_input = 1; /* Value zero is on calculator display */
- exp_clear();
-}
-
-
-/* Convert MP number to fixed number string in the given base to the
- * maximum number of digits specified.
- */
-
-void
-make_fixed(char *target, int target_len, int *MPnumber, int base, int cmax, int toclear)
-{
- char half[MAXLINE], *optr;
- int MP1base[MP_SIZE], MP1[MP_SIZE], MP2[MP_SIZE], MPval[MP_SIZE];
- int ndig; /* Total number of digits to generate. */
- int ddig; /* Number of digits to left of decimal sep. */
- int dval, n, i;
-
- optr = target;
- mpabs(MPnumber, MPval);
- do_zero(MP1);
- if (mplt(MPnumber, MP1)) {
- *optr++ = '-';
- }
-
- mpcim(&basevals[base], MP1base);
-
- mppwr(MP1base, &v->accuracy, MP1);
- /* FIXME: string const. if MPstr_to_num can get it */
- SNPRINTF(half, MAXLINE, "0.5");
- MPstr_to_num(half, DEC, MP2);
- mpdiv(MP2, MP1, MP1);
- mpadd(MPval, MP1, MPval);
-
- n = 1;
- mpcim(&n, MP2);
- if (mplt(MPval, MP2)) {
- ddig = 0;
- *optr++ = '0';
- cmax--;
- } else {
- for (ddig = 0; mpge(MPval, MP2); ddig++) {
- mpdiv(MPval, MP1base, MPval);
- }
- }
-
- ndig = MIN(ddig + v->accuracy, --cmax);
-
- while (ndig-- > 0) {
- if (ddig-- == 0) {
- for (i = 0; i < strlen(v->radix); i++)
- *optr++ = v->radix[i];
- }
- mpmul(MPval, MP1base, MPval);
- mpcmi(MPval, &dval);
-
- if (dval > basevals[base]-1) {
- dval = basevals[base]-1;
- }
-
- *optr++ = digits[dval];
- dval = -dval;
- mpaddi(MPval, &dval, MPval);
- }
- *optr++ = '\0';
- if (toclear == TRUE) {
- v->ltr.toclear = 1;
- }
- v->ltr.pointed = 0;
-
- /* Strip off trailing zeroes */
- if (!v->show_zeroes) {
- for (i = strlen(target) - 1; i > 1 && target[i] == '0'; i--) {
- target[i] = '\0';
- }
-
- /* If no fractional part discard radix */
- if (strlen(target) >= strlen(v->radix) && strcmp(target + strlen(target) - strlen(v->radix), v->radix) == 0) {
- target[strlen(target) - strlen(v->radix)] = '\0';
- }
- }
+ display_clear(TRUE);
}
-
-/* Convert engineering or scientific number in the given base. */
-
-void
-make_eng_sci(char *target, int target_len, int *MPnumber, int base)
-{
- char half[MAXLINE], fixed[MAX_DIGITS], *optr;
- int MP1[MP_SIZE], MPatmp[MP_SIZE], MPval[MP_SIZE];
- int MP1base[MP_SIZE], MP3base[MP_SIZE], MP10base[MP_SIZE];
- int i, dval, len, n;
- int MPmant[MP_SIZE]; /* Mantissa. */
- int ddig; /* Number of digits in exponent. */
- int eng = 0; /* Set if this is an engineering number. */
- int exp = 0; /* Exponent */
-
- if (v->dtype == ENG) {
- eng = 1;
- }
- optr = target;
- mpabs(MPnumber, MPval);
- do_zero(MP1);
- if (mplt(MPnumber, MP1)) {
- *optr++ = '-';
- }
- mpstr(MPval, MPmant);
-
- mpcim(&basevals[base], MP1base);
- n = 3;
- mppwr(MP1base, &n, MP3base);
-
- n = 10;
- mppwr(MP1base, &n, MP10base);
-
- n = 1;
- mpcim(&n, MP1);
- mpdiv(MP1, MP10base, MPatmp);
-
- do_zero(MP1);
- if (!mpeq(MPmant, MP1)) {
- while (!eng && mpge(MPmant, MP10base)) {
- exp += 10;
- mpmul(MPmant, MPatmp, MPmant);
- }
-
- while ((!eng && mpge(MPmant, MP1base)) ||
- (eng && (mpge(MPmant, MP3base) || exp % 3 != 0))) {
- exp += 1;
- mpdiv(MPmant, MP1base, MPmant);
- }
-
- while (!eng && mplt(MPmant, MPatmp)) {
- exp -= 10;
- mpmul(MPmant, MP10base, MPmant);
- }
-
- n = 1;
- mpcim(&n, MP1);
- while (mplt(MPmant, MP1) || (eng && exp % 3 != 0)) {
- exp -= 1;
- mpmul(MPmant, MP1base, MPmant);
- }
- }
-
- make_fixed(fixed, MAX_DIGITS, MPmant, base, MAX_DIGITS-6, TRUE);
- len = strlen(fixed);
- for (i = 0; i < len; i++) {
- *optr++ = fixed[i];
- }
-
- *optr++ = 'e';
-
- if (exp < 0) {
- exp = -exp;
- *optr++ = '-';
- } else {
- *optr++ = '+';
- }
-
- SNPRINTF(half, MAXLINE, "0.5");
- MPstr_to_num(half, DEC, MP1);
- mpaddi(MP1, &exp, MPval);
- n = 1;
- mpcim(&n, MP1);
- for (ddig = 0; mpge(MPval, MP1); ddig++) {
- mpdiv(MPval, MP1base, MPval);
- }
-
- if (ddig == 0) {
- *optr++ = '0';
- }
-
- while (ddig-- > 0) {
- mpmul(MPval, MP1base, MPval);
- mpcmi(MPval, &dval);
- *optr++ = digits[dval];
- dval = -dval;
- mpaddi(MPval, &dval, MPval);
- }
- *optr++ = '\0';
- v->ltr.toclear = 1;
- v->ltr.pointed = 0;
-}
-
-
-/* Convert MP number to character string in the given base. */
-
-void
-make_number(char *target, int target_len, int *MPnumber, int base, int ignoreError)
-{
- double number, val;
-
-/* NOTE: make_number can currently set v->error when converting to a double.
- * This is to provide the same look&feel as V3 even though gcalctool
- * now does internal arithmetic to "infinite" precision.
- *
- * XXX: Needs to be improved. Shouldn't need to convert to a double in
- * order to do these tests.
- */
-
- mpcmd(MPnumber, &number);
- val = fabs(number);
- if (v->error && !ignoreError) {
- STRNCPY(target, _("Error"), target_len - 1);
- return;
- }
- if ((v->dtype == ENG) ||
- (v->dtype == SCI) ||
- (v->dtype == FIX && val != 0.0 && (val > max_fix[base]))) {
- make_eng_sci(target, target_len, MPnumber, base);
- } else {
- make_fixed(target, target_len, MPnumber, base, MAX_DIGITS, TRUE);
- }
-}
-
-
-/* Convert string into an MP number, in the given base
- */
-
-void
-MPstr_to_num(char *str, enum base_type base, int *MPval)
-{
- char *optr;
- int MP1[MP_SIZE], MP2[MP_SIZE], MPbase[MP_SIZE];
- int i, inum;
- int exp = 0;
- int exp_sign = 1;
- int negate = 0;
- char *lnp = ui_get_localized_numeric_point();
- assert(lnp);
-
- do_zero(MPval);
- mpcim(&basevals[(int) base], MPbase);
-
- optr = str;
-
- /* Remove any initial spaces or tabs. */
- while (*optr == ' ' || *optr == '\t') {
- optr++;
- }
-
- /* Check if this is a negative number. */
- if (*optr == '-') {
- negate = 1;
- optr++;
- }
-
- while ((inum = char_val(*optr)) >= 0) {
- mpmul(MPval, MPbase, MPval);
- mpaddi(MPval, &inum, MPval);
- optr++;
- }
-
- if (*optr == '.' || *optr == *lnp) {
- optr++;
- for (i = 1; (inum = char_val(*optr)) >= 0; i++) {
- mppwr(MPbase, &i, MP1);
- mpcim(&inum, MP2);
- mpdiv(MP2, MP1, MP1);
- mpadd(MPval, MP1, MPval);
- optr++;
- }
- }
-
- while (*optr == ' ') {
- optr++;
- }
-
- if (*optr != '\0') {
- if (*optr == '-') {
- exp_sign = -1;
- }
-
- while ((inum = char_val(*++optr)) >= 0) {
- exp = exp * basevals[(int) base] + inum;
- }
- }
- exp *= exp_sign;
-
- if (v->ltr.key_exp) {
- mppwr(MPbase, &exp, MP1);
- mpmul(MPval, MP1, MPval);
- }
-
- if (negate == 1) {
- mpneg(MPval, MPval);
- }
-}
-
-
/* Append the latest parenthesis char to the display item. */
void
@@ -554,9 +300,208 @@
void
display_set_string(char *value)
{
- if(value != v->display)
- STRNCPY(value, v->display, MAX_DIGITS - 1);
- ui_set_display(v->display, -1);
+ struct exprm_state *e;
+
+ switch(v->syntax) {
+ case NPA:
+ if(value != v->display)
+ STRNCPY(value, v->display, MAX_DIGITS - 1);
+ ui_set_display(v->display, -1);
+ break;
+
+ case EXPRS:
+ e = get_state();
+ free(e->expression);
+ e->expression = strdup(value);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
+void
+display_set_error(const char *message)
+{
+ ui_set_statusbar(message, "gtk-dialog-error");
+}
+
+static void
+copy_state(struct exprm_state *dst, struct exprm_state *src)
+{
+ MEMCPY(dst, src, sizeof(struct exprm_state));
+ dst->expression = strdup(src->expression);
+}
+
+static void
+update_undo_redo_button_sensitivity(void)
+{
+ int undo = 0;
+ int redo = 0;
+
+ if (v->h.current != v->h.end) {
+ redo = 1;
+ }
+
+ if (v->h.current != v->h.begin) {
+ undo = 1;
+ }
+
+ ui_set_undo_enabled(undo, redo);
+}
+
+void display_clear_stack(void)
+{
+ int i = v->h.begin;
+ while (i != v->h.end) {
+ if (i != v->h.current) {
+ free(v->h.e[i].expression);
+ v->h.e[i].expression = NULL;
+ }
+ i = ((i + 1) % UNDO_HISTORY_LENGTH);
+ }
+ v->h.begin = v->h.end = v->h.current;
+ update_undo_redo_button_sensitivity();
+}
+
+void display_push(void)
+{
+ int c;
+
+ if (v->h.current != v->h.end) {
+ int i = v->h.current;
+
+ do {
+ i = ((i + 1) % UNDO_HISTORY_LENGTH);
+ free(v->h.e[i].expression);
+ v->h.e[i].expression = strdup("Ans");
+ } while (i != v->h.end);
+ }
+
+ v->h.end = v->h.current;
+
+ c = v->h.current;
+ v->h.end = v->h.current = ((v->h.current + 1) % UNDO_HISTORY_LENGTH);
+ if (v->h.current == v->h.begin) {
+ free(v->h.e[v->h.begin].expression);
+ v->h.e[v->h.begin].expression = NULL;
+ v->h.begin = ((v->h.begin + 1) % UNDO_HISTORY_LENGTH);
+ }
+
+ copy_state(&(v->h.e[v->h.current]), &(v->h.e[c]));
+ update_undo_redo_button_sensitivity();
+}
+
+void display_pop(void)
+{
+ struct exprm_state *e;
+
+ if (v->h.current != v->h.begin) {
+ v->h.current = ((v->h.current - 1) % UNDO_HISTORY_LENGTH);
+ ui_set_statusbar("", "");
+ } else {
+ ui_set_statusbar(_("No undo history"), "gtk-dialog-warning");
+ }
+ update_undo_redo_button_sensitivity();
+
+ e = get_state();
+ display_refresh(e->cursor);
+}
+
+void
+display_unpop(void)
+{
+ if (v->h.current != v->h.end) {
+ v->h.current = ((v->h.current + 1) % UNDO_HISTORY_LENGTH);
+ ui_set_statusbar("", "");
+ } else {
+ ui_set_statusbar(_("No redo steps"), "gtk-dialog-warning");
+ }
+ update_undo_redo_button_sensitivity();
+}
+
+int
+display_insert(const char *text, int cursor)
+{
+ char buf[MAXLINE], *display;
+ struct exprm_state *e = get_state();
+
+ if (cursor < 0) {
+ SNPRINTF(buf, MAXLINE, "%s%s", e->expression, text);
+ } else {
+ display = ui_get_display();
+ SNPRINTF(buf, MAXLINE, "%.*s%s%s", cursor, display, text, display + cursor);
+ cursor += strlen(text);
+ }
+ display_set_string(buf);
+
+ return cursor;
+}
+
+int
+display_backspace(int cursor)
+{
+ char buf[MAXLINE] = "", buf2[MAXLINE], *t;
+ struct exprm_state *e = get_state();
+ int i, MP_reg[MP_SIZE];
+
+ /* If cursor is at end of the line then delete the last character preserving accuracy */
+ if (cursor < 0) {
+ if (exp_has_postfix(e->expression, "Ans")) {
+ make_number(buf, MAXLINE, e->ans, v->base, FALSE);
+ t = str_replace(e->expression, "Ans", buf);
+ free(e->expression);
+ e->expression = t;
+ } else {
+ for (i = 0; i < 10; i++) {
+ SNPRINTF(buf, MAXLINE, "R%d", i);
+ if (exp_has_postfix(e->expression, buf)) {
+ do_rcl_reg(i, MP_reg);
+ make_number(buf2, MAXLINE, MP_reg, v->base, FALSE);
+ /* Remove "Rx" postfix and replace with backspaced number */
+ SNPRINTF(buf, MAXLINE, "%.*s%s", strlen(e->expression) - 2, e->expression - 3, buf2);
+ display_set_string(buf);
+ return cursor - 1;
+ }
+ }
+ }
+
+ SNPRINTF(buf, MAXLINE, "%.*s", strlen(e->expression) - 1, e->expression);
+ } else if (cursor > 0) {
+ t = ui_get_display();
+ SNPRINTF(buf, MAXLINE, "%.*s%s", cursor - 1, t, t + cursor);
+ } else {
+ return cursor; /* At the start of the line */
+ }
+
+ display_set_string(buf);
+ return cursor - 1;
+}
+
+int
+display_delete(int cursor)
+{
+ char buf[MAXLINE] = "", *display;
+
+ if (cursor >= 0) {
+ display = ui_get_display();
+ SNPRINTF(buf, MAXLINE, "%.*s%s", cursor, display, display + cursor + 1);
+ display_set_string(buf);
+ }
+
+ return cursor;
+}
+
+int
+display_surround(const char *prefix, const char *suffix, int cursor)
+{
+ struct exprm_state *e = get_state();
+ char buffer[MAXLINE];
+
+ SNPRINTF(buffer, MAXLINE, "%s%s%s", prefix, e->expression, suffix);
+ display_set_string(buffer);
+
+ return cursor;
}
/* In arithmetic precedence mode this routine should be called to redraw
@@ -577,12 +522,12 @@
case EXPRS:
e = get_state();
- if (e->expression[0] == '\0') {
+ if (display_is_empty()) {
do_zero(MP_reg);
make_number(x, MAX_LOCALIZED, MP_reg, v->base, FALSE);
str = x;
} else {
- str = gc_strdup(e->expression);
+ str = strdup(e->expression);
}
/* Substitute answer register */
@@ -609,7 +554,26 @@
}
}
-gboolean display_is_result(void)
+gboolean
+display_is_empty(void)
+{
+ struct exprm_state *e;
+
+ switch (v->syntax) {
+ case NPA:
+ return v->ltr.toclear;
+
+ case EXPRS:
+ e = get_state();
+ return strcmp(e->expression, "") == 0;
+
+ default:
+ assert(FALSE);
+ }
+}
+
+gboolean
+display_is_result(void)
{
struct exprm_state *e;
@@ -634,3 +598,52 @@
return FALSE;
}
+
+gboolean
+display_is_usable_number(int MPnum[MP_SIZE])
+{
+ struct exprm_state *e = get_state();
+ if (display_is_empty()) {
+ return ce_parse("0", MPnum);
+ } else {
+ return ce_parse(e->expression, MPnum);
+ }
+}
+
+void
+display_init(void)
+{
+ int i;
+
+ memset(&(v->h), 0, sizeof(struct exprm_state_history)); /* clear expression mode state history */
+ for (i = 0; i < UNDO_HISTORY_LENGTH; i++)
+ v->h.e[i].expression = strdup("");
+}
+
+int
+display_solve(int *result)
+{
+ struct exprm_state *e;
+ char *c;
+ GString *clean;
+ int errorCode;
+
+ e = get_state();
+
+ /* Remove thousands separators and use english radix */
+ clean = g_string_sized_new(strlen(e->expression));
+ for (c = e->expression; *c; c++) {
+ if (strncmp(c, v->tsep, strlen(v->tsep)) == 0) {
+ c += strlen(v->tsep) - 1;
+ } else if (strncmp(c, v->radix, strlen(v->radix)) == 0) {
+ g_string_append_c(clean, '.');
+ c += strlen(v->radix) - 1;
+ } else {
+ g_string_append_c(clean, *c);
+ }
+ }
+ errorCode = ce_parse(clean->str, result);
+ g_string_free(clean, TRUE);
+
+ return errorCode;
+}
Modified: trunk/gcalctool/display.h
==============================================================================
--- trunk/gcalctool/display.h (original)
+++ trunk/gcalctool/display.h Sat May 17 03:08:32 2008
@@ -24,17 +24,31 @@
#include "calctool.h"
-void display_reset();
+void display_init(void);
+
+void display_reset(void);
void localize_expression(char *, const char *, int, int *);
void display_clear(int);
void paren_disp(int);
void display_refresh(int);
void display_set_number(int *);
void display_set_string(char *);
+void display_set_error(const char *);
+
+void display_clear_stack(void);
+void display_push(void);
+void display_pop(void);
+void display_unpop(void);
+
+int display_insert(const char *, int);
+int display_backspace(int cursor);
+int display_delete(int);
+int display_surround(const char *, const char *, int);
+
+gboolean display_is_empty(void);
gboolean display_is_result(void);
+gboolean display_is_usable_number(int *);
-void MPstr_to_num(char *, enum base_type, int *);
-void make_fixed(char *, int, int *, int, int, int);
-void make_number(char *, int, int *, int, int);
+int display_solve(int *);
#endif /* DISPLAY_H */
Modified: trunk/gcalctool/functions.c
==============================================================================
--- trunk/gcalctool/functions.c (original)
+++ trunk/gcalctool/functions.c Sat May 17 03:08:32 2008
@@ -36,26 +36,6 @@
#include "lr_parser.h"
#include "ui.h"
-char *
-gc_strdup(char *str)
-{
- char *dup;
- int len;
-
- if (!str) {
- return NULL;
- }
-
- len = strlen(str);
- dup = malloc(len+1);
- assert(dup);
- memset(dup, 0, len+1);
- strncpy(dup, str, len);
-
- return(dup);
-}
-
-
void
make_exp(char *number, int t[MP_SIZE])
{
@@ -67,7 +47,7 @@
int MP_b[MP_SIZE];
assert(number);
- a = gc_strdup(number);
+ a = strdup(number);
assert(a);
for (i = 0; !((a[i] == 'e') || (a[i] == 'E')); i++) {
@@ -91,37 +71,10 @@
}
-static void
-update_undo_redo_button_sensitivity(void)
-{
- int undo = 0;
- int redo = 0;
-
- if (v->h.current != v->h.end) {
- redo = 1;
- }
-
- if (v->h.current != v->h.begin) {
- undo = 1;
- }
-
- ui_set_undo_enabled(undo, redo);
-}
-
-
void
clear_undo_history(void)
{
- int i = v->h.begin;
- while (i != v->h.end) {
- if (i != v->h.current) {
- free(v->h.e[i].expression);
- v->h.e[i].expression = NULL;
- }
- i = ((i + 1) % UNDO_HISTORY_LENGTH);
- }
- v->h.begin = v->h.end = v->h.current;
- update_undo_redo_button_sensitivity();
+ display_clear_stack();
}
@@ -132,77 +85,12 @@
}
-static void
-copy_state(struct exprm_state *dst, struct exprm_state *src)
-{
- MEMCPY(dst, src, sizeof(struct exprm_state));
- dst->expression = gc_strdup(src->expression);
-}
-
-
-static void
-purge_redo_history(void)
-{
- if (v->h.current != v->h.end) {
- int i = v->h.current;
-
- do {
- i = ((i + 1) % UNDO_HISTORY_LENGTH);
- free(v->h.e[i].expression);
- v->h.e[i].expression = gc_strdup("Ans");
- } while (i != v->h.end);
- }
-
- v->h.end = v->h.current;
-}
-
-
-static void
-new_state(void)
-{
- int c;
-
- purge_redo_history();
-
- c = v->h.current;
- v->h.end = v->h.current = ((v->h.current + 1) % UNDO_HISTORY_LENGTH);
- if (v->h.current == v->h.begin) {
- free(v->h.e[v->h.begin].expression);
- v->h.e[v->h.begin].expression = NULL;
- v->h.begin = ((v->h.begin + 1) % UNDO_HISTORY_LENGTH);
- }
-
- copy_state(&(v->h.e[v->h.current]), &(v->h.e[c]));
- update_undo_redo_button_sensitivity();
-}
-
-
void
perform_undo(void)
{
- struct exprm_state *e;
-
- if (v->h.current != v->h.begin) {
- v->h.current = ((v->h.current - 1) % UNDO_HISTORY_LENGTH);
- ui_set_statusbar("", "");
- } else {
- ui_set_statusbar(_("No undo history"), "gtk-dialog-warning");
- }
- update_undo_redo_button_sensitivity();
-
- e = get_state();
- display_refresh(e->cursor);
+ display_pop();
}
-struct exprm_state *
-peek_previous_state(void)
-{
- if (v->h.current != v->h.begin) {
- return &(v->h.e[(v->h.current - 1) % UNDO_HISTORY_LENGTH]);
- } else {
- return NULL;
- }
-}
static int
is_undo_step(void)
@@ -214,13 +102,7 @@
void
perform_redo(void)
{
- if (v->h.current != v->h.end) {
- v->h.current = ((v->h.current + 1) % UNDO_HISTORY_LENGTH);
- ui_set_statusbar("", "");
- } else {
- ui_set_statusbar(_("No redo steps"), "gtk-dialog-warning");
- }
- update_undo_redo_button_sensitivity();
+ display_unpop();
}
@@ -262,198 +144,17 @@
}
-int
-exp_insert(char *text, int cursor)
-{
- char buf[MAXLINE], *display;
- struct exprm_state *e = get_state();
-
- if (cursor < 0) {
- SNPRINTF(buf, MAXLINE, "%s%s", e->expression, text);
- } else {
- display = ui_get_display();
- SNPRINTF(buf, MAXLINE, "%.*s%s%s", cursor, display, text, display + cursor);
- cursor += strlen(text);
- }
- exp_replace(buf);
-
- return cursor;
-}
-
-
-void
-exp_clear(void)
-{
- exp_replace("");
-}
-
-
-int
-usable_num(int MPnum[MP_SIZE])
-{
- struct exprm_state *e = get_state();
- if (e->expression[0] == '\0') {
- return ce_parse("0", MPnum);
- } else {
- return ce_parse(e->expression, MPnum);
- }
-}
-
-
-static int
-exp_has_postfix(char *str, char *postfix)
-{
- int len, plen;
-
- if (!str) {
- return(0);
- }
-
- assert(postfix);
-
- len = strlen(str);
- plen = strlen(postfix);
-
- if (plen > len) {
- return(0);
- }
-
- if (!strcasecmp(str + len - plen, postfix)) {
- return(1);
- } else {
- return(0);
- }
-}
-
-
-static int
-exp_backspace(int cursor)
-{
- char buf[MAXLINE] = "", buf2[MAXLINE], *t;
- struct exprm_state *e = get_state();
- int i, MP_reg[MP_SIZE];
-
- /* If cursor is at end of the line then delete the last character preserving accuracy */
- if (cursor < 0) {
- if (exp_has_postfix(e->expression, "Ans")) {
- make_number(buf, MAXLINE, e->ans, v->base, FALSE);
- t = str_replace(e->expression, "Ans", buf);
- free(e->expression);
- e->expression = t;
- } else {
- for (i = 0; i < 10; i++) {
- SNPRINTF(buf, MAXLINE, "R%d", i);
- if (exp_has_postfix(e->expression, buf)) {
- do_rcl_reg(i, MP_reg);
- make_number(buf2, MAXLINE, MP_reg, v->base, FALSE);
- /* Remove "Rx" postfix and replace with backspaced number */
- SNPRINTF(buf, MAXLINE, "%.*s%s", strlen(e->expression) - 2, e->expression - 3, buf2);
- exp_replace(buf);
- return cursor - 1;
- }
- }
- }
-
- SNPRINTF(buf, MAXLINE, "%.*s", strlen(e->expression) - 1, e->expression);
- } else if (cursor > 0) {
- t = ui_get_display();
- SNPRINTF(buf, MAXLINE, "%.*s%s", cursor - 1, t, t + cursor);
- } else {
- return cursor; /* At the start of the line */
- }
-
- exp_replace(buf);
- return cursor - 1;
-}
-
-
-static int
-exp_delete(int cursor)
-{
- char buf[MAXLINE] = "", *display;
-
- if (cursor >= 0) {
- display = ui_get_display();
- SNPRINTF(buf, MAXLINE, "%.*s%s", cursor, display, display + cursor + 1);
- exp_replace(buf);
- }
-
- return cursor;
-}
-
-
-void
-exp_replace(char *text)
-{
- struct exprm_state *e;
- e = get_state();
- if (e->expression != NULL) {
- free(e->expression);
- }
- e->expression = gc_strdup(text);
-}
-
-
static void
exp_negate(void)
{
- struct exprm_state *e = get_state();
-
- /* Ending zero + parenthesis + minus */
- int len = strlen(e->expression) + 4;
- char *exp = malloc(len);
-
- assert(exp);
- if (snprintf(exp, len, "-(%s)", e->expression) < 0) {
- assert(0);
- }
- free(e->expression);
- e->expression = exp;
+ display_surround("-(", ")", 0); // FIXME: Cursor
}
static void
exp_inv(void)
{
- struct exprm_state *e = get_state();
-
- /* Ending zero + 1/ + parenthesis */
- int len = strlen(e->expression) + 5;
- char *exp = malloc(len);
-
- assert(exp);
- if (snprintf(exp, len, "1/(%s)", e->expression) < 0) {
- assert(0);
- }
- free(e->expression);
- e->expression = exp;
-}
-
-
-char *
-str_replace(char *str, char *from, char *to)
-{
- char output[MAXLINE];
- int offset = 0;
- char *c;
- int flen = strlen(from);
- int tlen = strlen(to);
-
- for (c = str; *c && offset < MAXLINE - 1; c++, offset++) {
- if (strncasecmp(from, c, flen) == 0) {
- SNPRINTF(output + offset, MAXLINE - offset, to);
- c += flen - 1;
- offset += tlen - 1;
- } else {
- output[offset] = *c;
- }
- }
-
- if (offset >= MAXLINE)
- offset = MAXLINE - 1;
- output[offset] = '\0';
-
- return strdup(output);
+ display_surround("1/(", ")", 0); // FIXME: Cursor
}
@@ -461,29 +162,26 @@
do_expression(int function, int arg, int cursor)
{
char buf[MAXLINE];
- struct exprm_state *e, *ex;
+ struct exprm_state *e;
- new_state();
+ display_push();
e = get_state();
- ex = peek_previous_state();
e->cursor = cursor;
- e->clear = 0;
ui_set_statusbar("", "");
/* Starting a number after a calculation clears the display */
- if (strcmp(e->expression, "Ans") == 0) {
+ if (display_is_result()) {
if (buttons[function].flags & NUMBER) {
- exp_replace("");
+ display_set_string("");
}
}
switch (buttons[function].id) {
case KEY_CLEAR:
case KEY_CLEAR_ENTRY:
- e->clear = 1;
- exp_clear();
+ display_clear(FALSE);
ui_set_error_state(FALSE);
MPstr_to_num("0", DEC, e->ans);
break;
@@ -511,20 +209,20 @@
case KEY_RECALL:
SNPRINTF(buf, MAXLINE, "R%d", arg);
- cursor = exp_insert(buf, cursor);
+ cursor = display_insert(buf, cursor);
break;
case KEY_CONSTANT:
make_number(buf, MAXLINE, v->MPcon_vals[arg], v->base, FALSE);
- cursor = exp_insert(buf, cursor);
+ cursor = display_insert(buf, cursor);
break;
case KEY_BACKSPACE:
- cursor = exp_backspace(cursor);
+ cursor = display_backspace(cursor);
break;
case KEY_DELETE:
- cursor = exp_delete(cursor);
+ cursor = display_delete(cursor);
break;
case KEY_CHANGE_SIGN:
@@ -542,7 +240,7 @@
* this result */
/* TODO: Work out why two undo steps are required and why
* the cursor must be taken from the first undo */
- if (strcmp(e->expression, "Ans") == 0) {
+ if (display_is_result()) {
perform_undo();
e = get_state();
cursor = e->cursor;
@@ -551,35 +249,20 @@
}
/* Do nothing */
- } else if (e->expression[0] == '\0') {
+ } else if (display_is_empty()) {
;
/* Solve the equation */
} else {
int MPval[MP_SIZE];
- char *c, *message = NULL;
- GString *clean;
int result;
+ const char *message = NULL;
- /* Remove thousands separators and use english radix */
- clean = g_string_sized_new(strlen(e->expression));
- for (c = e->expression; *c; c++) {
- if (strncmp(c, v->tsep, strlen(v->tsep)) == 0) {
- c += strlen(v->tsep) - 1;
- } else if (strncmp(c, v->radix, strlen(v->radix)) == 0) {
- g_string_append_c(clean, '.');
- c += strlen(v->radix) - 1;
- } else {
- g_string_append_c(clean, *c);
- }
- }
- result = ce_parse(clean->str, MPval);
- g_string_free(clean, TRUE);
-
+ result = display_solve(MPval);
switch (result) {
case 0:
mpstr(MPval, e->ans);
- exp_replace("Ans");
+ display_set_string("Ans");
cursor = -1;
break;
@@ -613,33 +296,20 @@
break;
case KEY_NUMERIC_POINT:
- cursor = exp_insert(ui_get_localized_numeric_point(), cursor);
+ cursor = display_insert(v->radix, cursor);
break;
default:
/* If display is a number then perform functions on that number */
- if ((buttons[function].flags & (PREFIXOP | FUNC))
- && !strcmp(e->expression, "Ans")
- && !(ex && ex->clear)) {
- SNPRINTF(buf, MAXLINE, "%s(%s)",
- buttons[function].symname,
- e->expression);
- exp_replace(buf);
- } else if ((((buttons[function].id == KEY_ADD)
- || (buttons[function].id == KEY_SUBTRACT))
- && !strcmp(e->expression, "Ans")
- && (ex && ex->clear))) {
- exp_replace(buttons[function].symname);
+ if (buttons[function].flags & (PREFIXOP | FUNC) && display_is_result()) {
+ SNPRINTF(buf, MAXLINE, "%s(", buttons[function].symname);
+ display_surround(buf, ")", 0); // FIXME: Cursor
} else {
if (buttons[function].flags & FUNC) {
SNPRINTF(buf, MAXLINE, "%s(", buttons[function].symname);
- if (!ex || ex->clear) {
- exp_replace(buf);
- } else {
- cursor = exp_insert(buf, cursor);
- }
+ cursor = display_insert(buf, cursor);
} else {
- cursor = exp_insert(buttons[function].symname, cursor);
+ cursor = display_insert(buttons[function].symname, cursor);
}
}
break;
@@ -924,14 +594,14 @@
case EXPRS:
e = get_state();
- ret = usable_num(MP);
+ ret = display_is_usable_number(MP);
if (ret) {
ui_set_statusbar(_("No sane value to convert"),
"gtk-dialog-error");
} else {
mpstr(MP, e->ans);
- exp_replace("Ans");
+ display_set_string("Ans");
}
v->base = b;
set_resource(R_BASE, Rbstr[(int) v->base]);
@@ -1025,14 +695,14 @@
case EXPRS:
e = get_state();
- if (usable_num(MPexpr)) {
+ if (display_is_usable_number(MPexpr)) {
ui_set_statusbar(_("No sane value to store"),
"gtk-dialog-error");
} else {
mpstr(v->MPmvals[index], MPtemp);
mpstr(MPexpr, v->MPmvals[index]);
mpstr(MPtemp, e->ans);
- exp_replace("Ans");
+ display_set_string("Ans");
display_refresh(-1);
ui_make_registers();
}
@@ -1278,13 +948,13 @@
case EXPRS:
e = get_state();
- ret = usable_num(MP);
+ ret = display_is_usable_number(MP);
if (ret) {
ui_set_statusbar(_("No sane value to convert"),
"gtk-dialog-error");
} else {
mpstr(MP, e->ans);
- exp_replace("Ans");
+ display_set_string("Ans");
ui_make_registers();
}
clear_undo_history();
@@ -1352,7 +1022,7 @@
break;
case EXPRS:
- if (usable_num(v->MPmvals[index])) {
+ if (display_is_usable_number(v->MPmvals[index])) {
ui_set_statusbar(_("No sane value to store"),
"gtk-dialog-error");
}
@@ -1504,7 +1174,7 @@
case EXPRS:
e = get_state();
- if (usable_num(MPval) || !is_integer(MPval)) {
+ if (display_is_usable_number(MPval) || !is_integer(MPval)) {
ui_set_statusbar(_("No sane value to do bitwise shift"),
"gtk-dialog-error");
break;
@@ -1512,7 +1182,7 @@
calc_shift(MPval, e->ans, count);
- exp_replace("Ans");
+ display_set_string("Ans");
break;
default:
@@ -1522,10 +1192,3 @@
v->ltr.new_input = 1;
syntaxdep_show_display();
}
-
-
-void
-show_error(char *message)
-{
- ui_set_statusbar(message, "gtk-dialog-error");
-}
Modified: trunk/gcalctool/functions.h
==============================================================================
--- trunk/gcalctool/functions.h (original)
+++ trunk/gcalctool/functions.h Sat May 17 03:08:32 2008
@@ -24,16 +24,9 @@
#include "calctool.h"
-void show_error(char *);
-char *str_replace(char *, char *, char *);
void syntaxdep_show_display(void);
-char *gc_strdup(char *str);
-int usable_num(int MPnum[MP_SIZE]);
void make_exp(char *number, int t[MP_SIZE]);
-int exp_insert(char *text, int);
-void exp_replace(char *text);
-void exp_clear(void);
struct exprm_state *get_state(void);
Modified: trunk/gcalctool/get.c
==============================================================================
--- trunk/gcalctool/get.c (original)
+++ trunk/gcalctool/get.c Sat May 17 03:08:32 2008
@@ -33,8 +33,7 @@
#include <gconf/gconf-client.h>
#include "get.h"
-#include "display.h"
-#include "mp.h"
+#include "mpmath.h"
#define EQUAL(a, b) (strlen(a)==strlen(b)) & !strcmp(a, b)
Modified: trunk/gcalctool/gtk.c
==============================================================================
--- trunk/gcalctool/gtk.c (original)
+++ trunk/gcalctool/gtk.c Sat May 17 03:08:32 2008
@@ -452,9 +452,6 @@
GtkWidget *disp[MAXDISPMODES]; /* Numeric display mode. */
GtkWidget *trig[MAXTRIGMODES]; /* Trigonometric mode. */
- //FIXME: Obsolete?
- char *lnp; /* Localized numerical point (UTF8 format) */
-
char *shelf; /* PUT selection shelf contents. */
gboolean warn_change_mode; /* Should we warn user when changing modes? */
@@ -491,7 +488,7 @@
case EXPRS:
e = get_state();
MPstr_to_num("0", DEC, e->ans);
- exp_clear();
+ display_clear(FALSE);
display_set_number(e->ans);
break;
@@ -870,7 +867,7 @@
void
-ui_set_statusbar(gchar *text, const gchar *imagename)
+ui_set_statusbar(const gchar *text, const gchar *imagename)
{
GtkImage *image = GTK_IMAGE(X->status_image);
@@ -919,7 +916,7 @@
break;
case EXPRS:
- if (usable_num(MP) || !is_integer(MP)) {
+ if (display_is_usable_number(MP) || !is_integer(MP)) {
gtk_widget_set_sensitive(X->bit_panel, FALSE);
return;
}
@@ -1045,17 +1042,6 @@
}
-char *
-ui_get_localized_numeric_point(void)
-{
- const char *decimal_point;
-
- decimal_point = localeconv()->decimal_point;
-
- return (g_locale_to_utf8(decimal_point, -1, NULL, NULL, NULL));
-}
-
-
void
ui_set_base(enum base_type base)
{
@@ -1738,7 +1724,7 @@
MPstr_to_num(v->display, v->base, MP1);
break;
case EXPRS: {
- int ret = usable_num(e->ans);
+ int ret = display_is_usable_number(e->ans);
assert(!ret);
mpstr(e->ans, MP1);
}
@@ -1766,7 +1752,7 @@
break;
case EXPRS:
mpcdm(&number, e->ans);
- exp_replace("Ans");
+ display_set_string("Ans");
display_refresh(-1);
break;
default:
@@ -1913,7 +1899,7 @@
outbuf[g_unichar_to_utf8(ch, outbuf)] = '\0';
- return (strcmp(outbuf, X->lnp) == 0);
+ return (strcmp(outbuf, v->radix) == 0);
}
@@ -2202,7 +2188,7 @@
break;
case EXPRS:
- exp_insert((char *) text, get_cursor()); // FIXME: Move out of gtk.c
+ display_insert((char *) text, get_cursor()); // FIXME: Move out of gtk.c
display_refresh(-1);
break;
@@ -2865,7 +2851,6 @@
gtk_init(argc, argv);
- X->lnp = ui_get_localized_numeric_point();
X->shelf = NULL; /* No selection for shelf initially. */
gtk_rc_get_default_files();
Modified: trunk/gcalctool/lr_parser.c
==============================================================================
--- trunk/gcalctool/lr_parser.c (original)
+++ trunk/gcalctool/lr_parser.c Sat May 17 03:08:32 2008
@@ -22,7 +22,6 @@
#include "lr_parser.h"
#include "limits.h"
#include "calctool.h"
-#include "functions.h" /* FIXME: Needed for gc_strdup() */
/* TODO: This file is almost identical to ce-parser. */
@@ -39,7 +38,7 @@
if (strlen(expression)) {
parser_state.i = 0;
- parser_state.buff = gc_strdup(expression);
+ parser_state.buff = strdup(expression);
ret = lrparse();
free(parser_state.buff);
}
Modified: trunk/gcalctool/lr_tokeniser.l
==============================================================================
--- trunk/gcalctool/lr_tokeniser.l (original)
+++ trunk/gcalctool/lr_tokeniser.l Sat May 17 03:08:32 2008
@@ -27,8 +27,7 @@
#include <string.h>
#include <sys/types.h>
#include "calctool.h"
-#include "display.h"
-#include "functions.h" /* FIXME: Needed for gc_strdup() */
+#include "mpmath.h"
#include "lr_parser.h"
#include "lr_parser.tab.h"
%}
Modified: trunk/gcalctool/mp.c
==============================================================================
--- trunk/gcalctool/mp.c (original)
+++ trunk/gcalctool/mp.c Sat May 17 03:08:32 2008
@@ -40,9 +40,9 @@
#include <stdio.h>
#include "mp.h"
+#include "mpmath.h"
#include "calctool.h"
#include "display.h"
-#include "functions.h" /* FIXME: Only for show_error() */
#define C_abs(x) ((x) >= 0 ? (x) : -(x))
#define dabs(x) (double) C_abs(x)
@@ -3361,7 +3361,7 @@
else goto L70;
L10:
- show_error(_("Negative X and non-integer Y not supported"));
+ display_set_error(_("Negative X and non-integer Y not supported"));
goto L50;
/* HERE X IS ZERO, RETURN ZERO IF Y POSITIVE, OTHERWISE ERROR */
Modified: trunk/gcalctool/mpmath.c
==============================================================================
--- trunk/gcalctool/mpmath.c (original)
+++ trunk/gcalctool/mpmath.c Sat May 17 03:08:32 2008
@@ -21,9 +21,15 @@
#include <errno.h>
#include "mpmath.h"
-#include "mp.h"
-#include "calctool.h"
-#include "display.h" /* FIXME: Needed to MPstr_to_num() */
+
+static char digits[] = "0123456789ABCDEF";
+
+static double max_fix[MAXBASES] = {
+ 1.298074214e+33, /* Binary. */
+ 2.037035976e+90, /* Octal. */
+ 1.000000000e+100, /* Decimal */
+ 2.582249878e+120 /* Hexadecimal. */
+};
BOOLEAN
ibool(double x)
@@ -784,7 +790,7 @@
{
int MP1[MP_SIZE];
if (!is_integer(MPnum)) {
- return 0;
+ return 0;
}
mpabs(MPnum, MP1);
return mpeq(MPnum, MP1);
@@ -862,3 +868,303 @@
return(0);
}
+
+/* Convert MP number to fixed number string in the given base to the
+ * maximum number of digits specified.
+ */
+
+void
+make_fixed(char *target, int target_len, int *MPnumber, int base, int cmax, int toclear)
+{
+ char half[MAXLINE], *optr;
+ int MP1base[MP_SIZE], MP1[MP_SIZE], MP2[MP_SIZE], MPval[MP_SIZE];
+ int ndig; /* Total number of digits to generate. */
+ int ddig; /* Number of digits to left of decimal sep. */
+ int dval, n, i;
+
+ optr = target;
+ mpabs(MPnumber, MPval);
+ do_zero(MP1);
+ if (mplt(MPnumber, MP1)) {
+ *optr++ = '-';
+ }
+
+ mpcim(&basevals[base], MP1base);
+
+ mppwr(MP1base, &v->accuracy, MP1);
+ /* FIXME: string const. if MPstr_to_num can get it */
+ SNPRINTF(half, MAXLINE, "0.5");
+ MPstr_to_num(half, DEC, MP2);
+ mpdiv(MP2, MP1, MP1);
+ mpadd(MPval, MP1, MPval);
+
+ n = 1;
+ mpcim(&n, MP2);
+ if (mplt(MPval, MP2)) {
+ ddig = 0;
+ *optr++ = '0';
+ cmax--;
+ } else {
+ for (ddig = 0; mpge(MPval, MP2); ddig++) {
+ mpdiv(MPval, MP1base, MPval);
+ }
+ }
+
+ ndig = MIN(ddig + v->accuracy, --cmax);
+
+ while (ndig-- > 0) {
+ if (ddig-- == 0) {
+ for (i = 0; i < strlen(v->radix); i++)
+ *optr++ = v->radix[i];
+ }
+ mpmul(MPval, MP1base, MPval);
+ mpcmi(MPval, &dval);
+
+ if (dval > basevals[base]-1) {
+ dval = basevals[base]-1;
+ }
+
+ *optr++ = digits[dval];
+ dval = -dval;
+ mpaddi(MPval, &dval, MPval);
+ }
+ *optr++ = '\0';
+ if (toclear == TRUE) {
+ v->ltr.toclear = 1;
+ }
+ v->ltr.pointed = 0;
+
+ /* Strip off trailing zeroes */
+ if (!v->show_zeroes) {
+ for (i = strlen(target) - 1; i > 1 && target[i] == '0'; i--) {
+ target[i] = '\0';
+ }
+
+ /* If no fractional part discard radix */
+ if (strlen(target) >= strlen(v->radix) && strcmp(target + strlen(target) - strlen(v->radix), v->radix) == 0) {
+ target[strlen(target) - strlen(v->radix)] = '\0';
+ }
+ }
+}
+
+
+/* Convert engineering or scientific number in the given base. */
+
+void
+make_eng_sci(char *target, int target_len, int *MPnumber, int base)
+{
+ char half[MAXLINE], fixed[MAX_DIGITS], *optr;
+ int MP1[MP_SIZE], MPatmp[MP_SIZE], MPval[MP_SIZE];
+ int MP1base[MP_SIZE], MP3base[MP_SIZE], MP10base[MP_SIZE];
+ int i, dval, len, n;
+ int MPmant[MP_SIZE]; /* Mantissa. */
+ int ddig; /* Number of digits in exponent. */
+ int eng = 0; /* Set if this is an engineering number. */
+ int exp = 0; /* Exponent */
+
+ if (v->dtype == ENG) {
+ eng = 1;
+ }
+ optr = target;
+ mpabs(MPnumber, MPval);
+ do_zero(MP1);
+ if (mplt(MPnumber, MP1)) {
+ *optr++ = '-';
+ }
+ mpstr(MPval, MPmant);
+
+ mpcim(&basevals[base], MP1base);
+ n = 3;
+ mppwr(MP1base, &n, MP3base);
+
+ n = 10;
+ mppwr(MP1base, &n, MP10base);
+
+ n = 1;
+ mpcim(&n, MP1);
+ mpdiv(MP1, MP10base, MPatmp);
+
+ do_zero(MP1);
+ if (!mpeq(MPmant, MP1)) {
+ while (!eng && mpge(MPmant, MP10base)) {
+ exp += 10;
+ mpmul(MPmant, MPatmp, MPmant);
+ }
+
+ while ((!eng && mpge(MPmant, MP1base)) ||
+ (eng && (mpge(MPmant, MP3base) || exp % 3 != 0))) {
+ exp += 1;
+ mpdiv(MPmant, MP1base, MPmant);
+ }
+
+ while (!eng && mplt(MPmant, MPatmp)) {
+ exp -= 10;
+ mpmul(MPmant, MP10base, MPmant);
+ }
+
+ n = 1;
+ mpcim(&n, MP1);
+ while (mplt(MPmant, MP1) || (eng && exp % 3 != 0)) {
+ exp -= 1;
+ mpmul(MPmant, MP1base, MPmant);
+ }
+ }
+
+ make_fixed(fixed, MAX_DIGITS, MPmant, base, MAX_DIGITS-6, TRUE);
+ len = strlen(fixed);
+ for (i = 0; i < len; i++) {
+ *optr++ = fixed[i];
+ }
+
+ *optr++ = 'e';
+
+ if (exp < 0) {
+ exp = -exp;
+ *optr++ = '-';
+ } else {
+ *optr++ = '+';
+ }
+
+ SNPRINTF(half, MAXLINE, "0.5");
+ MPstr_to_num(half, DEC, MP1);
+ mpaddi(MP1, &exp, MPval);
+ n = 1;
+ mpcim(&n, MP1);
+ for (ddig = 0; mpge(MPval, MP1); ddig++) {
+ mpdiv(MPval, MP1base, MPval);
+ }
+
+ if (ddig == 0) {
+ *optr++ = '0';
+ }
+
+ while (ddig-- > 0) {
+ mpmul(MPval, MP1base, MPval);
+ mpcmi(MPval, &dval);
+ *optr++ = digits[dval];
+ dval = -dval;
+ mpaddi(MPval, &dval, MPval);
+ }
+ *optr++ = '\0';
+ v->ltr.toclear = 1;
+ v->ltr.pointed = 0;
+}
+
+
+/* Convert MP number to character string in the given base. */
+
+void
+make_number(char *target, int target_len, int *MPnumber, int base, int ignoreError)
+{
+ double number, val;
+
+/* NOTE: make_number can currently set v->error when converting to a double.
+ * This is to provide the same look&feel as V3 even though gcalctool
+ * now does internal arithmetic to "infinite" precision.
+ *
+ * XXX: Needs to be improved. Shouldn't need to convert to a double in
+ * order to do these tests.
+ */
+
+ mpcmd(MPnumber, &number);
+ val = fabs(number);
+ if (v->error && !ignoreError) {
+ STRNCPY(target, _("Error"), target_len - 1);
+ return;
+ }
+ if ((v->dtype == ENG) ||
+ (v->dtype == SCI) ||
+ (v->dtype == FIX && val != 0.0 && (val > max_fix[base]))) {
+ make_eng_sci(target, target_len, MPnumber, base);
+ } else {
+ make_fixed(target, target_len, MPnumber, base, MAX_DIGITS, TRUE);
+ }
+}
+
+
+static int
+char_val(char chr)
+{
+ if (chr >= '0' && chr <= '9') {
+ return(chr - '0');
+ } else if (chr >= 'a' && chr <= 'f') {
+ return(chr - 'a' + 10);
+ } else if (chr >= 'A' && chr <= 'F') {
+ return(chr - 'A' + 10);
+ } else {
+ return(-1);
+ }
+}
+
+
+/* Convert string into an MP number, in the given base
+ */
+
+void
+MPstr_to_num(char *str, enum base_type base, int *MPval)
+{
+ char *optr;
+ int MP1[MP_SIZE], MP2[MP_SIZE], MPbase[MP_SIZE];
+ int i, inum;
+ int exp = 0;
+ int exp_sign = 1;
+ int negate = 0;
+
+ do_zero(MPval);
+ mpcim(&basevals[(int) base], MPbase);
+
+ optr = str;
+
+ /* Remove any initial spaces or tabs. */
+ while (*optr == ' ' || *optr == '\t') {
+ optr++;
+ }
+
+ /* Check if this is a negative number. */
+ if (*optr == '-') {
+ negate = 1;
+ optr++;
+ }
+
+ while ((inum = char_val(*optr)) >= 0) {
+ mpmul(MPval, MPbase, MPval);
+ mpaddi(MPval, &inum, MPval);
+ optr++;
+ }
+
+ if (*optr == '.' || *optr == *v->radix) {
+ optr++;
+ for (i = 1; (inum = char_val(*optr)) >= 0; i++) {
+ mppwr(MPbase, &i, MP1);
+ mpcim(&inum, MP2);
+ mpdiv(MP2, MP1, MP1);
+ mpadd(MPval, MP1, MPval);
+ optr++;
+ }
+ }
+
+ while (*optr == ' ') {
+ optr++;
+ }
+
+ if (*optr != '\0') {
+ if (*optr == '-') {
+ exp_sign = -1;
+ }
+
+ while ((inum = char_val(*++optr)) >= 0) {
+ exp = exp * basevals[(int) base] + inum;
+ }
+ }
+ exp *= exp_sign;
+
+ if (v->ltr.key_exp) {
+ mppwr(MPbase, &exp, MP1);
+ mpmul(MPval, MP1, MPval);
+ }
+
+ if (negate == 1) {
+ mpneg(MPval, MPval);
+ }
+}
+
Modified: trunk/gcalctool/mpmath.h
==============================================================================
--- trunk/gcalctool/mpmath.h (original)
+++ trunk/gcalctool/mpmath.h Sat May 17 03:08:32 2008
@@ -23,6 +23,7 @@
#define MPMATH_H
#include "mp.h"
+#include "calctool.h"
typedef unsigned long BOOLEAN;
@@ -76,4 +77,8 @@
int
is_natural(int MPnum[MP_SIZE]);
+void MPstr_to_num(char *, enum base_type, int *);
+void make_fixed(char *, int, int *, int, int, int);
+void make_number(char *, int, int *, int, int);
+
#endif /*MPMATH_H*/
Modified: trunk/gcalctool/ui.h
==============================================================================
--- trunk/gcalctool/ui.h (original)
+++ trunk/gcalctool/ui.h Sat May 17 03:08:32 2008
@@ -48,9 +48,8 @@
void ui_set_show_trailing_zeroes(gboolean);
void ui_set_error_state(gboolean);
-void ui_set_statusbar(gchar *, const gchar *);
+void ui_set_statusbar(const gchar *, const gchar *);
void ui_beep(void);
-char *ui_get_localized_numeric_point(void);
#endif /* UI_H */
Modified: trunk/gcalctool/unittest.c
==============================================================================
--- trunk/gcalctool/unittest.c (original)
+++ trunk/gcalctool/unittest.c Sat May 17 03:08:32 2008
@@ -21,6 +21,7 @@
#include "unittest.h"
+#include "mpmath.h"
#include "display.h"
#include "functions.h"
#include "calctool.h"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]