/*
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 <config.h>
#endif
#include <ctype.h>
#include <gnome.h>
#include <sys/param.h>
#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<<x", "Shift Y, X bits left", "<<", ">>" },
{ 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: */
syntax highlighted by Code2HTML, v. 0.9.1