2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: calctool.c /main/9 1996/09/25 11:28:16 rswiston $ */
26 * Contains the none user interface portion of the Desktop *
29 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
30 * (c) Copyright 1993, 1994 International Business Machines Corp. *
31 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
32 * (c) Copyright 1993, 1994 Novell, Inc. *
40 #include <sys/types.h>
42 #include <sys/param.h>
45 #include "patchlevel.h"
47 #include "ds_common.h"
51 /* Copied from math.h */
65 6.871947674e+10, 3.245185537e+32,
66 1.000000000e+36, 2.230074520e+43
68 double min_fix0[4] = {
69 2.500000000e-1, 3.750000000e-1,
70 1.000000000e-1, 4.375000000e-1
72 double min_fix1[4] = {
73 1.250000000e-1, 4.687500000e-2,
74 1.000000000e-2, 2.734375000e-2
76 double min_fix2[4] = {
77 6.250000000e-2, 5.859375000e-3,
78 1.000000000e-3, 1.708984375e-3
80 double min_fix3[4] = {
81 3.125000000e-2, 7.324218750e-4,
82 1.000000000e-4, 1.068115234e-4
84 double min_fix4[4] = {
85 1.562500000e-2, 9.155273437e-5,
86 1.000000000e-5, 6.675720215e-6
88 double min_fix5[4] = {
89 7.812500000e-3, 1.144409180e-5,
90 1.000000000e-6, 4.172325134e-7
92 double min_fix6[4] = {
93 6.906250000e-3, 1.430511475e-6,
94 1.000000000e-7, 2.607703209e-8
96 double min_fix7[4] = {
97 1.953125000e-3, 1.788139343e-7,
98 1.000000000e-8, 1.629814506e-9
100 double min_fix8[4] = {
101 9.765625000e-4, 2.235174179e-8,
102 1.000000000e-9, 1.018634066e-10
104 double min_fix9[4] = {
105 4.882812500e-4, 2.793967724e-9,
106 1.000000000e-10, 6.366462912e-12
109 extern char *base_str[] ; /* Strings for each base value. */
110 extern char *cmdstr[] ; /* Strings for each command line option. */
111 extern char *dtype_str[] ; /* Strings for each display mode value. */
112 extern char *lstrs[] ; /* Labels for various Motif items. */
113 extern char *mess[] ; /* Message strings. */
114 extern char *mode_str[] ; /* Strings for each mode value. */
115 extern char *opts[] ; /* Command line option strings. */
116 extern char *ttype_str[] ; /* Strings for each trig type value. */
117 extern char *ustrs[] ; /* Usage message strings. */
118 extern char *vstrs[] ; /* Various strings. */
120 char digits[] = "0123456789ABCDEF" ;
121 int basevals[4] = { 2, 8, 10, 16 } ;
123 int left_pos[BCOLS] = { 3, 2, 1, 0 } ; /* Left positions. */
124 int right_pos[BCOLS] = { 0, 1, 2, 3 } ; /* "Right" positions. */
126 /* Valid keys when an error condition has occurred. */
127 /* MEM KEYS clr clr QUIT REDRAW */
128 char validkeys[MAXVKEYS] = { 'm', 'k', '\177', '\013', 'q', '\f' } ;
130 Vars v ; /* Calctool variables and options. */
132 struct menu_entry menu_entries[MAXENTRIES] ;
134 struct menu cmenus[MAXMENUS] = { /* Calculator menus. */
135 /* title total index defval */
136 { (char *) NULL, 10, 0, 2 /* 2 places */ }, /* ACC */
137 { (char *) NULL, 4, 20, 2 /* Decimal */ }, /* BASE TYPE */
138 { (char *) NULL, 10, 0, 0 /* Con. 0 */ }, /* CON */
139 { (char *) NULL, 10, 10, 0 /* Reg. 0 */ }, /* EXCH */
140 { (char *) NULL, 10, 0, 0 /* Fun. 0 */ }, /* FUN */
141 { (char *) NULL, 4, 30, 0 /* Basic */ }, /* MODE */
142 { (char *) NULL, 3, 24, 1 /* Fixed */ }, /* NUM TYPE */
143 { (char *) NULL, 10, 10, 0 /* Reg. 0 */ }, /* RCL */
144 { (char *) NULL, 10, 10, 0 /* Reg. 0 */ }, /* STO */
145 { (char *) NULL, 3, 27, 0 /* Degrees */ }, /* TRIG TYPE */
148 /* This table shows the keyboard values that are currently being used:
150 * | a b c d e f g h i j k l m n o p q r s t u v w x y z
151 *-------------+--------------------------------------------------
152 * Control: | a c d f h i l m r s t u y
153 * Lower: | a b c d e f h i k m n p q r s v x y
154 * Upper: | A B C D E F G M N P Q R S T X
155 * Numeric: | 0 1 2 3 4 5 6 7 8 9
156 * Other: | @ . + - * / = % ( ) # < > [ ] { } | & ~ ^ ? ! \177
157 *----------------------------------------------------------------
160 /* Calculator button values. */
162 struct button buttons[TITEMS] = {
163 /* str str2 value opdisp menutype resname func */
166 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
167 { (char *)NULL, (char *)NULL, 0, OP_SET, M_FUN, "fun", do_pending },
168 { (char *)NULL, (char *)NULL, 0, OP_SET, M_CON, "con", do_pending },
169 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "keys", do_keys },
172 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "int", do_portion },
173 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "frac", do_portion },
174 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "abs", do_portion },
175 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "exp", do_expno },
178 { (char *)NULL, (char *)NULL, 0, OP_SET, M_ACC, "acc", do_pending },
179 { (char *)NULL, (char *)NULL, 0, OP_SET, M_STO, "sto", do_pending },
180 { (char *)NULL, (char *)NULL, 0, OP_SET, M_RCL, "rcl", do_pending },
181 { (char *)NULL, (char *)NULL, 0, OP_SET, M_EXCH, "exch", do_pending },
184 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
185 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
186 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
187 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
190 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
191 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
192 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
193 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
196 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
197 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
198 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
199 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
202 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "recip", do_immed },
203 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "square", do_immed },
204 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "sqrt", do_immed },
205 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "percent", do_calc },
208 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "lparen", do_paren },
209 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "rparen", do_paren },
210 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "bsp", do_delete },
211 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "clr", do_clear },
214 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "numd", do_number },
215 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "nume", do_number },
216 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "numf", do_number },
217 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "chs", do_immed },
220 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "numa", do_number },
221 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "numb", do_number },
222 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "numc", do_number },
223 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "mul", do_calc },
226 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num7", do_number },
227 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num8", do_number },
228 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num9", do_number },
229 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "div", do_calc },
232 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num4", do_number },
233 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num5", do_number },
234 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num6", do_number },
235 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "sub", do_calc },
238 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num1", do_number },
239 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num2", do_number },
240 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num3", do_number },
241 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "add", do_calc },
244 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num0", do_number },
245 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "point", do_point },
246 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "equals", do_calc },
247 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "quit", do_frame },
249 { (char *)NULL, (char *)NULL, 0, OP_SET, M_BASE, "base", do_pending },
250 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NUM, "disp", do_pending },
251 { (char *)NULL, (char *)NULL, 0, OP_SET, M_MODE, "mode", do_pending },
252 { (char *)NULL, (char *)NULL, 0, OP_SET, M_TRIG, "trig", do_pending },
255 struct button mode_buttons[MAXMODES * MODEKEYS] = {
256 /* str str2 value opdisp menutype resname func */
259 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "term", do_business},
260 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "rate", do_business},
261 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "pv", do_business},
262 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "pmt", do_business},
263 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "fv", do_business},
264 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "ppy", do_business},
265 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "clrreg", do_business},
266 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "ctrm", do_business},
267 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "ddb", do_business},
268 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "sln", do_business},
269 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "syd", do_business},
270 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
271 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
272 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
273 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
274 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
277 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "lshift", do_pending },
278 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "rshift", do_pending },
279 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "and16", do_immed },
280 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "and32", do_immed },
281 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "or", do_calc },
282 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "and", do_calc },
283 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "not", do_immed },
284 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "xor", do_calc },
285 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "xnor", do_calc },
286 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
287 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
288 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
289 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
290 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
291 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
292 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
295 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "inv", do_immed },
296 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "hyp", do_immed },
297 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "etox", do_immed },
298 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "tentox", do_immed },
299 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "ytox", do_calc },
300 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "xfact", do_immed },
301 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "cos", do_trig },
302 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "sin", do_trig },
303 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "tan", do_trig },
304 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "ln", do_immed },
305 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "log", do_immed },
306 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "rand", do_immed },
307 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
308 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
309 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
310 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
317 if (chr >= '0' && chr <= '9') return(chr - '0') ;
318 else if (chr >= 'a' && chr <= 'f') return(chr - 'a' + 10) ;
319 else if (chr >= 'A' && chr <= 'F') return(chr - 'A' + 10) ;
333 mpcim(&i, v->MPdisp_val) ;
334 STRCPY(v->display, make_number(v->MPdisp_val, FALSE)) ;
335 set_item(DISPLAYITEM, v->display) ;
340 v->opsptr = 0 ; /* Clear parentheses stacks. */
342 set_item(HYPITEM, " ") ;
343 set_item(INVITEM, " ") ;
346 /* Convert .dtcalcrc line to ascii values. */
347 /* line Input line to be converted. */
351 static char output[MAXLINE] ; /* Converted output record. */
352 int ctrl = 0 ; /* Set if we are processing a control character. */
353 int i ; /* Position within input line. */
355 int n = 0 ; /* Position within output line. */
358 for (i = 0; i < len; i++)
360 if (line[i] == ' ') continue ;
361 else if (line[i] == '\\') ctrl = 1 ;
364 output[n++] = CTL(line[i]) ;
367 else output[n++] = line[i] ;
375 do_dtcalc(int argc, char **argv)
379 v->progname = argv[0] ; /* Save programs name. */
381 init_cmdline_opts() ; /* Initialize command line option strings. */
383 if ((ptr = strrchr(argv[0], '/')) != NULL)
384 read_str(&v->appname, ptr+1) ;
385 else read_str(&v->appname, argv[0]) ;
387 init_text() ; /* Setup text strings depending upon language. */
388 init_vars() ; /* Setup default values for variables. */
389 key_init() ; /* Determine numeric function keys. */
390 load_resources() ; /* Get resources from various places. */
391 read_resources() ; /* Read resources from merged database. */
392 get_options(argc, argv) ; /* Get command line arguments. */
393 if(application_args.session != NULL)
397 read_rcfiles() ; /* Read .dtcalcrc's files. */
399 make_frames() ; /* Create dtcalc window frames. */
401 v->shelf = NULL ; /* No selection for shelf initially. */
402 v->noparens = 0 ; /* No unmatched brackets initially. */
403 v->opsptr = 0 ; /* Nothing on the parentheses op stack. */
404 v->numsptr = 0 ; /* Nothing on the parenthese numeric stack. */
405 v->pending = 0 ; /* No initial pending command. */
406 if(application_args.session == NULL)
407 v->tstate = 0 ; /* Button values displayed first. */
408 v->hyperbolic = 0 ; /* Normal trig functions initially. */
409 v->inverse = 0 ; /* No inverse functions initially. */
411 srand48((long) time((time_t *) 0)) ; /* Seed random number generator. */
413 make_items() ; /* Create server images and fir frames. */
414 if(v->display[0] == 0)
415 do_clear() ; /* Initialize and clear display. */
417 if (v->rstate == TRUE) /* Show the memory register window? */
419 make_registers(MEM) ;
420 if (!v->iconic) win_display(FCP_REG, TRUE) ;
422 if (!v->iconic) win_display(FCP_MODE, TRUE) ;
423 show_display(v->MPdisp_val) ; /* Output in correct display mode. */
424 save_cmdline(argc, argv) ; /* Setup dtcalc command line. */
425 start_tool() ; /* Display the calculator. */
429 /* Dtcalc's customised math library error-handling routine. */
434 if (!v->started) return ;
435 STRCPY(v->display, errmes) ;
436 set_item(DISPLAYITEM, v->display) ;
439 set_item(OPITEM, vstrs[(int) V_CLR]) ;
442 /* Get boolean resource from database. */
444 get_bool_resource(enum res_type rtype, int *boolval)
446 char *val, tempstr[MAXLINE] ;
449 if ((val = get_resource(rtype)) == NULL) return(0) ;
450 STRCPY(tempstr, val) ;
451 len = strlen(tempstr) ;
452 for (n = 0; n < len; n++)
453 if (isupper(tempstr[n])) tempstr[n] = tolower(tempstr[n]) ;
454 if (EQUAL(tempstr, vstrs[(int) V_TRUE])) *boolval = TRUE ;
455 else *boolval = FALSE ;
460 /* Get button index for given character value, setting curwin,
461 * row and column appropriately. Note that if the value isn't found,
462 * then a value of TITEMS is returned. This is "chucked out" by
463 * process_item as being invalid.
465 * XXX: This routine can be improved by using a hash lookup table.
473 for (n = 0; n < TITEMS; n++) {
474 if (ch == buttons[n].value)
478 v->curwin = FCP_KEY ;
483 v->row = n / MAXCOLS ;
484 v->column = n - (v->row * MAXCOLS) ;
488 /* Get integer resource from database. */
490 get_int_resource(enum res_type rtype, int *intval)
494 if ((val = get_resource(rtype)) == NULL) return(0) ;
495 *intval = atoi(val) ;
500 /* Get keyboard equivalent from first character of localised string. */
503 get_key_val(char *val, char *str)
515 temp = buttons[n].str2;
517 temp = buttons[n].str;
520 STRCPY(v->pstr, temp) ;
525 /* Extract command line options. */
527 get_options(int argc, char *argv[])
529 char next[MAXLINE] ; /* The next command line parameter. */
530 char strval[MAXLINE] ;
537 if (argv[0][0] == '-' || argv[0][0] == '+')
541 case 'D' : v->MPdebug = TRUE ; /* MP debug info. to stderr. */
544 getparam(next, argv, opts[(int) O_ACCVAL]) ;
545 v->accuracy = atoi(next) ;
546 if (v->accuracy < 0 || v->accuracy > 9)
548 msg = (char *) XtMalloc(strlen(
549 opts[(int) O_ACCRANGE]) + 3);
550 sprintf(msg, "%s", opts[(int) O_ACCRANGE]);
551 _DtSimpleError (v->appname, DtWarning, NULL, msg);
557 msg = (char *) XtMalloc(strlen(opts[(int) O_MODE])+
559 sprintf(msg, opts[(int) O_MODE], next);
560 getparam(next, argv, msg) ;
562 STRCPY(strval, next) ;
563 len = strlen(strval) ;
564 for (i = 0; i < len; i++)
566 if (islower(strval[i]))
567 strval[i] = toupper(strval[i]) ;
569 if(strcmp(strval, "FINANCIAL") == 0)
570 v->modetype = FINANCIAL ;
571 else if(strcmp(strval, "LOGICAL") == 0)
572 v->modetype = LOGICAL ;
573 else if(strcmp(strval, "SCIENTIFIC") == 0)
574 v->modetype = SCIENTIFIC ;
577 msg = (char *) XtMalloc(strlen(opts[(int) O_MODE])+
579 sprintf(msg, opts[(int) O_MODE], next);
580 _DtSimpleError (v->appname, DtWarning, NULL, msg);
582 v->modetype = SCIENTIFIC ;
586 getparam(next, argv, opts[(int) O_BASE]) ;
587 STRCPY(strval, next) ;
588 len = strlen(strval) ;
589 for (i = 0; i < len; i++)
591 if (islower(strval[i]))
592 strval[i] = toupper(strval[i]) ;
594 if(strncmp(strval, "BIN", 3) == 0)
596 else if(strncmp(strval, "OCT", 3) == 0)
598 else if(strncmp(strval, "DEC", 3) == 0)
600 else if(strncmp(strval, "HEX", 3) == 0)
604 msg = (char *) XtMalloc(strlen(
605 opts[(int) O_BASE]) + 3);
606 sprintf(msg, "%s", opts[(int) O_BASE]);
607 _DtSimpleError (v->appname, DtWarning, NULL, msg);
612 case 'n' : if(strcmp(&argv[0][1], "notation") == 0)
615 msg = (char *) XtMalloc(strlen(
616 opts[(int) O_DISPLAY]) +
618 sprintf(msg, opts[(int) O_DISPLAY], next);
619 getparam(next, argv, msg) ;
621 STRCPY(strval, next) ;
622 len = strlen(strval) ;
623 for (i = 0; i < len; i++)
625 if (islower(strval[i]))
626 strval[i] = toupper(strval[i]) ;
628 if(strncmp(strval, "FIX", 3) == 0)
630 else if(strncmp(strval, "ENG", 3) == 0)
632 else if(strncmp(strval, "SCI", 3) == 0)
636 msg = (char *) XtMalloc(strlen(
637 opts[(int) O_DISPLAY]) +
639 sprintf(msg, opts[(int) O_DISPLAY], next);
640 _DtSimpleError (v->appname, DtWarning, NULL, msg);
646 else if(strcmp(&argv[0][1], "no_menu_bar") == 0)
649 application_args.menuBar = False;
652 case 't' : if(strcmp(&argv[0][1], "trig") == 0)
655 msg = (char *) XtMalloc(strlen(
656 opts[(int) O_TRIG]) +
658 sprintf(msg, opts[(int) O_TRIG], next);
659 getparam(next, argv, msg) ;
661 STRCPY(strval, next) ;
662 len = strlen(strval) ;
663 for (i = 0; i < len; i++)
665 if (islower(strval[i]))
666 strval[i] = toupper(strval[i]) ;
668 if(strncmp(strval, "DEG", 3) == 0)
670 else if(strncmp(strval, "RAD", 3) == 0)
672 else if(strncmp(strval, "GRAD", 4) == 0)
676 msg = (char *) XtMalloc(strlen(
677 opts[(int) O_TRIG]) +
679 sprintf(msg, opts[(int) O_TRIG], next);
680 _DtSimpleError (v->appname, DtWarning, NULL, msg);
686 case 's' : if(strcmp(&argv[0][1], "session") == 0)
689 getparam(next, argv, opts[(int) O_SESSION]) ;
690 application_args.session = XtNewString(next);
694 case 'v' : usage(v->progname) ;
707 getparam(char *s, char *argv[], char *errmes)
711 if (*argv != NULL && argv[0][0] != '-') STRCPY(s, *argv) ;
714 msg = (char *) XtMalloc(strlen(mess[(int) MESS_PARAM]) +
716 sprintf(msg, mess[(int) MESS_PARAM], errmes);
717 _DtSimpleError (v->appname, DtError, NULL, msg);
718 FPRINTF(stderr, mess[(int) MESS_PARAM], errmes) ;
724 /* Read .dtcalcrc file. */
726 get_rcfile(char *name)
728 char line[MAXLINE] ; /* Current line from the .dtcalcrc file. */
729 char tmp[MAXLINE] ; /* Used to extract definitions. */
730 double cval ; /* Current constant value being converted. */
731 int i ; /* Index to constant or function array. */
732 int isval ; /* Set to 'c' or 'f' for convertable line. */
734 FILE *rcfd ; /* File descriptor for dtcalc rc file. */
736 if ((rcfd = fopen(name, "r")) == NULL) return ;
738 /* Process the .dtcalcrc file. There are currently four types of
739 * records to look for:
741 * 1) Those starting with a hash in the first column are comments.
743 * 2) Lines starting with 'c' or 'C' in the first column are
744 * definitions for constants. The cC is followed by a digit in
745 * the range 0-9, then a space. This is followed by a number
746 * in fixed or scientific notation. Following this is an optional
747 * comment, which if found, will be used in the popup menu for
748 * the constants. If the comment is present, there must be at
749 * least one space between this and the preceding number.
751 * 3) Those starting with a 'f' or a 'F' in the first column are
752 * definitions for functions. The fF is followed by a digit in
753 * the range 0-9, then a space. This is followed by a function
754 * definition. Following this is an optional comment, which if
755 * found, will be used in the popup menu for the functions.
756 * If the comment is present, there must be at least one space
757 * between this and the preceding function definition.
759 * 4) Lines starting with a 'r' or a 'R' in the first column are
760 * definitions for the initial contents of the calculators
761 * memory registers. The rR is followed by a digit in the
762 * range 0-9, then a space. This is followed by a number in
763 * fixed or scientific notation. The rest of the line is ignored.
765 * All other lines are ignored.
767 * Two other things to note. There should be no embedded spaces in
768 * the function definitions, and whenever a backslash is found, that
769 * and the following character signify a control character, for
770 * example \g would be ascii 7.
773 while (fgets(line, MAXLINE, rcfd) != NULL)
776 if (line[0] == 'c' || line[0] == 'C') isval = 'c' ;
777 else if (line[0] == 'f' || line[0] == 'F') isval = 'f' ;
778 else if (line[0] == 'r' || line[0] == 'R') isval = 'r' ;
780 if (line[1] >= '0' && line[1] <= '9' && line[2] == ' ')
782 i = char_val(line[1]) ;
785 n = sscanf(&line[3], "%lf", &cval) ;
790 MPstr_to_num(&line[4], DEC, v->MPcon_vals[i]) ;
791 mpneg(v->MPcon_vals[i], v->MPcon_vals[i]) ;
794 MPstr_to_num(&line[3], DEC, v->MPcon_vals[i]) ;
797 else if (isval == 'f')
799 SSCANF(&line[3], "%s", tmp) ;
800 STRCPY(v->fun_vals[i], convert(tmp)) ;
802 else if (isval == 'r')
804 n = sscanf(&line[3], "%lf", &cval) ;
805 if (n == 1) MPstr_to_num(&line[3], DEC, v->MPmvals[i]) ;
809 for (n = 3; n < len; n++)
810 if (line[n] == ' ' || line[n] == '\n')
812 while (line[n] == ' ') n++ ;
813 line[strlen(line)-1] = '\0' ;
816 STRCPY(tmp, make_number(v->MPcon_vals[i], TRUE)) ;
817 SPRINTF(v->con_names[i], "%1d: %s [%s]",
821 SPRINTF(v->fun_names[i], "%1d: %s [%s]",
830 /* Get a string resource from database. */
832 get_str_resource(enum res_type rtype, char *strval)
837 if ((val = get_resource(rtype)) == NULL) return(0) ;
838 STRCPY(strval, val) ;
839 len = strlen(strval) ;
840 if(rtype != R_TRIG && rtype != R_DISPLAY)
842 for (i = 0; i < len; i++)
843 if (islower(strval[i])) strval[i] = toupper(strval[i]) ;
848 /* Grey out numeric buttons depending upon base. */
850 grey_buttons(enum base_type base)
853 int column, dim, i, n, row ;
855 for (i = 0; i < 16; i++)
858 if (isupper(val)) val = tolower(val) ;
859 for (n = 0; n < TITEMS; n++)
860 if (val == buttons[n].value) break ;
862 column = n - (row * MAXCOLS) ;
864 if (i < basevals[(int) base]) dim = FALSE ;
866 grey_button(row, column, dim) ;
870 /* Process right button menu selection. */
872 handle_menu_selection(int n, int item)
876 if (IS_KEY(v->pending, KEY_LPAR)) /* Are we inside parentheses? */
878 v->current = buttons[n].value ;
885 save_pending_values(buttons[n].value) ;
887 v->ismenu = 1 ; /* To prevent grey buttons being redrawn. */
894 /* Setup default values for various variables. */
898 int acc, i, n, size ;
900 v->accuracy = 2 ; /* Initial accuracy. */
901 v->base = DEC ; /* Initial base. */
902 v->dtype = FIX ; /* Initial number display mode. */
903 v->ttype = DEG ; /* Initial trigonometric type. */
904 v->modetype = SCIENTIFIC; /* Initial calculator mode. */
905 v->rstate = 0 ; /* No memory register frame display initially. */
906 v->frstate = 0 ; /* No fin. memory register frame display
908 v->iconic = FALSE ; /* Calctool not iconic by default. */
909 v->MPdebug = FALSE ; /* No debug info by default. */
910 v->MPerrors = TRUE ; /* No error information. */
911 acc = MAX_DIGITS + 12 ; /* MP internal accuracy. */
913 mpset(&acc, &size, &size) ;
915 v->hasicon = FALSE ; /* Use standard dtcalc icon by default. */
916 v->beep = TRUE ; /* Beep on error by default. */
917 v->error = 0 ; /* No calculator error initially. */
918 v->key_exp = 0 ; /* Not entering an exponent number. */
919 v->pending_op = 0 ; /* No pending arithmetic operation. */
920 v->titleline = NULL ; /* No User supplied title line. */
928 v->workspaces = NULL;
930 read_str(&v->iconlabel, lstrs[(int) L_LCALC]) ; /* Default icon label. */
932 MPstr_to_num("0.621", DEC, v->MPcon_vals[0]) ; /* kms/hr <=> miles/hr. */
933 MPstr_to_num("1.4142135623", DEC, v->MPcon_vals[1]) ; /* square root of 2 */
934 MPstr_to_num("2.7182818284", DEC, v->MPcon_vals[2]) ; /* e */
935 MPstr_to_num("3.1415926535", DEC, v->MPcon_vals[3]) ; /* pi */
936 MPstr_to_num("2.54", DEC, v->MPcon_vals[4]) ; /* cms <=> inch. */
937 MPstr_to_num("57.295779513", DEC, v->MPcon_vals[5]) ; /* degrees/radian. */
938 MPstr_to_num("1048576.0", DEC, v->MPcon_vals[6]) ; /* 2 ^ 20. */
939 MPstr_to_num("0.0353", DEC, v->MPcon_vals[7]) ; /* grams <=> ounce. */
940 MPstr_to_num("0.948", DEC, v->MPcon_vals[8]) ; /* Kjoules <=> BTU's. */
941 MPstr_to_num("0.0610", DEC, v->MPcon_vals[9]) ; /* cms3 <=> inches3. */
944 for (i = 0; i < MAXREGS; i++) mpcim(&n, v->MPmvals[i]) ;
945 for (i = 0; i < FINREGS; i++)
946 v->MPfvals[i] = (double)n;
947 v->MPfvals[FINREGS - 1] = (double)12;
956 v->error = 0 ; /* Currently no display error. */
957 v->cur_op = '?' ; /* No arithmetic operator defined yet. */
958 v->old_cal_value = '?' ;
960 mpcim(&i, v->MPresult) ; /* No previous result yet. */
961 mpcim(&i, v->MPlast_input) ;
965 /* Convert engineering or scientific number. */
967 make_eng_sci(int *MPnumber)
969 char fixed[MAX_DIGITS+1], *optr ;
970 int MP1[MP_SIZE], MPatmp[MP_SIZE], MPval[MP_SIZE] ;
971 int MP1base[MP_SIZE], MP3base[MP_SIZE], MP10base[MP_SIZE] ;
972 int i, dval, len, n ;
973 int MPmant[MP_SIZE] ; /* Mantissa. */
974 int ddig ; /* Number of digits in exponent. */
975 int eng = 0 ; /* Set if this is an engineering number. */
976 int exp = 0 ; /* Exponent */
978 if (v->dtype == ENG) eng = 1 ;
980 mpabs(MPnumber, MPval) ;
983 if (mplt(MPnumber, MP1)) *optr++ = '-' ;
984 mpstr(MPval, MPmant) ;
986 mpcim(&basevals[(int) v->base], MP1base) ;
988 mppwr(MP1base, &n, MP3base) ;
991 mppwr(MP1base, &n, MP10base) ;
995 mpdiv(MP1, MP10base, MPatmp) ;
999 if (!mpeq(MPmant, MP1))
1001 while (mpge(MPmant, MP10base))
1004 mpmul(MPmant, MPatmp, MPmant) ;
1007 while ((!eng && mpge(MPmant, MP1base)) ||
1008 (eng && (mpge(MPmant, MP3base) || exp % 3 != 0)))
1011 mpdiv(MPmant, MP1base, MPmant) ;
1014 while (mplt(MPmant, MPatmp))
1017 mpmul(MPmant, MP10base, MPmant) ;
1022 while (mplt(MPmant, MP1) || (eng && exp % 3 != 0))
1025 mpmul(MPmant, MP1base, MPmant) ;
1029 STRCPY(fixed, make_fixed(MPmant, MAX_DIGITS-6)) ;
1030 len = strlen(fixed) ;
1031 for (i = 0; i < len; i++) *optr++ = fixed[i] ;
1040 else *optr++ = '+' ;
1042 MPstr_to_num("0.5", DEC, MP1) ;
1043 mpaddi(MP1, &exp, MPval) ;
1046 for (ddig = 0; mpge(MPval, MP1); ddig++)
1047 mpdiv(MPval, MP1base, MPval) ;
1049 if (ddig == 0) *optr++ = '0' ;
1053 mpmul(MPval, MP1base, MPval) ;
1054 mpcmi(MPval, &dval) ;
1055 *optr++ = digits[dval] ;
1057 mpaddi(MPval, &dval, MPval) ;
1065 /* Convert MP number to fixed number string. */
1066 /* cmax Maximum characters to generate. */
1068 make_fixed(int *MPnumber, int cmax)
1071 int MP1base[MP_SIZE], MP1[MP_SIZE], MP2[MP_SIZE], MPval[MP_SIZE] ;
1072 int ndig ; /* Total number of digits to generate. */
1073 int ddig ; /* Number of digits to left of . */
1077 mpabs(MPnumber, MPval) ;
1080 if (mplt(MPnumber, MP1)) *optr++ = '-' ;
1082 mpcim(&basevals[(int) v->base], MP1base) ;
1084 mppwr(MP1base, &v->accuracy, MP1) ;
1085 MPstr_to_num("0.5", DEC, MP2) ;
1086 mpdiv(MP2, MP1, MP1) ;
1087 mpadd(MPval, MP1, MPval) ;
1091 if (mplt(MPval, MP2))
1098 for (ddig = 0; mpge(MPval, MP2); ddig++)
1099 mpdiv(MPval, MP1base, MPval) ;
1101 ndig = MIN(ddig + v->accuracy, --cmax) ;
1105 if (ddig-- == 0) *optr++ = '.' ;
1106 mpmul(MPval, MP1base, MPval) ;
1107 mpcmi(MPval, &dval) ;
1108 *optr++ = digits[dval] ;
1110 mpaddi(MPval, &dval, MPval) ;
1122 set_item(DISPLAYITEM, v->display) ;
1123 set_item(OPITEM, " ") ;
1124 set_item(HYPITEM, " ") ;
1125 set_item(INVITEM, " ") ;
1128 /* Convert MP number to character string. */
1130 make_number(int *MPnumber, BOOLEAN mkFix)
1132 double number, val ;
1134 /* NOTE: make_number can currently set v->error when converting to a double.
1135 * This is to provide the same look&feel as V3 even though dtcalc
1136 * now does internal arithmetic to "infinite" precision.
1138 * XXX: Needs to be improved. Shouldn't need to convert to a double in
1139 * order to do these tests.
1142 mpcmd(MPnumber, &number) ;
1143 val = fabs(number) ;
1144 if (v->error) return(vstrs[(int) V_ERROR]) ;
1145 if (v->dtype == ENG || v->dtype == SCI ||
1146 (v->dtype == FIX && val != 0.0 && (val > max_fix[(int) v->base])))
1147 return(make_eng_sci(MPnumber)) ;
1148 else if (v->dtype == FIX && val != 0.0 && mkFix)
1150 if(v->accuracy == 0)
1152 if(val <= min_fix0[(int) v->base])
1153 return(make_eng_sci(MPnumber)) ;
1155 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1157 else if(v->accuracy == 1)
1159 if(val <= min_fix1[(int) v->base])
1160 return(make_eng_sci(MPnumber)) ;
1162 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1164 else if(v->accuracy == 2)
1166 if(val <= min_fix2[(int) v->base])
1167 return(make_eng_sci(MPnumber)) ;
1169 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1171 else if(v->accuracy == 3)
1173 if(val <= min_fix3[(int) v->base])
1174 return(make_eng_sci(MPnumber)) ;
1176 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1178 else if(v->accuracy == 4)
1180 if(val <= min_fix4[(int) v->base])
1181 return(make_eng_sci(MPnumber)) ;
1183 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1185 else if(v->accuracy == 5)
1187 if(val <= min_fix5[(int) v->base])
1188 return(make_eng_sci(MPnumber)) ;
1190 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1192 else if(v->accuracy == 6)
1194 if(val <= min_fix6[(int) v->base])
1195 return(make_eng_sci(MPnumber)) ;
1197 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1199 else if(v->accuracy == 7)
1201 if(val <= min_fix7[(int) v->base])
1202 return(make_eng_sci(MPnumber)) ;
1204 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1206 else if(v->accuracy == 8)
1208 if(val <= min_fix8[(int) v->base])
1209 return(make_eng_sci(MPnumber)) ;
1211 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1213 else if(v->accuracy == 9)
1215 if(val <= min_fix9[(int) v->base])
1216 return(make_eng_sci(MPnumber)) ;
1218 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1222 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1226 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1231 /* Default math library exception handling routine. */
1233 matherr(struct exception *exc)
1239 strcpy(msg, exc->name);
1241 if(exc->type == DOMAIN)
1242 strcat(msg, "DOMAIN ");
1243 else if(exc->type == SING)
1244 strcat(msg, "SING ");
1245 else if(exc->type == OVERFLOW)
1246 strcat(msg, "OVERFLOW ");
1247 else if(exc->type == UNDERFLOW)
1248 strcat(msg, "UNDERFLOW ");
1249 else if(exc->type == TLOSS)
1250 strcat(msg, "TLOSS ");
1251 else if(exc->type == PLOSS)
1252 strcat(msg, "PLOSS ");
1254 strcat(msg, vstrs[(int) V_ERROR]);
1256 _DtSimpleError (v->appname, DtWarning, NULL, msg);
1260 doerr(vstrs[(int) V_ERROR]) ;
1261 return(1) ; /* Value ignored. */
1264 /* Convert string into an MP number. */
1266 MPstr_to_num(char *str, enum base_type base, int *MPval)
1269 int MP1[MP_SIZE], MP2[MP_SIZE], MPbase[MP_SIZE] ;
1277 mpcim(&basevals[(int) base], MPbase) ;
1279 while (*optr == ' ') optr++ ;
1282 /* negative number */
1286 while ((inum = char_val(*optr)) >= 0)
1288 mpmul(MPval, MPbase, MPval) ;
1289 mpaddi(MPval, &inum, MPval) ;
1294 for (i = 1; (inum = char_val(*++optr)) >= 0; i++)
1296 mppwr(MPbase, &i, MP1) ;
1298 mpdiv(MP2, MP1, MP1) ;
1299 mpadd(MPval, MP1, MPval) ;
1302 while (*optr == ' ') optr++ ;
1306 if (*optr == '-') exp_sign = -1 ;
1308 while ((inum = char_val(*++optr)) >= 0)
1309 exp = exp * basevals[(int) base] + inum ;
1313 if (v->key_exp || exp_sign == -1)
1315 mppwr(MPbase, &exp, MP1) ;
1316 mpmul(MPval, MP1, MPval) ;
1322 mpmul(MPval, MP1, MPval) ;
1326 /* Append the latest parenthesis char to the display item. */
1332 /* If the character is a Delete, clear the whole line, and exit parenthesis
1335 * If the character is a Back Space, remove the last character. If the last
1336 * character was a left parenthesis, decrement the parentheses count. If
1337 * the parentheses count is zero, exit parenthesis processing.
1339 * If the character is a control character (not Ctrl-h), then append ^(char).
1341 * Otherwise just append the character.
1344 n = strlen(v->display) ;
1345 if (IS_KEY(c, KEY_CLR)) /* Is it a Delete character? */
1347 v->noparens = v->pending = v->opsptr = v->numsptr = 0 ;
1349 set_item(OPITEM, "") ;
1351 mpcim(&i, v->MPdisp_val) ;
1352 show_display(v->MPdisp_val) ;
1354 set_numtype(v->dtype);
1355 set_option_menu((int) TTYPEITEM, (int)v->ttype);
1357 v->curwin = FCP_KEY ;
1361 else if (IS_KEY(c, KEY_BSP)) /* Is is a Back Space character? */
1364 if (v->display[n-1] == '(')
1369 v->pending = v->opsptr = v->numsptr = 0 ;
1371 set_item(OPITEM, "") ;
1372 show_display(v->MPdisp_val) ;
1376 v->display[n-1] = '\0' ;
1378 else if (c <= CTL('z')) /* Is it a control character? */
1382 v->display[n] = '^' ;
1383 v->display[n+1] = c + 96 ;
1384 v->display[n+2] = '\0' ;
1387 else /* It must be an ordinary character. */
1392 v->display[n+1] = '\0' ;
1396 n = (n < MAX_DIGITS) ? 0 : n - MAX_DIGITS ;
1397 v->show_paren = 1 ; /* Hack to get set_item to really display it. */
1398 set_item(DISPLAYITEM, &v->display[n]) ;
1402 /* Process this event. */
1404 process_event(int type)
1410 case KEYBOARD_DOWN : if (v->pending)
1412 v->current = v->cur_ch ;
1417 ival = get_index(v->cur_ch) ;
1418 if (ival < TITEMS - EXTRA) {
1419 if ((v->modetype == FINANCIAL &&
1421 (v->modetype == LOGICAL && (
1422 ival == 21 || ival == 22 ||
1426 /* go arm the button */
1427 draw_button(ival, v->curwin, v->row,
1430 process_item(ival) ;
1434 case KEYBOARD_UP : ival = get_index(v->cur_ch) ;
1435 if (ival < TITEMS - EXTRA) {
1436 if ((v->modetype == FINANCIAL &&
1438 (v->modetype == LOGICAL && (
1439 ival == 21 || ival == 22 ||
1443 /* go disarm the button */
1444 draw_button(ival, v->curwin, v->row,
1447 /* go disarm the button */
1448 draw_button(ival, v->curwin, v->row,
1461 if (n < 0 || n >= TITEMS)
1467 v->current = buttons[n].value ;
1468 if (v->current == '*') v->current = 'x' ; /* Reassign "extra" values. */
1469 if (v->current == '\015') v->current = '=' ;
1470 if (v->current == 'Q') v->current = 'q' ;
1474 isvalid = 0 ; /* Must press a valid key first. */
1475 for (i = 0; i < MAXVKEYS; i++)
1476 if (v->current == validkeys[i]) isvalid = 1 ;
1477 if (v->pending == '?') isvalid = 1 ;
1478 if (!isvalid) return ;
1484 if (v->pending_win == FCP_KEY) (*buttons[v->pending_n].func)() ;
1485 else (*mode_buttons[MODEKEYS * ((int) v->pending_mode - 1) +
1486 v->pending_n].func)() ;
1489 switch (buttons[n].opdisp)
1492 if (v->current == 'T')
1494 if (v->modetype == SCIENTIFIC)
1495 set_item(OPITEM, buttons[n].str) ;
1500 set_item(OPITEM, buttons[n].str) ;
1504 set_item(OPITEM, vstrs[(int) V_CLR]) ;
1506 set_item(OPITEM, "") ;
1511 (*buttons[n].func)() ;
1513 if(strcmp(buttons[n].resname, "clr") != 0)
1518 /* Process a portion of the parentheses stack.
1519 startop Initial position in the operand stack.
1520 startnum Initial position in the numeric stack.
1521 n Number of items to process.
1525 process_stack(int startop, int startnum, int n)
1527 char sdisp[MAXLINE] ; /* Used to save display contents. */
1529 int nptr ; /* Pointer to next number from numeric stack. */
1531 STRCPY(sdisp, v->display) ; /* Save current display. */
1534 v->cur_op = '?' ; /* Current operation is initially undefined. */
1535 for (i = 0; i < n; i++)
1537 if (v->opstack[startop + i] == -1)
1539 mpstr(v->MPnumstack[nptr++], v->MPdisp_val) ;
1543 v->cur_ch = v->opstack[startop + i] ;
1544 if (v->cur_ch == '^') /* Control character? */
1547 v->cur_ch = CTL(v->opstack[startop + i]) ;
1551 v->current = v->cur_ch ;
1554 else process_item(get_index(v->cur_ch)) ;
1557 v->numsptr = startnum ;
1558 push_num(v->MPdisp_val) ;
1559 v->opsptr = startop - 1 ;
1561 save_pending_values(KEY_LPAR) ;
1562 STRCPY(v->display, sdisp) ; /* Restore current display. */
1567 process_str(char *str, enum menu_type mtype)
1573 STRCPY(save, v->display) ;
1574 STRCPY(v->display, " ") ;
1575 set_item(DISPLAYITEM, v->display);
1576 for (i = 0 ; i < len; i++)
1584 STRCPY(v->display, save);
1585 set_item(DISPLAYITEM, v->display);
1592 v->current = str[i] ;
1611 process_item(get_index(str[i])) ;
1618 read_rcfiles(void) /* Read .dtcalcrc's from home and current directories. */
1620 char *home ; /* Pathname for users home directory. */
1621 char name[MAXPATHLEN + 50] ; /* Full name of users .dtcalcrc file. */
1622 char pathname[MAXPATHLEN + 5] ; /* Current working directory. */
1623 char tmp[MAXLINE] ; /* For temporary constant string creation. */
1625 struct passwd *entry ;
1627 for (n = 0; n < MAXREGS; n++)
1629 STRCPY(tmp, make_number(v->MPcon_vals[n], FALSE)) ;
1630 SPRINTF(name, "%1d: %s [%s]", n, tmp, v->con_names[n]) ;
1632 STRCPY(v->con_names[n], name) ;
1633 STRCPY(v->fun_vals[n], "") ; /* Initially empty function strings. */
1636 if ((home = getenv("HOME")) == NULL)
1638 if ((entry = getpwuid(getuid())) == NULL) return ;
1639 home = entry->pw_dir ;
1641 snprintf(name, MAXPATHLEN, "%s/%s", home, RCNAME) ;
1642 get_rcfile(name) ; /* Read .dtcalcrc from users home directory. */
1644 snprintf(name, MAXPATHLEN, "%s/%s", getcwd(pathname, MAXPATHLEN+1), RCNAME) ;
1645 get_rcfile(name) ; /* Read .dtcalcrc file from current directory. */
1650 show_display(int *MPval)
1654 STRCPY(v->display, make_number(MPval, TRUE)) ;
1655 set_item(DISPLAYITEM, v->display) ;
1661 usage(char *progname)
1663 FPRINTF(stderr, ustrs[(int) USAGE1], PATCHLEVEL) ;
1664 FPRINTF(stderr, "%s", ustrs[(int) USAGE2]) ;
1665 FPRINTF(stderr, "%s", ustrs[(int) USAGE3]) ;
1670 write_rcfile(enum menu_type mtype, int exists, int cfno, char *val, char *comment)
1672 char *home ; /* Pathname for users home directory. */
1673 char pathname[MAXPATHLEN] ; /* Current working directory. */
1674 char rcname[MAXPATHLEN] ; /* Full name of users .dtcalcrc file. */
1675 char str[MAXLINE] ; /* Temporary buffer. */
1676 char sval[3] ; /* Used for string comparisons. */
1677 char tmp_filename[MAXLINE] ; /* Used to construct temp filename. */
1678 int rcexists ; /* Set to 1, if .dtcalcrc file exists. */
1679 FILE *rcfd ; /* File descriptor for .dtcalcrc file. */
1680 FILE *tmpfd ; /* File descriptor for new temp .dtcalcrc. */
1681 struct passwd *entry ; /* The user's /etc/passwd entry. */
1684 SPRINTF(rcname, "%s/%s", getcwd(pathname, MAXPATHLEN), RCNAME) ;
1685 if (access(rcname, F_OK) == 0) rcexists = 1 ;
1688 if ((home = getenv("HOME")) == NULL)
1690 if ((entry = getpwuid(getuid())) == NULL) return ;
1691 home = entry->pw_dir ;
1693 SPRINTF(rcname, "%s/%s", home, RCNAME) ;
1694 if (access(rcname, F_OK) == 0) rcexists = 1 ;
1696 STRCPY(tmp_filename, "/tmp/.dtcalcrcXXXXXX") ;
1697 MKTEMP(tmp_filename) ;
1698 if ((tmpfd = fopen(tmp_filename, "w+")) == NULL) return ;
1702 rcfd = fopen(rcname, "r") ;
1703 SPRINTF(sval, " %1d", cfno) ;
1704 while (fgets(str, MAXLINE, rcfd))
1710 case M_CON : sval[0] = 'c' ;
1711 if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1713 if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1715 case M_FUN : sval[0] = 'f' ;
1716 if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1718 if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1723 FPRINTF(tmpfd, "%s", str) ;
1730 case M_CON : FPRINTF(tmpfd, "\nC%1d %s %s\n", cfno, val, comment) ;
1733 if(strcmp(val, "") != 0)
1734 FPRINTF(tmpfd, "\nF%1d %s %s\n", cfno, val, comment) ;
1739 rcfd = fopen(rcname, "w") ;
1741 while (fgets(str, MAXLINE, tmpfd)) FPRINTF(rcfd, "%s", str) ;
1744 UNLINK(tmp_filename) ;
1749 write_resources(char *filename)
1752 int MPtemp[MP_SIZE];
1754 SPRINTF(intval, "%d", v->accuracy) ;
1755 put_resource(R_ACCURACY, intval) ;
1756 put_resource(R_DISPLAYED, v->display) ;
1757 put_resource(R_BASE, base_str[(int) v->base]) ;
1758 put_resource(R_DISPLAY, dtype_str[(int) v->dtype]) ;
1759 put_resource(R_MODE, mode_str[(int) v->modetype]) ;
1760 put_resource(R_TRIG, ttype_str[(int) v->ttype]) ;
1761 put_resource(R_REGS, set_bool(v->rstate == TRUE)) ;
1763 put_resource(R_REG0, make_number(v->MPmvals[0], FALSE)) ;
1764 put_resource(R_REG1, make_number(v->MPmvals[1], FALSE)) ;
1765 put_resource(R_REG2, make_number(v->MPmvals[2], FALSE)) ;
1766 put_resource(R_REG3, make_number(v->MPmvals[3], FALSE)) ;
1767 put_resource(R_REG4, make_number(v->MPmvals[4], FALSE)) ;
1768 put_resource(R_REG5, make_number(v->MPmvals[5], FALSE)) ;
1769 put_resource(R_REG6, make_number(v->MPmvals[6], FALSE)) ;
1770 put_resource(R_REG7, make_number(v->MPmvals[7], FALSE)) ;
1771 put_resource(R_REG8, make_number(v->MPmvals[8], FALSE)) ;
1772 put_resource(R_REG9, make_number(v->MPmvals[9], FALSE)) ;
1774 mpcdm(&(v->MPfvals[0]), MPtemp);
1775 put_resource(R_FREG0, make_number(MPtemp, FALSE)) ;
1776 mpcdm(&(v->MPfvals[1]), MPtemp);
1777 put_resource(R_FREG1, make_number(MPtemp, FALSE)) ;
1778 mpcdm(&(v->MPfvals[2]), MPtemp);
1779 put_resource(R_FREG2, make_number(MPtemp, FALSE)) ;
1780 mpcdm(&(v->MPfvals[3]), MPtemp);
1781 put_resource(R_FREG3, make_number(MPtemp, FALSE)) ;
1782 mpcdm(&(v->MPfvals[4]), MPtemp);
1783 put_resource(R_FREG4, make_number(MPtemp, FALSE)) ;
1784 mpcdm(&(v->MPfvals[5]), MPtemp);
1785 put_resource(R_FREG5, make_number(MPtemp, FALSE)) ;
1787 save_resources(filename) ;