/* main.c: gtk driver for dcalc Contact info: bhepple@freeshell.org http://bhepple.freeshell.org/dcalc/unix Copyright (C) 1999,2000 Bob Hepple 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 the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* $Id: main.c,v 1.15 2006/12/31 09:06:53 bhepple Exp $ */ /* With glade 0.5.11 that every time the menubar is edited, one item in every radio group is turned on and interface.c gets a gtk_check_menu_item_set_active for that item. This results in seemingly harmless but distracting runtime errors. */ /* To build: cd .../dcalc/gtk aclocal autoconf autoheader automake configure (the above may happen automagically by typing 'make') cd src make make install whew */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "interface.h" #include "support.h" #include "dcalc.h" #include "callbacks.h" #include "main.h" /* naughty global exported to callbacks.c: */ GtkWidget *main_window; GtkWidget *mem_dialog; GtkWidget *eval_dialog; GtkWidget *convert; GtkWidget *registers = NULL; GtkEntry *entryX; GtkButton *invert_button; int mem_value; int raw_mode = 0; int is_resident = 0; int insertedTextIsFromDcalc = 1; dcalc_button *l_buttons, *r_buttons; char calculatorFont[100]; char buttonFont[100]; char plusMinusFont[100]; dcalc_button sci_buttons[] = { { 0, 0, SIN, "SIN", "Sine of X (or INV)", "SIN(", "ASIN(" }, { 0, 1, COS, "COS", "Cosine of X (or INV)", "COS(", "ACOS(" }, { 0, 2, TAN, "TAN", "Tangent of X (or INV)", "TAN(", "ATAN(" }, { 0, 3, HMS, "h.ms", "Convert X to Hours.MinsSecs (or INV)", "HMS(", "HOURS(" }, { 0, 4, RTOP, "r->p", "Convert (X,Y) to polar coordinates (or INV)", "RTOP ", "PTOR " }, { 0, 5, DTOR, "d->r", "Convert degrees to radians (or INV)", "DTOR(", "RTOD(" }, { 0, 6, LOG10, "LOG", "Logarithm (base 10) (or INV)", "LOG10(", "ALOG10(" }, { 0, 7, LOGE, "LN", "Natural logarithm (base e) (or INV)", "LOGe(", "ALOGe" }, { 1, 0, SINH, "SINh", "Hyperbolic sine (or INV)", "SINH(", "ASINH(" }, { 1, 1, COSH, "COSh", "Hyperbolic cosine (or INV)", "COSH(", "ACOSH(" }, { 1, 2, TANH, "TANh", "Hyperbolic tangent (or INV)", "TANH(", "ATANH(" }, { 1, 3, NOP, " ", " ", "", "" }, { 1, 4, NOP, " ", " ", "", "" }, { 1, 5, PI, "PI", "PI", "PI ", "" }, { 1, 6, INT, "INT", "Integer part of X", "INT(", "" }, { 1, 7, FRC, "FRC", "Fractional part of X", "FRC(", "" }, { 2, 0, INV, "INV", "Invert functions", "", "" }, { 2, 1, NOP, " ", " ", "", "" }, { 2, 2, NOP, " ", " ", "", "" }, { 2, 3, NOP, " ", " ", "", "" }, { 2, 4, NOP, " ", " ", "", "" }, { 2, 5, E, "e", "Base of natural logs", " e ", "" }, { 2, 6, NOP, " ", " ", "", "" }, { 2, 7, EVAL, "Eval", "Last algebraic expression", "", "" }, { -1, -1, 0, " ", " ", "", "" } }; dcalc_button fin_buttons[] = { { 0, 0, NFIN, "n", "Number of periods (or INV)", "", "" }, { 0, 1, INTST, "i", "Interest rate in % per period (or INV)", "", "" }, { 0, 2, PVAL, "PV", "Present value (or INV)", "", "" }, { 0, 3, PMT, "PMT", "Payment (or INV)", "", "" }, { 0, 4, FVAL, "FV", "Future value (or INV)", "", "" }, { 0, 5, FCLR, "CLf", "Clear compound interest registers (5-9)", "", "" }, { 0, 6, LOG10, "LOG", "Logarithm (base 10) (or INV)", "LOG(", " 10^" }, { 0, 7, LOGE, "LN", "Natural logarithm (base e)", "LN(", " e^" }, { 1, 0, TIMES12, "x12", "X times 12", "x12 ", "/12 " }, { 1, 1, DIVIDE12, "/12", "X divided by 12", "/12 ", "x12 " }, { 1, 2, BEGIN, "B/E", "Toggle Annuity at beginning of period", "", "" }, { 1, 3, DYS, "DYS", "Days between dates", " DYS ", "" }, { 1, 4, TDY, "TDY", "Today's date", " TDY ", "" }, { 1, 5, PI, "PI", "PI", "PI ", "" }, { 1, 6, INT, "INT", "Integer part of X", "INT(", "" }, { 1, 7, FRC, "FRC", "Fractional part of X", "FRC(", "" }, { 2, 0, INV, "INV", "Invert functions", "", "" }, { 2, 1, NOP, " ", " ", "", "" }, { 2, 2, NOP, " ", " ", "", "" }, { 2, 3, NOP, " ", " ", "", "" }, { 2, 4, NOP, " ", " ", "", "" }, { 2, 5, E, "e", "Base of natural logs", " e ", "" }, { 2, 6, NOP, " ", " ", "", "" }, { 2, 7, EVAL, "Eval", "Last algebraic expression", "", "" }, { -1, -1, 0, " ", " ", "", "" } }; dcalc_button stat_buttons[] = { { 0, 0, SUM, "SUM+", "Add X to the accumulator (register 7)", "", "" }, { 0, 1, MEAN, "m(X)", "Calculate the mean of X", "", "" }, { 0, 2, MEANY, "m(Y)", "Calculate the mean of Y", "", "" }, { 0, 3, S_DEV, "StdD", "Calculate the standard deviations", "", "" }, { 0, 4, NSTAT, "N", "Number of samples", "", "" }, { 0, 5, FACT, "x!", "X factorial", "!", "" }, { 0, 6, LOG10, "LOG", "Logarithm (base 10)", "LOG(", " 10^" }, { 0, 7, LOGE, "LN", "Natural logarithm (base e)", "LN(", " e^" }, { 1, 0, SUMR, "SUM-", "subtract X from the accumulator (register 7)", "", "" }, { 1, 1, PERM, "yPx", "x permutations of y", "yPx ", "" }, { 1, 2, COMB, "yCx", "x combinations of y", "yCx ", "" }, { 1, 3, LR, "LR", "Linear Regression", "LR", "" }, { 1, 4, CALCY, "f(x)", "Calculate Y from X using linear regression results (Inv: calculate X from Y)", "Fx(", "" }, { 1, 5, PI, "PI", "PI", "PI ", "" }, { 1, 6, INT, "INT", "Integer part of X", "INT(", "" }, { 1, 7, FRC, "FRC", "Fractional part of X", "FRC(", "" }, { 2, 0, INV, "INV", "Invert functions", "", "" }, { 2, 1, NOP, " ", " ", "", "" }, { 2, 2, NOP, " ", " ", "", "" }, { 2, 3, NOP, " ", " ", "", "" }, { 2, 4, NOP, " ", " ", "", "" }, { 2, 5, E, "e", "e", " e ", "" }, { 2, 6, NOP, " ", " ", "", "" }, { 2, 7, EVAL, "Eval", "Last algebraic expression", "", "" }, { -1, -1, 0, " ", " ", "", "" } }; dcalc_button prog_buttons[] = { { 0, 0, BIN, "BIN", "Binary mode", "", "" }, { 0, 1, OCT, "OCT", "Octal mode", "", "" }, { 0, 2, DEC, "DEC", "Decimal mode", "", "" }, { 0, 3, HEX, "HEX", "Hexadecimal mode", "", "" }, { 0, 4, ASCIIM, "ASC", "Ascii mode", "", "" }, { 0, 5, IP, "IP", "IP address mode", "", "" }, { 0, 6, NOP, " ", " ", "", "" }, { 0, 7, NOP, " ", " ", "", "" }, { 1, 0, dAND, "AND", "x and y", " AND ", "" }, { 1, 1, dOR, "OR", "y or x", " OR ", "" }, { 1, 2, dXOR, "XOR", "y xor x", " XOR ", "" }, { 1, 3, MODULUS, "MOD", "y mod x", " MOD ", "" }, { 1, 4, dNOT, "~X", "not X (complement)", "NOT ", "" }, { 1, 5, SHIFTYL, "y<>" }, { 1, 6, SHIFTYR, "y>>x", "Shift Y, X bits right", ">>", "<<" }, { 1, 7, NOP, " ", " ", "", "" }, { 2, 0, INV, "INV", "Invert functions", "", "" }, { 2, 1, PRIMEF, "PF", "Prime factors of X", "PF(", "" }, { 2, 2, NOP, " ", " ", "", "" }, { 2, 3, NOP, " ", " ", "", "" }, { 2, 4, NOP, " ", " ", "", "" }, { 2, 5, SHIFTL, "<<", "Shift X left 1 bit", "<<1 ", ">>1 " }, { 2, 6, SHIFTR, ">>", "Shift X right 1 bit", ">>1 ", "<<1 " }, { 2, 7, EVAL, "Eval", "Last algebraic expression", "", "" }, { -1, -1, 0, " ", " ", "", "" } }; dcalc_button float_buttons[] = { { 0, 0, FIN, "FIN", "Finance mode", "", "" }, { 0, 1, STAT, "STA", "Statistics mode", "", "" }, { 0, 2, PROG, "PRO", "Programmers mode", "", "" }, { 0, 3, NOP, " ", " ", "", "" }, { 0, 4, 'E', "E", " ", "E", "" }, { 0, 5, PERCENT, "%", "X percent of Y (or INV)", "%", "" }, { 1, 0, YTOX, "y^X", "Y to the power of X", "^", "" }, { 1, 1, SQR, "x2", "X squared", "^2 ", "" }, { 1, 2, ROOT, "SQRT", "Square root of X", "SQRT(", "" }, { 1, 3, NOP, " ", " ", "", "" }, { 1, 4, RECI, "1/X", "Reciprocal of X", " 1/", "" }, { 1, 5, PERCENTCH, "%CH", "Percentage change from Y to X (or INV)", "%ch ", "" }, { 2, 0, FIX, "FIX", "Floating point notation", "", "" }, { 2, 1, SCIFORMAT, "SCI", "Scientific notation", "", "" }, { 2, 2, ENG, "ENG", "Engineering notation", "", "" }, { 2, 3, '7', "7", " ", "7", "" }, { 2, 4, '8', "8", " ", "8", "" }, { 2, 5, '9', "9", " ", "9", "" }, { 3, 0, STORE, "STO", "Store X to a register", "", "" }, { 3, 1, STOPLUS, "ST+", "Add X to a register", "", "" }, { 3, 2, STOMINUS, "ST-", "Subtract X from a register", "", "" }, { 3, 3, '4', "4", " ", "4", "" }, { 3, 4, '5', "5", " ", "5", "" }, { 3, 5, '6', "6", " ", "6", "" }, { 4, 0, RECALL, "RCL", "Recall from a register", "", "" }, { 4, 1, CLR, "CLs", "Clear stack (INV= clear registers)", "", "" }, { 4, 2, NOP, " ", " ", "", "" }, /* reserved for CLu */ { 4, 3, '1', "1", " ", "1", "" }, { 4, 4, '2', "2", " ", "2", "" }, { 4, 5, '3', "3", " ", "3", "" }, { 5, 0, ROLLDOWN, "ROLL", "Roll stack down", "", "" }, { 5, 1, CLX, "CLx", "Clear X", "", "" }, { 5, 2, BACKSPACE, "BSP", "Backspace", "", "" }, { 5, 3, '0', "0", " ", "0", "" }, { 5, 4, '.', ".", " ", ".", "" }, { 5, 5, CHS, "CHS", "Change sign of X", "-", "" }, { -1, -1, 0, " ", " ", "", "" } }; dcalc_button int_buttons[] = { { 0, 0, SCI, "SCI", "Scientific mode", "", "" }, { 0, 1, FIN, "FIN", "Finance mode", "", "" }, { 0, 2, STAT, "STA", "Statistics mode", "", "" }, { 0, 3, 'D', "D", " ", "D", "" }, { 0, 4, 'E', "E", " ", "E", "" }, { 0, 5, 'F', "F", " ", "F", "" }, { 1, 0, YTOX, "y^X", "Y to the power of X", "^", "" }, { 1, 1, SQR, "x2", "X squared", "^2 ", "" }, { 1, 2, NOP, " ", " ", "", "" }, { 1, 3, 'A', "A", " ", "A", "" }, { 1, 4, 'B', "B", " ", "B", "" }, { 1, 5, 'C', "C", " ", "C", "" }, { 2, 0, NOP, " ", " ", "", "" }, { 2, 1, NOP, " ", " ", "", "" }, { 2, 2, NOP, " ", " ", "", "" }, { 2, 3, '7', "7", " ", "7", "" }, { 2, 4, '8', "8", " ", "8", "" }, { 2, 5, '9', "9", " ", "9", "" }, { 3, 0, STORE, "STO", "Store X to a register", "", "" }, { 3, 1, STOPLUS, "ST+", "Add X to a register", "", "" }, { 3, 2, STOMINUS, "ST-", "Subtract X from a register", "", "" }, { 3, 3, '4', "4", " ", "4", "" }, { 3, 4, '5', "5", " ", "5", "" }, { 3, 5, '6', "6", " ", "6", "" }, { 4, 0, RECALL, "RCL", "Recall from a register", "", "" }, { 4, 1, CLR, "CLs", "Clear stack (INV= clear registers)", "", "" }, { 4, 2, NOP, " ", " ", "", "" }, { 4, 3, '1', "1", " ", "1", "" }, { 4, 4, '2', "2", " ", "2", "" }, { 4, 5, '3', "3", " ", "3", "" }, { 5, 0, ROLLDOWN, "ROLL", "Roll stack down", "", "" }, { 5, 1, CLX, "CLx", "Clear X", "", "" }, { 5, 2, BACKSPACE, "BSP", "Backspace", "", "" }, { 5, 3, '0', "0", " ", "0", "" }, { 5, 4, '.', ".", " ", ".", "" }, { 5, 5, CHS, "CHS", "Change sign of X", "", "" }, { -1, -1, 0, " ", " ", "", "" } }; void set_x(char *inbuf) { insertedTextIsFromDcalc = 1; gtk_entry_set_text(entryX, inbuf); insertedTextIsFromDcalc = 0; } void append_x(char *inbuf) { insertedTextIsFromDcalc = 1; gtk_entry_append_text(entryX, inbuf); insertedTextIsFromDcalc = 0; } char *get_x() { return(gtk_entry_get_text(entryX)); } static int prepareKey(dcalc_button *b) { if (!algebraic_mode) return(b->command); /* RPN is too easy! */ switch (b->command) { /* These needY: */ case COMB: case DIVIDE12: case DIVIDE: case DYS: case SHIFTL: case SHIFTR: case SHIFTYL: case SHIFTYR: case MINUS: case MULT: case PERM: case PLUS: case RTOP: case SQR: case TIMES12: case YTOX: case dAND: case dOR: case dXOR: last_was_fin_key = 0; if (liftStack()) { set_x("ans "); } if (isInverted()) append_x(b->invtext); else append_x(b->text); return(NOP); case PERCENT: last_was_fin_key = 0; append_x("%"); on_Equals_clicked(NULL, NULL); return(NOP); case EVAL: last_was_fin_key = 0; liftStack(); set_x(last_eval); return(NOP); case BACKSPACE: { char buf[200]; int len; isInverted(); last_was_fin_key = 0; if (lift_needed) { set_x(""); return(BACKSPACE); } strcpy(buf, get_x()); len = strlen(buf); if (len) { buf[len - 1] = 0; set_x(buf); } } return(NOP); case CLR: process(b->command); set_x(""); return(NOP); case CLX: set_x(""); lift_needed = 0; last_was_fin_key = 0; return(NOP); case 'F': case 'f': case 'E': case 'e': case 'D': case 'd': case 'C': case 'c': case 'B': case 'b': case 'A': case 'a': if ((mode == PROG && intmode == HEX) || (mode != PROG && toupper(b->command) == 'E')) /* is OK */; else return(NOP); case '9': case '8': if (mode == PROG && ((intmode == BIN) || (intmode == OCT))) return(NOP); case '7': case '6': case '5': case '4': case '3': case '2': if (mode == PROG && intmode == BIN) return(NOP); case '1': case '0': case '.': if ((b->command == '.') && (mode == PROG) && (intmode != IP)) return(NOP); last_was_fin_key = 0; if (liftStack()) { set_x(""); } if (isInverted() && strlen(b->invtext)) append_x(b->invtext); else append_x(b->text); return(NOP); case INV: return(b->command); case RECALL: if (liftStack()) { set_x(""); } exec_recall(); return NOP; default: if (liftStack()) { set_x(""); } if (strlen(b->text)) { last_was_fin_key = 0; if (isInverted() && strlen(b->invtext)) append_x(b->invtext); else append_x(b->text); } else { /* just do the command or key: */ int saveInv = invert; strcpy(last_eval, get_x()); if (mode == PROG) pop(); else popf();; exec_equals(); invert = saveInv; return(b->command); } return(NOP); } return(NOP); } int button_command(dcalc_button *b, int i, int j) { while (b != NULL && b->i >= 0) if (b->i == i && b->j == j) return(prepareKey(b)); else b++; return(NOP); } static void display_panel(char which_panel, dcalc_button *b) { gpointer g; char widget_name[80]; if (which_panel == 'R') r_buttons = b; else l_buttons = b; while (b != NULL && b->i >= 0) { sprintf(widget_name, "%c%d_%d", which_panel, b->i, b->j); g = gtk_object_get_data(GTK_OBJECT (main_window), widget_name); if (g) { GtkWidget *child; GtkTooltipsData *tooltipsdata; child = GTK_BIN (g)->child; if (GTK_IS_LABEL (child)) { gtk_label_set_text (GTK_LABEL (child), b->label); } tooltipsdata = gtk_tooltips_data_get(g); if (tooltipsdata) { if (b->tooltip[0] == 0) { gtk_tooltips_disable(tooltipsdata->tooltips); } else { gtk_tooltips_enable(tooltipsdata->tooltips); gtk_tooltips_set_tip(tooltipsdata->tooltips, g, b->tooltip, NULL); } } else fprintf(stderr, "gdcalc: Can't find tooltip for widget %s\n", widget_name); } else fprintf(stderr, "gdcalc: Can't find widget %s\n", widget_name); b++; } } void display_buttons(int c) { GtkWidget *w; if (c == PROG) { display_panel('R', int_buttons); display_panel('L', prog_buttons); } else { switch (c) { case STAT: float_buttons[0].command = PROG; strcpy(float_buttons[0].label, "PRO"); strcpy(float_buttons[0].tooltip, "Programmers mode"); float_buttons[1].command = SCI; strcpy(float_buttons[1].label, "SCI"); strcpy(float_buttons[1].tooltip, "Scientific mode"); float_buttons[2].command = FIN; strcpy(float_buttons[2].label, "FIN"); strcpy(float_buttons[2].tooltip, "Finance mode"); display_panel('L', stat_buttons); break; case FIN: float_buttons[0].command = STAT; strcpy(float_buttons[0].label, "STA"); strcpy(float_buttons[0].tooltip, "Statistics mode"); float_buttons[1].command = PROG; strcpy(float_buttons[1].label, "PRO"); strcpy(float_buttons[1].tooltip, "Programmers mode"); float_buttons[2].command = SCI; strcpy(float_buttons[2].label, "SCI"); strcpy(float_buttons[2].tooltip, "Scientific mode"); display_panel('L', fin_buttons); break; default: /* SCI */ float_buttons[0].command = FIN; strcpy(float_buttons[0].label, "FIN"); strcpy(float_buttons[0].tooltip, "Finance mode"); float_buttons[1].command = STAT; strcpy(float_buttons[1].label, "STA"); strcpy(float_buttons[1].tooltip, "Statistics mode"); float_buttons[2].command = PROG; strcpy(float_buttons[2].label, "PRO"); strcpy(float_buttons[2].tooltip, "Programmers mode"); display_panel('L', sci_buttons); break; } display_panel('R', float_buttons); } w = gtk_object_get_data(GTK_OBJECT(main_window), "degree"); if (w) gtk_widget_set_sensitive(w, (c==PROG)? 0: 1); else fprintf(stderr, "gdcalc: can't find degree menu item\n"); w = gtk_object_get_data(GTK_OBJECT(main_window), "radians"); if (w) gtk_widget_set_sensitive(w, (c==PROG)? 0: 1); else fprintf(stderr, "gdcalc: can't find radians menu item\n"); w = gtk_object_get_data(GTK_OBJECT(main_window), "annuity_in_advance"); if (w) gtk_widget_set_sensitive(w, (c==FIN)? 1: 0); else fprintf(stderr, "gdcalc: can't find annuity menu item\n"); w = gtk_object_get_data(GTK_OBJECT(main_window), "convert"); if (w) gtk_widget_set_sensitive(w, (c==PROG)? 0: 1); else fprintf(stderr, "gdcalc: can't find convert menu item\n"); w = gtk_object_get_data(GTK_OBJECT(main_window), "fixed_point_numbering"); if (w) gtk_widget_set_sensitive(w, (c==PROG)? 0: 1); else fprintf(stderr, "gdcalc: can't find fixed_point_mode menu item\n"); w = gtk_object_get_data(GTK_OBJECT(main_window), "engineering_numbering"); if (w) gtk_widget_set_sensitive(w, (c==PROG)? 0: 1); else fprintf(stderr, "gdcalc: can't find engineering_mode menu item\n"); w = gtk_object_get_data(GTK_OBJECT(main_window), "scientific_numbering"); if (w) gtk_widget_set_sensitive(w, (c==PROG)? 0: 1); else fprintf(stderr, "gdcalc: can't find scientific_numberingmenu item\n"); w = gtk_object_get_data(GTK_OBJECT(main_window), "places"); if (w) gtk_widget_set_sensitive(w, (c==PROG)? 0: 1); else fprintf(stderr, "gdcalc: can't find places menu item\n"); } static void print_number(char *buf, char *name) { gpointer g; g = gtk_object_get_data(GTK_OBJECT (main_window), name); gtk_entry_set_text (GTK_ENTRY (g), buf); } void print_x(char *buf) { set_x(buf); } void add_x(char *buf) { append_x(buf); } void dispnums() { char outbuf[80]; if (entering) { strcpy(outbuf, inbuf); } else fmt_base(outbuf, xiReg, xfReg); prep_for_output(outbuf); print_x(outbuf); fmt_base(outbuf, yiReg, yfReg); prep_for_output(outbuf); print_number(outbuf, "entry_Y"); fmt_base(outbuf, ziReg, zfReg); prep_for_output(outbuf); print_number(outbuf, "entry_Z"); fmt_base(outbuf, tiReg, tfReg); prep_for_output(outbuf); print_number(outbuf, "entry_T"); fmt_base(outbuf, liReg, lfReg); prep_for_output(outbuf); print_number(outbuf, "entry_L"); } /* only used for the bell ... */ void put_a_char(int i) { gdk_beep(); } static char *printBase() { if (mode == PROG) switch (intmode) { case ASCIIM: return("prog:asc: "); case BIN: return("prog:bin: "); case OCT: return("prog:oct: "); case DEC: return("prog:dec: "); case HEX: return("prog:hex: "); } else if (l_buttons == sci_buttons) return "sci: "; else if (l_buttons == fin_buttons) return "fin: "; else return "stats: "; return ""; } static char *printInv() { if (invert) return("inv: "); else return(""); } static char *printDeg(){ if (degree) return("deg: "); else return("rad: "); } void msg(char *buf) { gint context_id; gpointer status_bar; char status[200]; strcpy(status, printBase()); if (mode != PROG) { strcat(status, printDeg()); } strcat(status, printInv()); strcat(status, " "); strcat(status, buf); status_bar = gtk_object_get_data(GTK_OBJECT (main_window), _("statusbar")); context_id = gtk_statusbar_get_context_id(GTK_STATUSBAR(status_bar), "Statusbar example"); gtk_statusbar_push( GTK_STATUSBAR(status_bar), context_id, status); } void clear_msg() { msg(""); } void print_inv() { gtk_button_set_relief(invert_button, invert? GTK_RELIEF_NONE: GTK_RELIEF_NORMAL); } /* These not needed for GTK version: */ void prinbase() {}; void print_string(char *buf) {} void print_deg(){} void pop_up_help(void) {} void os_raw_mode(int i) { raw_mode = 0 /* i */; } void os_init(void) {} void os_term(void) {gtk_main_quit();} int get_a_char(int *c) {return 0;} int dialog(char *buf) { GtkWidget *dialog_popup; gpointer g; int reply; dialog_popup = create_gen_dialog (); g = gtk_object_get_data(GTK_OBJECT (dialog_popup), _("msg")); gtk_label_set_text(GTK_LABEL(g), buf); reply = gtk_dialog_run(dialog_popup); gtk_widget_destroy(dialog_popup); return (reply==0)? 'Y': 'N'; } int places(char *buf) { GtkWidget *places_dialog; GtkSpinButton *spinbutton; int reply; gfloat decplacesf = decplaces; places_dialog = create_places (); spinbutton = gtk_object_get_data(GTK_OBJECT (places_dialog), _("places_spinbutton")); gtk_spin_button_set_value(spinbutton, decplacesf); reply = gtk_dialog_run(places_dialog); if (reply == 0) reply = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinbutton)); else reply = -1; gtk_widget_destroy(places_dialog); return reply; } int eval(char *buf, char *expr) { GtkEntry *eval_expr_entry; int reply; eval_dialog = create_eval (); eval_expr_entry = gtk_object_get_data(GTK_OBJECT (eval_dialog), _("eval_expr")); gtk_entry_set_text( eval_expr_entry, buf); reply = gtk_dialog_run(eval_dialog); if (reply == 0) { strcpy(expr, gtk_entry_get_text(eval_expr_entry)); } else reply = -1; gtk_widget_destroy(eval_dialog); return reply; } static void setFont(char *widgetName, GtkWidget *main_window, GdkFont *newFont) { GtkWidget *widget; GtkStyle *style; widget = gtk_object_get_data(GTK_OBJECT (main_window), widgetName); if (!widget) { fprintf(stderr, "gdcalc: setFont: can't find %s\n", widgetName); return; } style = gtk_widget_get_style(widget); if (!style) { fprintf(stderr, "gdcalc: setFont: can't find for widget %s\n", widgetName); return; } gdk_font_unref (style->private_font); style->private_font = newFont; gdk_font_ref (style->private_font); gtk_widget_set_style (widget, style); } void setPlusMinusFont(char *fontName) { GdkFont *newFont; newFont = gdk_font_load(fontName); if (!newFont) { fprintf(stderr, "gdcalc: can't find font \"%s\"\n", fontName); return; } setFont("Equals", main_window, newFont); setFont("LeftBrace", main_window, newFont); setFont("RightBrace", main_window, newFont); setFont("Plus", main_window, newFont); setFont("Minus", main_window, newFont); setFont("Mult", main_window, newFont); setFont("Divide", main_window, newFont); } void setButtonFont(char *fontName) { GdkFont *newFont; int row, col; char widgetName[100]; newFont = gdk_font_load(fontName); if (!newFont) { fprintf(stderr, "gdcalc: can't find font \"%s\"\n", fontName); return; } for (row = 0; row < 3; row++) for (col = 0; col < 8; col++) { sprintf(widgetName, "L%d_%d", row, col); setFont(widgetName, main_window, newFont); } for (row = 0; row < 6; row++) for (col = 0; col < 6; col++) { sprintf(widgetName, "R%d_%d", row, col); setFont(widgetName, main_window, newFont); } setFont("Enter", main_window, newFont); } #ifdef RUNTIME_FONT_CHANGES_ARE_WORKING void fixFont(char *newFont, GtkWidget *this_main_window, char *name) { GdkFont *fixed_font; fixed_font = gdk_font_load(newFont); if (!fixed_font) { fprintf(stderr, "gdcalc: fixFont: can't find font \"%s\"\n", newFont); return; } setFont(name, this_main_window, fixed_font); } #endif static void xdispreg(GtkWidget *dialog, int i) { char labelname[80], outbuf[80]; GtkWidget *entry; if (dialog) { sprintf(labelname, "mem%d", i); #ifdef RUNTIME_FONT_CHANGES_ARE_WORKING fixFont(calculatorFont, dialog, labelname); #endif entry = gtk_object_get_data(GTK_OBJECT (dialog), labelname); fmt_base(outbuf, reg[i], regf[i]); prep_for_output(outbuf); if (l_buttons == fin_buttons) switch (i) { case FIN_NUM_REG: strcat(outbuf, " = periods"); break; case FIN_INT_REG: strcat(outbuf, " = interest (%)"); break; case FIN_PVAL_REG: strcat(outbuf, " = PVal"); break; case FIN_PMT_REG: strcat(outbuf, " = payment"); break; case FIN_FVAL_REG: strcat(outbuf, " = FVal"); break; } else if (l_buttons == stat_buttons) switch (i) { case STAT_R2: strcat(outbuf, " = correlation (1=good 0=poor)"); break; case STAT_Y_INT: strcat(outbuf, " = Y intersect"); break; case STAT_SLOPE: strcat(outbuf, " = slope"); break; case STAT_NUM_REG: strcat(outbuf, " = n"); break; case STAT_SUMX_REG: strcat(outbuf, " = sum of X's"); break; case STAT_SUMX2_REG: strcat(outbuf, " = sum of x2's"); break; case STAT_SUMY_REG: strcat(outbuf, " = sum of Y's"); break; case STAT_SUMY2_REG: strcat(outbuf, " = sum of y2's"); break; case STAT_SUMXY_REG: strcat(outbuf, " = sum of XY's"); break; } gtk_entry_set_text(GTK_ENTRY(entry), outbuf); } } void dispreg(int i) { xdispreg(registers, i); } void dispregs(void) { int i; if (registers) for (i = 0; i < NUMREGS; i++) dispreg(i); } void toggle_registers(void) { if (!registers) { registers = create_mem_dialog(); dispregs(); gtk_widget_show(registers); } else { gtk_widget_destroy(registers); registers = NULL; } } void pop_up_reg(void) { toggle_registers(); } static int do_mem_dialog(char *buf) { int reply, i; mem_dialog = create_mem_dialog (); gtk_window_set_title (GTK_WINDOW (mem_dialog), buf); for (i=0; i < NUMREGS; i++) xdispreg(mem_dialog, i); reply = gtk_dialog_run(mem_dialog); gtk_widget_destroy(mem_dialog); return (reply==0)? -1: mem_value+'0'; } int store(char *buf) { return(do_mem_dialog("Store...")); } int recall(char *buf) { return(do_mem_dialog("Recall...")); } void on_algebraic_activate(); static void setName(char *widgetName, char *name) { GtkWidget *w; w = (GtkWidget *) gtk_object_get_data(GTK_OBJECT (main_window), widgetName); if (!w) { fprintf(stderr, "gdcalc: Can't find widget %s\n", widgetName); return; } gtk_widget_set_name(w, name); } int main(int argc, char *argv[]) { char *cfont = NULL, *bfont = NULL, *pfont = NULL; char rcFileName[MAXPATHLEN]; struct poptOption options[] = { {"calculatorFont", 'f', POPT_ARG_STRING, NULL, 0, "Font for numbers", "FONT"}, {"buttonFont", 'b', POPT_ARG_STRING, NULL, 0, "Font for buttons", "FONT"}, {"plusMinusFont", 'p', POPT_ARG_STRING, NULL, 0, "Font for +, - etc", "FONT"}, {NULL, '\0', 0, NULL, 0, NULL, NULL} /* end the list */ }; GtkWidget *w; /* apparently not needed: bindtextdomain (PACKAGE, PACKAGE_LOCALE_DIR); textdomain (PACKAGE); */ options[0].arg = &cfont; options[0].arg = &bfont; options[0].arg = &pfont; gnome_init_with_popt_table("gdcalc", VERSION, argc, argv, options, 0, NULL); if (cfont && *cfont) strcpy(calculatorFont, cfont); else strcpy(calculatorFont, "-misc-fixed-medium-r-*-*-14-*-*-*-*-*-*-*"); if (bfont && *bfont) strcpy(buttonFont, bfont); else strcpy(buttonFont, "-misc-fixed-medium-r-*-*-14-*-*-*-*-*-*-*"); if (pfont && *pfont) strcpy(plusMinusFont, pfont); else strcpy(plusMinusFont, "-misc-fixed-medium-r-*-*-14-*-*-*-*-*-*-*"); main_window = create_main_window (); /* Assign names that can be picked up by resource file: */ setName("Plus", "big_button"); setName("Minus", "big_button"); setName("Mult", "big_button"); setName("Divide", "big_button"); setName("LeftBrace", "big_button"); setName("RightBrace", "big_button"); setName("Equals", "big_button"); /* setName("R5_4", "big_button"); .. decimal - distorts the display too much */ strcpy(rcFileName, getenv("HOME")); strcat(rcFileName, "/.gdcalc.rc"); gtk_rc_parse(rcFileName); #ifdef RUNTIME_FONT_CHANGES_ARE_WORKING /* Load a fixed font for the numeric displays: */ fixFont(calculatorFont, main_window, "entry_X"); fixFont(calculatorFont, main_window, "entry_Y"); fixFont(calculatorFont, main_window, "entry_Z"); fixFont(calculatorFont, main_window, "entry_T"); fixFont(calculatorFont, main_window, "entry_L"); setButtonFont(buttonFont); setPlusMinusFont(plusMinusFont); #endif gtk_widget_draw(main_window, NULL); gtk_widget_show (main_window); entryX = (GtkEntry *) gtk_object_get_data(GTK_OBJECT (main_window), "entry_X"); if (!entryX) { fprintf(stderr, "gdcalc: Can't find widget entry_X\n"); exit(1); } invert_button = (GtkButton *) gtk_object_get_data(GTK_OBJECT (main_window), "L2_0"); if (!invert_button) { fprintf(stderr, "gdcalc: Can't find widget for invert button\n"); exit(1); } initialise(); display_buttons(mode); /* gtk_check_menu_item_set_active actually calls the widgets activate method - ie simulating a button release!! This can lead to an infinite loop of invocations */ w = gtk_object_get_data(GTK_OBJECT(main_window), (mode==SCI)? "scientific_mode": (mode==FIN)? "financial_mode": (mode==STAT)? "statistics_mode": "programming_mode"); if (w) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), 1); else fprintf(stderr, "gdcalc: Can't find main mode item in menu\n"); w = gtk_object_get_data(GTK_OBJECT(main_window), degree? "degree": "radians"); if (w) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), 1); else fprintf(stderr, "gdcalc: Can't find degree/radians item in menu\n"); w = gtk_object_get_data(GTK_OBJECT(main_window), (floatmode==ENG)? "engineering_numbering": (floatmode==SCI)?"scientific_numbering": "fixed_point_numbering"); if (w) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), 1); else fprintf(stderr, "gdcalc: Can't find floating point item in menu\n"); w = gtk_object_get_data(GTK_OBJECT(main_window), "annuity_in_advance"); if (w) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), finPayAt0? 1: 0); else fprintf(stderr, "gdcalc: Can't find annuity item in menu\n"); w = gtk_object_get_data(GTK_OBJECT(main_window), algebraic_mode?"algebraic":"rpn"); if (w) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w), 1); else fprintf(stderr, "gdcalc: Can't find algebraic/rpn item in menu\n"); #ifndef RUNTIME_FONT_CHANGES_ARE_WORKING w = gtk_object_get_data(GTK_OBJECT(main_window), "font"); if (w) gtk_widget_hide(w); else fprintf(stderr, "gdcalc: Can't find font item in menu\n"); w = gtk_object_get_data(GTK_OBJECT(main_window), "button_font"); if (w) gtk_widget_hide(w); else fprintf(stderr, "gdcalc: Can't find button_font item in menu\n"); w = gtk_object_get_data(GTK_OBJECT(main_window), "plus_minus_font"); if (w) gtk_widget_hide(w); else fprintf(stderr, "gdcalc: Can't find plus_minus_font item in menu\n"); #endif dispnums(); msg(DEF_SIG(VERSION)); if (registers) { /* set to 1 by readGuiSettings */ registers = NULL; toggle_registers(); } gtk_main (); return 0; } /* For emacs: */ /* Local Variables: */ /* eval:(setq tab-width 4) */ /* End: */