simplify change mode dialog
[gcalctool.git] / gcalctool / calctool.c
blobb445b40978cf149805055cc4c3e6a63b8f523ae4
2 /* $Header$
4 * Copyright (c) 1987-2007 Sun Microsystems, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <sys/types.h>
28 #include "calctool.h"
29 #include "get.h"
30 #include "display.h"
31 #include "functions.h"
32 #include "ui.h"
34 time_t time();
36 int basevals[4] = { 2, 8, 10, 16 };
38 /* Calctool variables and options. */
39 Vars v;
41 // FIXME: Sort this list
42 /* Note that none of these strings can be translated as the parser expects them to be correct */
43 struct button buttons[NKEYS] = {
45 /* id,
46 symname
47 func
48 flags
52 KEY_0,
53 "0",
54 do_number,
55 NUMBER
58 KEY_1,
59 "1",
60 do_number,
61 NUMBER
64 KEY_2,
65 "2",
66 do_number,
67 NUMBER
68 },
70 KEY_3,
71 "3",
72 do_number,
73 NUMBER
76 KEY_4,
77 "4",
78 do_number,
79 NUMBER
82 KEY_5,
83 "5",
84 do_number,
85 NUMBER
88 KEY_6,
89 "6",
90 do_number,
91 NUMBER
94 KEY_7,
95 "7",
96 do_number,
97 NUMBER
100 KEY_8,
101 "8",
102 do_number,
103 NUMBER
106 KEY_9,
107 "9",
108 do_number,
109 NUMBER
112 KEY_A,
113 "A",
114 do_number,
115 NUMBER
118 KEY_B,
119 "B",
120 do_number,
121 NUMBER
124 KEY_C,
125 "C",
126 do_number,
127 NUMBER
130 KEY_D,
131 "D",
132 do_number,
133 NUMBER
136 KEY_E,
137 "E",
138 do_number,
139 NUMBER
142 KEY_F,
143 "F",
144 do_number,
145 NUMBER
148 KEY_NUMERIC_POINT,
149 ".",
150 do_point,
151 NUMBER
154 KEY_CALCULATE,
155 NULL,
156 do_calc,
160 KEY_CLEAR,
161 NULL,
162 do_clear,
166 KEY_CLEAR_ENTRY,
167 NULL,
168 do_clear_entry,
172 KEY_START_BLOCK,
173 "(",
174 do_paren,
178 KEY_END_BLOCK,
179 ")",
180 do_paren,
184 KEY_ADD,
185 "+",
186 do_calc,
190 KEY_SUBTRACT,
191 "-",
192 do_calc,
196 KEY_MULTIPLY,
197 "*",
198 do_calc,
202 KEY_DIVIDE,
203 "/",
204 do_calc,
208 KEY_BACKSPACE,
209 NULL,
210 do_delete,
214 KEY_CHANGE_SIGN,
215 NULL,
216 do_immed,
220 KEY_INTEGER,
221 "Int",
222 do_portion,
223 FUNC
226 KEY_FRACTION,
227 "Frac",
228 do_portion,
229 FUNC
232 KEY_PERCENTAGE,
233 "%",
234 do_percent,
238 KEY_SQUARE,
239 "^2",
240 do_immed,
241 POSTFIXOP
244 KEY_SQUARE_ROOT,
245 "Sqrt",
246 do_immed,
247 FUNC
250 KEY_RECIPROCAL,
251 NULL,
252 do_immed,
256 KEY_E_POW_X,
257 "e^",
258 do_immed,
259 PREFIXOP
262 KEY_10_POW_X,
263 "10^",
264 do_immed,
265 PREFIXOP
268 KEY_X_POW_Y,
269 "^",
270 do_calc,
271 POSTFIXOP
274 KEY_FACTORIAL,
275 "!",
276 do_immed,
277 POSTFIXOP
280 KEY_RANDOM,
281 "Rand",
282 do_immed,
286 KEY_SIN,
287 "Sin",
288 do_sin,
289 FUNC
292 KEY_SINH,
293 "Sinh",
294 do_sinh,
295 FUNC
298 KEY_ASIN,
299 "Asin",
300 do_asin,
301 FUNC
304 KEY_ASINH,
305 "Asinh",
306 do_asinh,
307 FUNC
310 KEY_COS,
311 "Cos",
312 do_cos,
313 FUNC
316 KEY_COSH,
317 "Cosh",
318 do_cosh,
319 FUNC
322 KEY_ACOS,
323 "Acos",
324 do_acos,
325 FUNC
328 KEY_ACOSH,
329 "Acosh",
330 do_acosh,
331 FUNC
334 KEY_TAN,
335 "Tan",
336 do_tan,
337 FUNC
340 KEY_TANH,
341 "Tanh",
342 do_tanh,
343 FUNC
346 KEY_ATAN,
347 "Atan",
348 do_atan,
349 FUNC
352 KEY_TAN,
353 "Atanh",
354 do_atanh,
355 FUNC
358 KEY_NATURAL_LOGARITHM,
359 "Ln",
360 do_immed,
361 FUNC
364 KEY_LOGARITHM,
365 "Log",
366 do_immed,
367 FUNC
370 KEY_ABSOLUTE_VALUE,
371 "Abs",
372 do_portion,
373 FUNC
376 KEY_MASK_16,
377 "u16",
378 do_immed,
379 FUNC
382 KEY_MASK_32,
383 "u32",
384 do_immed,
385 FUNC
388 KEY_MODULUS_DIVIDE,
389 " Mod ",
390 do_calc,
394 KEY_EXPONENTIAL,
395 "e",
396 do_expno,
400 KEY_NOT,
401 "~",
402 do_immed,
406 KEY_OR,
407 " OR ",
408 do_calc,
412 KEY_AND,
413 " AND ",
414 do_calc,
418 KEY_XOR,
419 " XOR ",
420 do_calc,
424 KEY_XNOR,
425 " XNOR ",
426 do_calc,
430 KEY_FINC_CTRM,
431 "Ctrm",
432 do_business,
436 KEY_FINC_DDB,
437 "Ddb",
438 do_business,
442 KEY_FINC_FV,
443 "Fv",
444 do_business,
448 KEY_FINC_PMT,
449 "Pmt",
450 do_business,
454 KEY_FINC_PV,
455 "Pv",
456 do_business,
460 KEY_FINC_RATE,
461 "Rate",
462 do_business,
466 KEY_FINC_SLN,
467 "Sln",
468 do_business,
472 KEY_FINC_SYD,
473 "Syd",
474 do_business,
478 KEY_FINC_TERM,
479 "Term",
480 do_business,
484 KEY_SHIFT,
485 NULL,
486 do_shift,
490 KEY_STORE,
491 NULL,
492 do_sto,
496 KEY_RECALL,
497 NULL,
498 do_rcl,
502 KEY_EXCHANGE,
503 NULL,
504 do_exchange,
508 KEY_SET_ACCURACY,
509 NULL,
510 do_accuracy,
514 KEY_CONSTANT,
515 NULL,
516 do_constant,
520 KEY_FUNCTION,
521 NULL,
522 do_function,
528 /* Calctools' customised math library error-handling routine. */
530 void
531 doerr(char *errmes)
533 if (!v->started) {
534 return;
537 switch (v->syntax) {
538 case NPA:
539 strncpy(v->display, errmes, MAXLINE - 1);
540 v->display[MAXLINE - 1] = '\0';
541 ui_set_error_state(TRUE);
542 ui_set_display(v->display, FALSE);
543 ui_beep();
544 break;
546 case EXPRS:
547 v->math_error = -MPMATH_ERR;
548 break;
550 default:
551 assert(FALSE);
555 static void
556 init_text() /* Setup constant strings. */
558 STRNCPY(v->con_names[0], _("Kilometer-to-mile conversion factor"),
559 MAXLINE - 1);
560 STRNCPY(v->con_names[1], _("square root of 2"), MAXLINE - 1);
561 STRNCPY(v->con_names[2], _("e"), MAXLINE - 1);
562 STRNCPY(v->con_names[3], _("pi"), MAXLINE - 1);
563 STRNCPY(v->con_names[4], _("Centimeter-to-inch conversion factor"),
564 MAXLINE - 1);
565 STRNCPY(v->con_names[5], _("degrees in a radian"), MAXLINE - 1);
566 STRNCPY(v->con_names[6], _("2 ^ 20"), MAXLINE - 1);
567 STRNCPY(v->con_names[7], _("Gram-to-ounce conversion factor"), MAXLINE - 1);
568 STRNCPY(v->con_names[8],
569 _("Kilojoule-to-British-thermal-unit conversion factor"),
570 MAXLINE - 1);
571 STRNCPY(v->con_names[9],
572 _("Cubic-centimeter-to-cubic-inch conversion factor"), MAXLINE - 1);
576 /* Default math library exception handling routine. */
578 /*ARGSUSED*/
580 matherr(exc)
581 struct exception *exc;
583 doerr(_("Error"));
585 return(1);
589 static void
590 getparam(char *s, char *argv[], char *errmes)
592 if (*argv != NULL && argv[0][0] != '-') {
593 STRNCPY(s, *argv, MAXLINE - 1);
594 } else {
595 FPRINTF(stderr, _("%s: %s as next argument.\n"), v->progname, errmes);
596 exit(1);
601 void
602 usage(char *progname)
604 FPRINTF(stderr, _("%s version %s\n\n"), progname, VERSION);
605 FPRINTF(stderr, _("Usage: %s: [-D] [-E] [-a accuracy] "), progname);
606 FPRINTF(stderr, _("\t\t [-?] [-v] [-h]\n"));
607 exit(1);
610 #define INC { argc--; argv++; }
612 void
613 get_options(int argc, char *argv[]) /* Extract command line options. */
615 char next[MAXLINE]; /* The next command line parameter. */
617 INC;
618 while (argc > 0) {
619 if (argv[0][0] == '-') {
620 switch (argv[0][1]) {
621 case 'D' : /* MP debug info. to stderr. */
622 v->MPdebug = TRUE;
623 break;
625 case 'E' : /* MP errors to stderr. */
626 v->MPerrors = TRUE;
627 break;
629 case 'a' :
630 INC;
631 getparam(next, argv, _("-a needs accuracy value"));
632 v->accuracy = atoi(next);
633 if (v->accuracy < 0 || v->accuracy > MAXACC) {
634 FPRINTF(stderr,
635 _("%s: accuracy should be in the range 0-%d\n"),
636 v->progname, MAXACC);
637 v->accuracy = 9;
639 break;
641 case 'n' :
642 if (strcmp(argv[0], "-name") == 0)
644 INC;
645 read_str(&v->appname, argv[0]);
647 break;
649 case '?' :
650 case 'v' :
651 case 'h' :
652 usage(v->progname);
653 break;
655 INC;
656 } else {
657 INC;
663 static void
664 init_constant(int n, gchar *value)
666 gchar *str = g_strdup(value);
668 MPstr_to_num(str, DEC, v->MPcon_vals[n]);
669 g_free(str);
673 static void
674 init_state(void)
676 int acc, i, n, size;
678 v->ghost_zero = 1; /* Display initially has empty content. */
679 v->accuracy = 9; /* Initial accuracy. */
680 v->show_zeroes = FALSE; /* Don't show trailing zeroes. */
681 v->base = DEC; /* Initial base. */
682 v->dtype = FIX; /* Initial number display mode. */
683 v->ttype = DEG; /* Initial trigonometric type. */
684 v->modetype = BASIC; /* Initial calculator mode. */
685 v->MPdebug = FALSE; /* No debug info by default. */
686 v->MPerrors = FALSE; /* No error information. */
687 acc = MAX_DIGITS + 12; /* MP internal accuracy. */
688 size = MP_SIZE;
689 mpset(&acc, &size, &size);
691 v->error = 0; /* No calculator error initially. */
692 v->key_exp = 0; /* Not entering an exponent number. */
694 v->current = KEY_CALCULATE;
695 v->shelf = NULL; /* No selection for shelf initially. */
696 v->noparens = 0; /* No unmatched brackets initially. */
697 v->numsptr = 0; /* Nothing on the parenthese numeric stack. */
698 v->warn_change_mode = 1; /* Warn user when changing modes. */
700 init_constant(0, "0.621"); /* kms/hr <=> miles/hr. */
701 init_constant(1, "1.4142135623"); /* square root of 2 */
702 init_constant(2, "2.7182818284"); /* e */
703 init_constant(3, "3.1415926536"); /* pi */
704 init_constant(4, "0.3937007"); /* cms <=> inch. */
705 init_constant(5, "57.295779513"); /* degrees/radian. */
706 init_constant(6, "1048576.0"); /* 2 ^ 20. */
707 init_constant(7, "0.0353"); /* grams <=> ounce. */
708 init_constant(8, "0.948"); /* Kjoules <=> BTU's. */
709 init_constant(9, "0.0610"); /* cms3 <=> inches3. */
711 n = 0;
712 for (i = 0; i < MAXREGS; i++) {
713 mpcim(&n, v->MPmvals[i]);
719 main(int argc, char **argv)
721 char *ptr;
723 v = (Vars) LINT_CAST(calloc(1, sizeof(struct calcVars)));
725 bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
726 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
727 textdomain(GETTEXT_PACKAGE);
729 v->progname = argv[0]; /* Save programs name. */
730 v->appname = NULL;
731 if ((ptr = strrchr(argv[0], '/')) != NULL) {
732 read_str(&v->appname, ptr+1);
733 } else {
734 read_str(&v->appname, argv[0]);
737 init_state();
739 get_options(argc, argv); /* Get command line arguments. */
740 ui_init(&argc, &argv); /* Initialise UI */
741 resources_init(); /* Initialise configuration */
743 v->radix = get_radix(); /* Locale specific radix string. */
744 v->tsep = get_tsep(); /* Locale specific thousands seperator. */
746 init_text(); /* Setup text strings depending upon language. */
747 read_resources(); /* Read resources from merged database. */
748 ui_load();
750 srand48((long) time((time_t *) 0)); /* Seed random number generator. */
752 do_clear(); /* Initialise and clear display. */
754 show_display(v->MPdisp_val); /* Output in correct display mode. */
756 memset(&(v->h), 0, sizeof(struct exprm_state_history)); /* clear expression mode state history*/
758 ui_start(); /* Display the calculator. */
760 return(0);