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"
52 6.871947674e+10, 3.245185537e+32,
53 1.000000000e+36, 2.230074520e+43
55 double min_fix0[4] = {
56 2.500000000e-1, 3.750000000e-1,
57 1.000000000e-1, 4.375000000e-1
59 double min_fix1[4] = {
60 1.250000000e-1, 4.687500000e-2,
61 1.000000000e-2, 2.734375000e-2
63 double min_fix2[4] = {
64 6.250000000e-2, 5.859375000e-3,
65 1.000000000e-3, 1.708984375e-3
67 double min_fix3[4] = {
68 3.125000000e-2, 7.324218750e-4,
69 1.000000000e-4, 1.068115234e-4
71 double min_fix4[4] = {
72 1.562500000e-2, 9.155273437e-5,
73 1.000000000e-5, 6.675720215e-6
75 double min_fix5[4] = {
76 7.812500000e-3, 1.144409180e-5,
77 1.000000000e-6, 4.172325134e-7
79 double min_fix6[4] = {
80 6.906250000e-3, 1.430511475e-6,
81 1.000000000e-7, 2.607703209e-8
83 double min_fix7[4] = {
84 1.953125000e-3, 1.788139343e-7,
85 1.000000000e-8, 1.629814506e-9
87 double min_fix8[4] = {
88 9.765625000e-4, 2.235174179e-8,
89 1.000000000e-9, 1.018634066e-10
91 double min_fix9[4] = {
92 4.882812500e-4, 2.793967724e-9,
93 1.000000000e-10, 6.366462912e-12
96 extern char *base_str[] ; /* Strings for each base value. */
97 extern char *cmdstr[] ; /* Strings for each command line option. */
98 extern char *dtype_str[] ; /* Strings for each display mode value. */
99 extern char *lstrs[] ; /* Labels for various Motif items. */
100 extern char *mess[] ; /* Message strings. */
101 extern char *mode_str[] ; /* Strings for each mode value. */
102 extern char *opts[] ; /* Command line option strings. */
103 extern char *ttype_str[] ; /* Strings for each trig type value. */
104 extern char *ustrs[] ; /* Usage message strings. */
105 extern char *vstrs[] ; /* Various strings. */
107 char digits[] = "0123456789ABCDEF" ;
108 int basevals[4] = { 2, 8, 10, 16 } ;
110 int left_pos[BCOLS] = { 3, 2, 1, 0 } ; /* Left positions. */
111 int right_pos[BCOLS] = { 0, 1, 2, 3 } ; /* "Right" positions. */
113 /* Valid keys when an error condition has occurred. */
114 /* MEM KEYS clr clr QUIT REDRAW */
115 char validkeys[MAXVKEYS] = { 'm', 'k', '\177', '\013', 'q', '\f' } ;
117 Vars v ; /* Calctool variables and options. */
119 struct menu_entry menu_entries[MAXENTRIES] ;
121 struct menu cmenus[MAXMENUS] = { /* Calculator menus. */
122 /* title total index defval */
123 { (char *) NULL, 10, 0, 2 /* 2 places */ }, /* ACC */
124 { (char *) NULL, 4, 20, 2 /* Decimal */ }, /* BASE TYPE */
125 { (char *) NULL, 10, 0, 0 /* Con. 0 */ }, /* CON */
126 { (char *) NULL, 10, 10, 0 /* Reg. 0 */ }, /* EXCH */
127 { (char *) NULL, 10, 0, 0 /* Fun. 0 */ }, /* FUN */
128 { (char *) NULL, 4, 30, 0 /* Basic */ }, /* MODE */
129 { (char *) NULL, 3, 24, 1 /* Fixed */ }, /* NUM TYPE */
130 { (char *) NULL, 10, 10, 0 /* Reg. 0 */ }, /* RCL */
131 { (char *) NULL, 10, 10, 0 /* Reg. 0 */ }, /* STO */
132 { (char *) NULL, 3, 27, 0 /* Degrees */ }, /* TRIG TYPE */
135 /* This table shows the keyboard values that are currently being used:
137 * | 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
138 *-------------+--------------------------------------------------
139 * Control: | a c d f h i l m r s t u y
140 * Lower: | a b c d e f h i k m n p q r s v x y
141 * Upper: | A B C D E F G M N P Q R S T X
142 * Numeric: | 0 1 2 3 4 5 6 7 8 9
143 * Other: | @ . + - * / = % ( ) # < > [ ] { } | & ~ ^ ? ! \177
144 *----------------------------------------------------------------
147 /* Calculator button values. */
149 struct button buttons[TITEMS] = {
150 /* str str2 value opdisp menutype resname func */
153 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
154 { (char *)NULL, (char *)NULL, 0, OP_SET, M_FUN, "fun", do_pending },
155 { (char *)NULL, (char *)NULL, 0, OP_SET, M_CON, "con", do_pending },
156 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "keys", do_keys },
159 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "int", do_portion },
160 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "frac", do_portion },
161 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "abs", do_portion },
162 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "exp", do_expno },
165 { (char *)NULL, (char *)NULL, 0, OP_SET, M_ACC, "acc", do_pending },
166 { (char *)NULL, (char *)NULL, 0, OP_SET, M_STO, "sto", do_pending },
167 { (char *)NULL, (char *)NULL, 0, OP_SET, M_RCL, "rcl", do_pending },
168 { (char *)NULL, (char *)NULL, 0, OP_SET, M_EXCH, "exch", do_pending },
171 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
172 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
173 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
174 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
177 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
178 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
179 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
180 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
183 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "blank", do_none },
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 },
189 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "recip", do_immed },
190 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "square", do_immed },
191 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "sqrt", do_immed },
192 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "percent", do_calc },
195 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "lparen", do_paren },
196 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "rparen", do_paren },
197 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "bsp", do_delete },
198 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "clr", do_clear },
201 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "numd", do_number },
202 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "nume", do_number },
203 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "numf", do_number },
204 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "chs", do_immed },
207 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "numa", do_number },
208 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "numb", do_number },
209 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "numc", do_number },
210 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "mul", do_calc },
213 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num7", do_number },
214 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num8", do_number },
215 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num9", do_number },
216 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "div", do_calc },
219 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num4", do_number },
220 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num5", do_number },
221 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num6", do_number },
222 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "sub", do_calc },
225 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num1", do_number },
226 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num2", do_number },
227 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num3", do_number },
228 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "add", do_calc },
231 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "num0", do_number },
232 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "point", do_point },
233 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "equals", do_calc },
234 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "quit", do_frame },
236 { (char *)NULL, (char *)NULL, 0, OP_SET, M_BASE, "base", do_pending },
237 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NUM, "disp", do_pending },
238 { (char *)NULL, (char *)NULL, 0, OP_SET, M_MODE, "mode", do_pending },
239 { (char *)NULL, (char *)NULL, 0, OP_SET, M_TRIG, "trig", do_pending },
242 struct button mode_buttons[MAXMODES * MODEKEYS] = {
243 /* str str2 value opdisp menutype resname func */
246 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "term", do_business},
247 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "rate", do_business},
248 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "pv", do_business},
249 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "pmt", do_business},
250 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "fv", do_business},
251 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "ppy", do_business},
252 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "clrreg", do_business},
253 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "ctrm", do_business},
254 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "ddb", do_business},
255 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "sln", do_business},
256 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "syd", do_business},
257 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
258 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
259 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
260 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
261 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
264 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "lshift", do_pending },
265 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "rshift", do_pending },
266 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "and16", do_immed },
267 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "and32", do_immed },
268 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "or", do_calc },
269 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "and", do_calc },
270 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "not", do_immed },
271 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "xor", do_calc },
272 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "xnor", do_calc },
273 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
274 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
275 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
276 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
277 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
278 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
279 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
282 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "inv", do_immed },
283 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "hyp", do_immed },
284 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "etox", do_immed },
285 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "tentox", do_immed },
286 { (char *)NULL, (char *)NULL, 0, OP_SET, M_NONE, "ytox", do_calc },
287 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "xfact", do_immed },
288 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "cos", do_trig },
289 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "sin", do_trig },
290 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "tan", do_trig },
291 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "ln", do_immed },
292 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "log", do_immed },
293 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE, "rand", do_immed },
294 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
295 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
296 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
297 { (char *)NULL, (char *)NULL, 0, OP_NOP, M_NONE, "", do_none },
304 if (chr >= '0' && chr <= '9') return(chr - '0') ;
305 else if (chr >= 'a' && chr <= 'f') return(chr - 'a' + 10) ;
306 else if (chr >= 'A' && chr <= 'F') return(chr - 'A' + 10) ;
320 mpcim(&i, v->MPdisp_val) ;
321 STRCPY(v->display, make_number(v->MPdisp_val, FALSE)) ;
322 set_item(DISPLAYITEM, v->display) ;
327 v->opsptr = 0 ; /* Clear parentheses stacks. */
329 set_item(HYPITEM, " ") ;
330 set_item(INVITEM, " ") ;
333 /* Convert .dtcalcrc line to ascii values. */
334 /* line Input line to be converted. */
338 static char output[MAXLINE] ; /* Converted output record. */
339 int ctrl = 0 ; /* Set if we are processing a control character. */
340 int i ; /* Position within input line. */
342 int n = 0 ; /* Position within output line. */
345 for (i = 0; i < len; i++)
347 if (line[i] == ' ') continue ;
348 else if (line[i] == '\\') ctrl = 1 ;
351 output[n++] = CTL(line[i]) ;
354 else output[n++] = line[i] ;
362 do_dtcalc(int argc, char **argv)
366 v->progname = argv[0] ; /* Save programs name. */
368 init_cmdline_opts() ; /* Initialize command line option strings. */
370 if ((ptr = strrchr(argv[0], '/')) != NULL)
371 read_str(&v->appname, ptr+1) ;
372 else read_str(&v->appname, argv[0]) ;
374 init_text() ; /* Setup text strings depending upon language. */
375 init_vars() ; /* Setup default values for variables. */
376 key_init() ; /* Determine numeric function keys. */
377 load_resources() ; /* Get resources from various places. */
378 read_resources() ; /* Read resources from merged database. */
379 get_options(argc, argv) ; /* Get command line arguments. */
380 if(application_args.session != NULL)
384 read_rcfiles() ; /* Read .dtcalcrc's files. */
386 make_frames() ; /* Create dtcalc window frames. */
388 v->shelf = NULL ; /* No selection for shelf initially. */
389 v->noparens = 0 ; /* No unmatched brackets initially. */
390 v->opsptr = 0 ; /* Nothing on the parentheses op stack. */
391 v->numsptr = 0 ; /* Nothing on the parenthese numeric stack. */
392 v->pending = 0 ; /* No initial pending command. */
393 if(application_args.session == NULL)
394 v->tstate = 0 ; /* Button values displayed first. */
395 v->hyperbolic = 0 ; /* Normal trig functions initially. */
396 v->inverse = 0 ; /* No inverse functions initially. */
398 srand48((long) time((time_t *) 0)) ; /* Seed random number generator. */
400 make_items() ; /* Create server images and fir frames. */
401 if(v->display[0] == 0)
402 do_clear() ; /* Initialize and clear display. */
404 if (v->rstate == TRUE) /* Show the memory register window? */
406 make_registers(MEM) ;
407 if (!v->iconic) win_display(FCP_REG, TRUE) ;
409 if (!v->iconic) win_display(FCP_MODE, TRUE) ;
410 show_display(v->MPdisp_val) ; /* Output in correct display mode. */
411 save_cmdline(argc, argv) ; /* Setup dtcalc command line. */
412 start_tool() ; /* Display the calculator. */
416 /* Dtcalc's customised math library error-handling routine. */
421 if (!v->started) return ;
422 STRCPY(v->display, errmes) ;
423 set_item(DISPLAYITEM, v->display) ;
426 set_item(OPITEM, vstrs[(int) V_CLR]) ;
429 /* Get boolean resource from database. */
431 get_bool_resource(enum res_type rtype, int *boolval)
433 char *val, tempstr[MAXLINE] ;
436 if ((val = get_resource(rtype)) == NULL) return(0) ;
437 STRCPY(tempstr, val) ;
438 len = strlen(tempstr) ;
439 for (n = 0; n < len; n++)
440 if (isupper(tempstr[n])) tempstr[n] = tolower(tempstr[n]) ;
441 if (EQUAL(tempstr, vstrs[(int) V_TRUE])) *boolval = TRUE ;
442 else *boolval = FALSE ;
447 /* Get button index for given character value, setting curwin,
448 * row and column appropriately. Note that if the value isn't found,
449 * then a value of TITEMS is returned. This is "chucked out" by
450 * process_item as being invalid.
452 * XXX: This routine can be improved by using a hash lookup table.
460 for (n = 0; n < TITEMS; n++) {
461 if (ch == buttons[n].value)
465 v->curwin = FCP_KEY ;
470 v->row = n / MAXCOLS ;
471 v->column = n - (v->row * MAXCOLS) ;
475 /* Get integer resource from database. */
477 get_int_resource(enum res_type rtype, int *intval)
481 if ((val = get_resource(rtype)) == NULL) return(0) ;
482 *intval = atoi(val) ;
487 /* Get keyboard equivalent from first character of localised string. */
490 get_key_val(char *val, char *str)
502 temp = buttons[n].str2;
504 temp = buttons[n].str;
507 STRCPY(v->pstr, temp) ;
512 /* Extract command line options. */
514 get_options(int argc, char *argv[])
516 char next[MAXLINE] ; /* The next command line parameter. */
517 char strval[MAXLINE] ;
524 if (argv[0][0] == '-' || argv[0][0] == '+')
528 case 'D' : v->MPdebug = TRUE ; /* MP debug info. to stderr. */
531 getparam(next, argv, opts[(int) O_ACCVAL]) ;
532 v->accuracy = atoi(next) ;
533 if (v->accuracy < 0 || v->accuracy > 9)
535 msg = (char *) XtMalloc(strlen(
536 opts[(int) O_ACCRANGE]) + 3);
537 sprintf(msg, "%s", opts[(int) O_ACCRANGE]);
538 _DtSimpleError (v->appname, DtWarning, NULL, msg);
544 msg = (char *) XtMalloc(strlen(opts[(int) O_MODE])+
546 sprintf(msg, opts[(int) O_MODE], next);
547 getparam(next, argv, msg) ;
549 STRCPY(strval, next) ;
550 len = strlen(strval) ;
551 for (i = 0; i < len; i++)
553 if (islower(strval[i]))
554 strval[i] = toupper(strval[i]) ;
556 if(strcmp(strval, "FINANCIAL") == 0)
557 v->modetype = FINANCIAL ;
558 else if(strcmp(strval, "LOGICAL") == 0)
559 v->modetype = LOGICAL ;
560 else if(strcmp(strval, "SCIENTIFIC") == 0)
561 v->modetype = SCIENTIFIC ;
564 msg = (char *) XtMalloc(strlen(opts[(int) O_MODE])+
566 sprintf(msg, opts[(int) O_MODE], next);
567 _DtSimpleError (v->appname, DtWarning, NULL, msg);
569 v->modetype = SCIENTIFIC ;
573 getparam(next, argv, opts[(int) O_BASE]) ;
574 STRCPY(strval, next) ;
575 len = strlen(strval) ;
576 for (i = 0; i < len; i++)
578 if (islower(strval[i]))
579 strval[i] = toupper(strval[i]) ;
581 if(strncmp(strval, "BIN", 3) == 0)
583 else if(strncmp(strval, "OCT", 3) == 0)
585 else if(strncmp(strval, "DEC", 3) == 0)
587 else if(strncmp(strval, "HEX", 3) == 0)
591 msg = (char *) XtMalloc(strlen(
592 opts[(int) O_BASE]) + 3);
593 sprintf(msg, "%s", opts[(int) O_BASE]);
594 _DtSimpleError (v->appname, DtWarning, NULL, msg);
599 case 'n' : if(strcmp(&argv[0][1], "notation") == 0)
602 msg = (char *) XtMalloc(strlen(
603 opts[(int) O_DISPLAY]) +
605 sprintf(msg, opts[(int) O_DISPLAY], next);
606 getparam(next, argv, msg) ;
608 STRCPY(strval, next) ;
609 len = strlen(strval) ;
610 for (i = 0; i < len; i++)
612 if (islower(strval[i]))
613 strval[i] = toupper(strval[i]) ;
615 if(strncmp(strval, "FIX", 3) == 0)
617 else if(strncmp(strval, "ENG", 3) == 0)
619 else if(strncmp(strval, "SCI", 3) == 0)
623 msg = (char *) XtMalloc(strlen(
624 opts[(int) O_DISPLAY]) +
626 sprintf(msg, opts[(int) O_DISPLAY], next);
627 _DtSimpleError (v->appname, DtWarning, NULL, msg);
633 else if(strcmp(&argv[0][1], "no_menu_bar") == 0)
636 application_args.menuBar = False;
639 case 't' : if(strcmp(&argv[0][1], "trig") == 0)
642 msg = (char *) XtMalloc(strlen(
643 opts[(int) O_TRIG]) +
645 sprintf(msg, opts[(int) O_TRIG], next);
646 getparam(next, argv, msg) ;
648 STRCPY(strval, next) ;
649 len = strlen(strval) ;
650 for (i = 0; i < len; i++)
652 if (islower(strval[i]))
653 strval[i] = toupper(strval[i]) ;
655 if(strncmp(strval, "DEG", 3) == 0)
657 else if(strncmp(strval, "RAD", 3) == 0)
659 else if(strncmp(strval, "GRAD", 4) == 0)
663 msg = (char *) XtMalloc(strlen(
664 opts[(int) O_TRIG]) +
666 sprintf(msg, opts[(int) O_TRIG], next);
667 _DtSimpleError (v->appname, DtWarning, NULL, msg);
673 case 's' : if(strcmp(&argv[0][1], "session") == 0)
676 getparam(next, argv, opts[(int) O_SESSION]) ;
677 application_args.session = XtNewString(next);
681 case 'v' : usage(v->progname) ;
694 getparam(char *s, char *argv[], char *errmes)
698 if (*argv != NULL && argv[0][0] != '-') STRCPY(s, *argv) ;
701 msg = (char *) XtMalloc(strlen(mess[(int) MESS_PARAM]) +
703 sprintf(msg, mess[(int) MESS_PARAM], errmes);
704 _DtSimpleError (v->appname, DtError, NULL, msg);
705 FPRINTF(stderr, mess[(int) MESS_PARAM], errmes) ;
711 /* Read .dtcalcrc file. */
713 get_rcfile(char *name)
715 char line[MAXLINE] ; /* Current line from the .dtcalcrc file. */
716 char tmp[MAXLINE] ; /* Used to extract definitions. */
717 double cval ; /* Current constant value being converted. */
718 int i ; /* Index to constant or function array. */
719 int isval ; /* Set to 'c' or 'f' for convertable line. */
721 FILE *rcfd ; /* File descriptor for dtcalc rc file. */
723 if ((rcfd = fopen(name, "r")) == NULL) return ;
725 /* Process the .dtcalcrc file. There are currently four types of
726 * records to look for:
728 * 1) Those starting with a hash in the first column are comments.
730 * 2) Lines starting with 'c' or 'C' in the first column are
731 * definitions for constants. The cC is followed by a digit in
732 * the range 0-9, then a space. This is followed by a number
733 * in fixed or scientific notation. Following this is an optional
734 * comment, which if found, will be used in the popup menu for
735 * the constants. If the comment is present, there must be at
736 * least one space between this and the preceding number.
738 * 3) Those starting with a 'f' or a 'F' in the first column are
739 * definitions for functions. The fF is followed by a digit in
740 * the range 0-9, then a space. This is followed by a function
741 * definition. Following this is an optional comment, which if
742 * found, will be used in the popup menu for the functions.
743 * If the comment is present, there must be at least one space
744 * between this and the preceding function definition.
746 * 4) Lines starting with a 'r' or a 'R' in the first column are
747 * definitions for the initial contents of the calculators
748 * memory registers. The rR is followed by a digit in the
749 * range 0-9, then a space. This is followed by a number in
750 * fixed or scientific notation. The rest of the line is ignored.
752 * All other lines are ignored.
754 * Two other things to note. There should be no embedded spaces in
755 * the function definitions, and whenever a backslash is found, that
756 * and the following character signify a control character, for
757 * example \g would be ascii 7.
760 while (fgets(line, MAXLINE, rcfd) != NULL)
763 if (line[0] == 'c' || line[0] == 'C') isval = 'c' ;
764 else if (line[0] == 'f' || line[0] == 'F') isval = 'f' ;
765 else if (line[0] == 'r' || line[0] == 'R') isval = 'r' ;
767 if (line[1] >= '0' && line[1] <= '9' && line[2] == ' ')
769 i = char_val(line[1]) ;
772 n = sscanf(&line[3], "%lf", &cval) ;
777 MPstr_to_num(&line[4], DEC, v->MPcon_vals[i]) ;
778 mpneg(v->MPcon_vals[i], v->MPcon_vals[i]) ;
781 MPstr_to_num(&line[3], DEC, v->MPcon_vals[i]) ;
784 else if (isval == 'f')
786 SSCANF(&line[3], "%s", tmp) ;
787 STRCPY(v->fun_vals[i], convert(tmp)) ;
789 else if (isval == 'r')
791 n = sscanf(&line[3], "%lf", &cval) ;
792 if (n == 1) MPstr_to_num(&line[3], DEC, v->MPmvals[i]) ;
796 for (n = 3; n < len; n++)
797 if (line[n] == ' ' || line[n] == '\n')
799 while (line[n] == ' ') n++ ;
800 line[strlen(line)-1] = '\0' ;
803 STRCPY(tmp, make_number(v->MPcon_vals[i], TRUE)) ;
804 SPRINTF(v->con_names[i], "%1d: %s [%s]",
808 SPRINTF(v->fun_names[i], "%1d: %s [%s]",
817 /* Get a string resource from database. */
819 get_str_resource(enum res_type rtype, char *strval)
824 if ((val = get_resource(rtype)) == NULL) return(0) ;
825 STRCPY(strval, val) ;
826 len = strlen(strval) ;
827 if(rtype != R_TRIG && rtype != R_DISPLAY)
829 for (i = 0; i < len; i++)
830 if (islower(strval[i])) strval[i] = toupper(strval[i]) ;
835 /* Grey out numeric buttons depending upon base. */
837 grey_buttons(enum base_type base)
840 int column, dim, i, n, row ;
842 for (i = 0; i < 16; i++)
845 if (isupper(val)) val = tolower(val) ;
846 for (n = 0; n < TITEMS; n++)
847 if (val == buttons[n].value) break ;
849 column = n - (row * MAXCOLS) ;
851 if (i < basevals[(int) base]) dim = FALSE ;
853 grey_button(row, column, dim) ;
857 /* Process right button menu selection. */
859 handle_menu_selection(int n, int item)
863 if (IS_KEY(v->pending, KEY_LPAR)) /* Are we inside parentheses? */
865 v->current = buttons[n].value ;
872 save_pending_values(buttons[n].value) ;
874 v->ismenu = 1 ; /* To prevent grey buttons being redrawn. */
881 /* Setup default values for various variables. */
885 int acc, i, n, size ;
887 v->accuracy = 2 ; /* Initial accuracy. */
888 v->base = DEC ; /* Initial base. */
889 v->dtype = FIX ; /* Initial number display mode. */
890 v->ttype = DEG ; /* Initial trigonometric type. */
891 v->modetype = SCIENTIFIC; /* Initial calculator mode. */
892 v->rstate = 0 ; /* No memory register frame display initially. */
893 v->frstate = 0 ; /* No fin. memory register frame display
895 v->iconic = FALSE ; /* Calctool not iconic by default. */
896 v->MPdebug = FALSE ; /* No debug info by default. */
897 v->MPerrors = TRUE ; /* No error information. */
898 acc = MAX_DIGITS + 12 ; /* MP internal accuracy. */
900 mpset(&acc, &size, &size) ;
902 v->hasicon = FALSE ; /* Use standard dtcalc icon by default. */
903 v->beep = TRUE ; /* Beep on error by default. */
904 v->error = 0 ; /* No calculator error initially. */
905 v->key_exp = 0 ; /* Not entering an exponent number. */
906 v->pending_op = 0 ; /* No pending arithmetic operation. */
907 v->titleline = NULL ; /* No User supplied title line. */
915 v->workspaces = NULL;
917 read_str(&v->iconlabel, lstrs[(int) L_LCALC]) ; /* Default icon label. */
919 MPstr_to_num("0.621", DEC, v->MPcon_vals[0]) ; /* kms/hr <=> miles/hr. */
920 MPstr_to_num("1.4142135623", DEC, v->MPcon_vals[1]) ; /* square root of 2 */
921 MPstr_to_num("2.7182818284", DEC, v->MPcon_vals[2]) ; /* e */
922 MPstr_to_num("3.1415926535", DEC, v->MPcon_vals[3]) ; /* pi */
923 MPstr_to_num("2.54", DEC, v->MPcon_vals[4]) ; /* cms <=> inch. */
924 MPstr_to_num("57.295779513", DEC, v->MPcon_vals[5]) ; /* degrees/radian. */
925 MPstr_to_num("1048576.0", DEC, v->MPcon_vals[6]) ; /* 2 ^ 20. */
926 MPstr_to_num("0.0353", DEC, v->MPcon_vals[7]) ; /* grams <=> ounce. */
927 MPstr_to_num("0.948", DEC, v->MPcon_vals[8]) ; /* Kjoules <=> BTU's. */
928 MPstr_to_num("0.0610", DEC, v->MPcon_vals[9]) ; /* cms3 <=> inches3. */
931 for (i = 0; i < MAXREGS; i++) mpcim(&n, v->MPmvals[i]) ;
932 for (i = 0; i < FINREGS; i++)
933 v->MPfvals[i] = (double)n;
934 v->MPfvals[FINREGS - 1] = (double)12;
943 v->error = 0 ; /* Currently no display error. */
944 v->cur_op = '?' ; /* No arithmetic operator defined yet. */
945 v->old_cal_value = '?' ;
947 mpcim(&i, v->MPresult) ; /* No previous result yet. */
948 mpcim(&i, v->MPlast_input) ;
952 /* Convert engineering or scientific number. */
954 make_eng_sci(int *MPnumber)
956 char fixed[MAX_DIGITS+1], *optr ;
957 int MP1[MP_SIZE], MPatmp[MP_SIZE], MPval[MP_SIZE] ;
958 int MP1base[MP_SIZE], MP3base[MP_SIZE], MP10base[MP_SIZE] ;
959 int i, dval, len, n ;
960 int MPmant[MP_SIZE] ; /* Mantissa. */
961 int ddig ; /* Number of digits in exponent. */
962 int eng = 0 ; /* Set if this is an engineering number. */
963 int exp = 0 ; /* Exponent */
965 if (v->dtype == ENG) eng = 1 ;
967 mpabs(MPnumber, MPval) ;
970 if (mplt(MPnumber, MP1)) *optr++ = '-' ;
971 mpstr(MPval, MPmant) ;
973 mpcim(&basevals[(int) v->base], MP1base) ;
975 mppwr(MP1base, &n, MP3base) ;
978 mppwr(MP1base, &n, MP10base) ;
982 mpdiv(MP1, MP10base, MPatmp) ;
986 if (!mpeq(MPmant, MP1))
988 while (mpge(MPmant, MP10base))
991 mpmul(MPmant, MPatmp, MPmant) ;
994 while ((!eng && mpge(MPmant, MP1base)) ||
995 (eng && (mpge(MPmant, MP3base) || exp % 3 != 0)))
998 mpdiv(MPmant, MP1base, MPmant) ;
1001 while (mplt(MPmant, MPatmp))
1004 mpmul(MPmant, MP10base, MPmant) ;
1009 while (mplt(MPmant, MP1) || (eng && exp % 3 != 0))
1012 mpmul(MPmant, MP1base, MPmant) ;
1016 STRCPY(fixed, make_fixed(MPmant, MAX_DIGITS-6)) ;
1017 len = strlen(fixed) ;
1018 for (i = 0; i < len; i++) *optr++ = fixed[i] ;
1027 else *optr++ = '+' ;
1029 MPstr_to_num("0.5", DEC, MP1) ;
1030 mpaddi(MP1, &exp, MPval) ;
1033 for (ddig = 0; mpge(MPval, MP1); ddig++)
1034 mpdiv(MPval, MP1base, MPval) ;
1036 if (ddig == 0) *optr++ = '0' ;
1040 mpmul(MPval, MP1base, MPval) ;
1041 mpcmi(MPval, &dval) ;
1042 *optr++ = digits[dval] ;
1044 mpaddi(MPval, &dval, MPval) ;
1052 /* Convert MP number to fixed number string. */
1053 /* cmax Maximum characters to generate. */
1055 make_fixed(int *MPnumber, int cmax)
1058 int MP1base[MP_SIZE], MP1[MP_SIZE], MP2[MP_SIZE], MPval[MP_SIZE] ;
1059 int ndig ; /* Total number of digits to generate. */
1060 int ddig ; /* Number of digits to left of . */
1064 mpabs(MPnumber, MPval) ;
1067 if (mplt(MPnumber, MP1)) *optr++ = '-' ;
1069 mpcim(&basevals[(int) v->base], MP1base) ;
1071 mppwr(MP1base, &v->accuracy, MP1) ;
1072 MPstr_to_num("0.5", DEC, MP2) ;
1073 mpdiv(MP2, MP1, MP1) ;
1074 mpadd(MPval, MP1, MPval) ;
1078 if (mplt(MPval, MP2))
1085 for (ddig = 0; mpge(MPval, MP2); ddig++)
1086 mpdiv(MPval, MP1base, MPval) ;
1088 ndig = MIN(ddig + v->accuracy, --cmax) ;
1092 if (ddig-- == 0) *optr++ = '.' ;
1093 mpmul(MPval, MP1base, MPval) ;
1094 mpcmi(MPval, &dval) ;
1095 *optr++ = digits[dval] ;
1097 mpaddi(MPval, &dval, MPval) ;
1109 set_item(DISPLAYITEM, v->display) ;
1110 set_item(OPITEM, " ") ;
1111 set_item(HYPITEM, " ") ;
1112 set_item(INVITEM, " ") ;
1115 /* Convert MP number to character string. */
1117 make_number(int *MPnumber, BOOLEAN mkFix)
1119 double number, val ;
1121 /* NOTE: make_number can currently set v->error when converting to a double.
1122 * This is to provide the same look&feel as V3 even though dtcalc
1123 * now does internal arithmetic to "infinite" precision.
1125 * XXX: Needs to be improved. Shouldn't need to convert to a double in
1126 * order to do these tests.
1129 mpcmd(MPnumber, &number) ;
1130 val = fabs(number) ;
1131 if (v->error) return(vstrs[(int) V_ERROR]) ;
1132 if (v->dtype == ENG || v->dtype == SCI ||
1133 (v->dtype == FIX && val != 0.0 && (val > max_fix[(int) v->base])))
1134 return(make_eng_sci(MPnumber)) ;
1135 else if (v->dtype == FIX && val != 0.0 && mkFix)
1137 if(v->accuracy == 0)
1139 if(val <= min_fix0[(int) v->base])
1140 return(make_eng_sci(MPnumber)) ;
1142 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1144 else if(v->accuracy == 1)
1146 if(val <= min_fix1[(int) v->base])
1147 return(make_eng_sci(MPnumber)) ;
1149 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1151 else if(v->accuracy == 2)
1153 if(val <= min_fix2[(int) v->base])
1154 return(make_eng_sci(MPnumber)) ;
1156 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1158 else if(v->accuracy == 3)
1160 if(val <= min_fix3[(int) v->base])
1161 return(make_eng_sci(MPnumber)) ;
1163 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1165 else if(v->accuracy == 4)
1167 if(val <= min_fix4[(int) v->base])
1168 return(make_eng_sci(MPnumber)) ;
1170 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1172 else if(v->accuracy == 5)
1174 if(val <= min_fix5[(int) v->base])
1175 return(make_eng_sci(MPnumber)) ;
1177 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1179 else if(v->accuracy == 6)
1181 if(val <= min_fix6[(int) v->base])
1182 return(make_eng_sci(MPnumber)) ;
1184 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1186 else if(v->accuracy == 7)
1188 if(val <= min_fix7[(int) v->base])
1189 return(make_eng_sci(MPnumber)) ;
1191 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1193 else if(v->accuracy == 8)
1195 if(val <= min_fix8[(int) v->base])
1196 return(make_eng_sci(MPnumber)) ;
1198 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1200 else if(v->accuracy == 9)
1202 if(val <= min_fix9[(int) v->base])
1203 return(make_eng_sci(MPnumber)) ;
1205 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1209 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1213 return(make_fixed(MPnumber, MAX_DIGITS)) ;
1218 /* Default math library exception handling routine. */
1220 matherr(struct exception *exc)
1226 strcpy(msg, exc->name);
1228 if(exc->type == DOMAIN)
1229 strcat(msg, "DOMAIN ");
1230 else if(exc->type == SING)
1231 strcat(msg, "SING ");
1232 else if(exc->type == OVERFLOW)
1233 strcat(msg, "OVERFLOW ");
1234 else if(exc->type == UNDERFLOW)
1235 strcat(msg, "UNDERFLOW ");
1236 else if(exc->type == TLOSS)
1237 strcat(msg, "TLOSS ");
1238 else if(exc->type == PLOSS)
1239 strcat(msg, "PLOSS ");
1241 strcat(msg, vstrs[(int) V_ERROR]);
1243 _DtSimpleError (v->appname, DtWarning, NULL, msg);
1247 doerr(vstrs[(int) V_ERROR]) ;
1248 return(1) ; /* Value ignored. */
1251 /* Convert string into an MP number. */
1253 MPstr_to_num(char *str, enum base_type base, int *MPval)
1256 int MP1[MP_SIZE], MP2[MP_SIZE], MPbase[MP_SIZE] ;
1264 mpcim(&basevals[(int) base], MPbase) ;
1266 while (*optr == ' ') optr++ ;
1269 /* negative number */
1273 while ((inum = char_val(*optr)) >= 0)
1275 mpmul(MPval, MPbase, MPval) ;
1276 mpaddi(MPval, &inum, MPval) ;
1281 for (i = 1; (inum = char_val(*++optr)) >= 0; i++)
1283 mppwr(MPbase, &i, MP1) ;
1285 mpdiv(MP2, MP1, MP1) ;
1286 mpadd(MPval, MP1, MPval) ;
1289 while (*optr == ' ') optr++ ;
1293 if (*optr == '-') exp_sign = -1 ;
1295 while ((inum = char_val(*++optr)) >= 0)
1296 exp = exp * basevals[(int) base] + inum ;
1300 if (v->key_exp || exp_sign == -1)
1302 mppwr(MPbase, &exp, MP1) ;
1303 mpmul(MPval, MP1, MPval) ;
1309 mpmul(MPval, MP1, MPval) ;
1313 /* Append the latest parenthesis char to the display item. */
1319 /* If the character is a Delete, clear the whole line, and exit parenthesis
1322 * If the character is a Back Space, remove the last character. If the last
1323 * character was a left parenthesis, decrement the parentheses count. If
1324 * the parentheses count is zero, exit parenthesis processing.
1326 * If the character is a control character (not Ctrl-h), then append ^(char).
1328 * Otherwise just append the character.
1331 n = strlen(v->display) ;
1332 if (IS_KEY(c, KEY_CLR)) /* Is it a Delete character? */
1334 v->noparens = v->pending = v->opsptr = v->numsptr = 0 ;
1336 set_item(OPITEM, "") ;
1338 mpcim(&i, v->MPdisp_val) ;
1339 show_display(v->MPdisp_val) ;
1341 set_numtype(v->dtype);
1342 set_option_menu((int) TTYPEITEM, (int)v->ttype);
1344 v->curwin = FCP_KEY ;
1348 else if (IS_KEY(c, KEY_BSP)) /* Is is a Back Space character? */
1351 if (v->display[n-1] == '(')
1356 v->pending = v->opsptr = v->numsptr = 0 ;
1358 set_item(OPITEM, "") ;
1359 show_display(v->MPdisp_val) ;
1363 v->display[n-1] = '\0' ;
1365 else if (c <= CTL('z')) /* Is it a control character? */
1369 v->display[n] = '^' ;
1370 v->display[n+1] = c + 96 ;
1371 v->display[n+2] = '\0' ;
1374 else /* It must be an ordinary character. */
1379 v->display[n+1] = '\0' ;
1383 n = (n < MAX_DIGITS) ? 0 : n - MAX_DIGITS ;
1384 v->show_paren = 1 ; /* Hack to get set_item to really display it. */
1385 set_item(DISPLAYITEM, &v->display[n]) ;
1389 /* Process this event. */
1391 process_event(int type)
1397 case KEYBOARD_DOWN : if (v->pending)
1399 v->current = v->cur_ch ;
1404 ival = get_index(v->cur_ch) ;
1405 if (ival < TITEMS - EXTRA) {
1406 if ((v->modetype == FINANCIAL &&
1408 (v->modetype == LOGICAL && (
1409 ival == 21 || ival == 22 ||
1413 /* go arm the button */
1414 draw_button(ival, v->curwin, v->row,
1417 process_item(ival) ;
1421 case KEYBOARD_UP : ival = get_index(v->cur_ch) ;
1422 if (ival < TITEMS - EXTRA) {
1423 if ((v->modetype == FINANCIAL &&
1425 (v->modetype == LOGICAL && (
1426 ival == 21 || ival == 22 ||
1430 /* go disarm the button */
1431 draw_button(ival, v->curwin, v->row,
1434 /* go disarm the button */
1435 draw_button(ival, v->curwin, v->row,
1448 if (n < 0 || n >= TITEMS)
1454 v->current = buttons[n].value ;
1455 if (v->current == '*') v->current = 'x' ; /* Reassign "extra" values. */
1456 if (v->current == '\015') v->current = '=' ;
1457 if (v->current == 'Q') v->current = 'q' ;
1461 isvalid = 0 ; /* Must press a valid key first. */
1462 for (i = 0; i < MAXVKEYS; i++)
1463 if (v->current == validkeys[i]) isvalid = 1 ;
1464 if (v->pending == '?') isvalid = 1 ;
1465 if (!isvalid) return ;
1471 if (v->pending_win == FCP_KEY) (*buttons[v->pending_n].func)() ;
1472 else (*mode_buttons[MODEKEYS * ((int) v->pending_mode - 1) +
1473 v->pending_n].func)() ;
1476 switch (buttons[n].opdisp)
1479 if (v->current == 'T')
1481 if (v->modetype == SCIENTIFIC)
1482 set_item(OPITEM, buttons[n].str) ;
1487 set_item(OPITEM, buttons[n].str) ;
1491 set_item(OPITEM, vstrs[(int) V_CLR]) ;
1493 set_item(OPITEM, "") ;
1498 (*buttons[n].func)() ;
1500 if(strcmp(buttons[n].resname, "clr") != 0)
1505 /* Process a portion of the parentheses stack.
1506 startop Initial position in the operand stack.
1507 startnum Initial position in the numeric stack.
1508 n Number of items to process.
1512 process_stack(int startop, int startnum, int n)
1514 char sdisp[MAXLINE] ; /* Used to save display contents. */
1516 int nptr ; /* Pointer to next number from numeric stack. */
1518 STRCPY(sdisp, v->display) ; /* Save current display. */
1521 v->cur_op = '?' ; /* Current operation is initially undefined. */
1522 for (i = 0; i < n; i++)
1524 if (v->opstack[startop + i] == -1)
1526 mpstr(v->MPnumstack[nptr++], v->MPdisp_val) ;
1530 v->cur_ch = v->opstack[startop + i] ;
1531 if (v->cur_ch == '^') /* Control character? */
1534 v->cur_ch = CTL(v->opstack[startop + i]) ;
1538 v->current = v->cur_ch ;
1541 else process_item(get_index(v->cur_ch)) ;
1544 v->numsptr = startnum ;
1545 push_num(v->MPdisp_val) ;
1546 v->opsptr = startop - 1 ;
1548 save_pending_values(KEY_LPAR) ;
1549 STRCPY(v->display, sdisp) ; /* Restore current display. */
1554 process_str(char *str, enum menu_type mtype)
1560 STRCPY(save, v->display) ;
1561 STRCPY(v->display, " ") ;
1562 set_item(DISPLAYITEM, v->display);
1563 for (i = 0 ; i < len; i++)
1571 STRCPY(v->display, save);
1572 set_item(DISPLAYITEM, v->display);
1579 v->current = str[i] ;
1598 process_item(get_index(str[i])) ;
1605 read_rcfiles(void) /* Read .dtcalcrc's from home and current directories. */
1607 char *home ; /* Pathname for users home directory. */
1608 char name[MAXPATHLEN + 50] ; /* Full name of users .dtcalcrc file. */
1609 char pathname[MAXPATHLEN + 5] ; /* Current working directory. */
1610 char tmp[MAXLINE] ; /* For temporary constant string creation. */
1612 struct passwd *entry ;
1614 for (n = 0; n < MAXREGS; n++)
1616 STRCPY(tmp, make_number(v->MPcon_vals[n], FALSE)) ;
1617 SPRINTF(name, "%1d: %s [%s]", n, tmp, v->con_names[n]) ;
1619 STRCPY(v->con_names[n], name) ;
1620 STRCPY(v->fun_vals[n], "") ; /* Initially empty function strings. */
1623 if ((home = getenv("HOME")) == NULL)
1625 if ((entry = getpwuid(getuid())) == NULL) return ;
1626 home = entry->pw_dir ;
1628 snprintf(name, MAXPATHLEN, "%s/%s", home, RCNAME) ;
1629 get_rcfile(name) ; /* Read .dtcalcrc from users home directory. */
1631 snprintf(name, MAXPATHLEN, "%s/%s", getcwd(pathname, MAXPATHLEN+1), RCNAME) ;
1632 get_rcfile(name) ; /* Read .dtcalcrc file from current directory. */
1637 show_display(int *MPval)
1641 STRCPY(v->display, make_number(MPval, TRUE)) ;
1642 set_item(DISPLAYITEM, v->display) ;
1648 usage(char *progname)
1650 FPRINTF(stderr, ustrs[(int) USAGE1], PATCHLEVEL) ;
1651 FPRINTF(stderr, "%s", ustrs[(int) USAGE2]) ;
1652 FPRINTF(stderr, "%s", ustrs[(int) USAGE3]) ;
1657 write_rcfile(enum menu_type mtype, int exists, int cfno, char *val, char *comment)
1659 char *home ; /* Pathname for users home directory. */
1660 char pathname[MAXPATHLEN] ; /* Current working directory. */
1661 char rcname[MAXPATHLEN] ; /* Full name of users .dtcalcrc file. */
1662 char str[MAXLINE] ; /* Temporary buffer. */
1663 char sval[3] ; /* Used for string comparisons. */
1664 char tmp_filename[MAXLINE] ; /* Used to construct temp filename. */
1665 int rcexists ; /* Set to 1, if .dtcalcrc file exists. */
1666 FILE *rcfd ; /* File descriptor for .dtcalcrc file. */
1667 FILE *tmpfd ; /* File descriptor for new temp .dtcalcrc. */
1668 struct passwd *entry ; /* The user's /etc/passwd entry. */
1671 SPRINTF(rcname, "%s/%s", getcwd(pathname, MAXPATHLEN), RCNAME) ;
1672 if (access(rcname, F_OK) == 0) rcexists = 1 ;
1675 if ((home = getenv("HOME")) == NULL)
1677 if ((entry = getpwuid(getuid())) == NULL) return ;
1678 home = entry->pw_dir ;
1680 SPRINTF(rcname, "%s/%s", home, RCNAME) ;
1681 if (access(rcname, F_OK) == 0) rcexists = 1 ;
1683 STRCPY(tmp_filename, "/tmp/.dtcalcrcXXXXXX") ;
1684 MKTEMP(tmp_filename) ;
1685 if ((tmpfd = fopen(tmp_filename, "w+")) == NULL) return ;
1689 rcfd = fopen(rcname, "r") ;
1690 SPRINTF(sval, " %1d", cfno) ;
1691 while (fgets(str, MAXLINE, rcfd))
1697 case M_CON : sval[0] = 'c' ;
1698 if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1700 if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1702 case M_FUN : sval[0] = 'f' ;
1703 if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1705 if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1710 FPRINTF(tmpfd, "%s", str) ;
1717 case M_CON : FPRINTF(tmpfd, "\nC%1d %s %s\n", cfno, val, comment) ;
1720 if(strcmp(val, "") != 0)
1721 FPRINTF(tmpfd, "\nF%1d %s %s\n", cfno, val, comment) ;
1726 rcfd = fopen(rcname, "w") ;
1728 while (fgets(str, MAXLINE, tmpfd)) FPRINTF(rcfd, "%s", str) ;
1731 UNLINK(tmp_filename) ;
1736 write_resources(char *filename)
1739 int MPtemp[MP_SIZE];
1741 SPRINTF(intval, "%d", v->accuracy) ;
1742 put_resource(R_ACCURACY, intval) ;
1743 put_resource(R_DISPLAYED, v->display) ;
1744 put_resource(R_BASE, base_str[(int) v->base]) ;
1745 put_resource(R_DISPLAY, dtype_str[(int) v->dtype]) ;
1746 put_resource(R_MODE, mode_str[(int) v->modetype]) ;
1747 put_resource(R_TRIG, ttype_str[(int) v->ttype]) ;
1748 put_resource(R_REGS, set_bool(v->rstate == TRUE)) ;
1750 put_resource(R_REG0, make_number(v->MPmvals[0], FALSE)) ;
1751 put_resource(R_REG1, make_number(v->MPmvals[1], FALSE)) ;
1752 put_resource(R_REG2, make_number(v->MPmvals[2], FALSE)) ;
1753 put_resource(R_REG3, make_number(v->MPmvals[3], FALSE)) ;
1754 put_resource(R_REG4, make_number(v->MPmvals[4], FALSE)) ;
1755 put_resource(R_REG5, make_number(v->MPmvals[5], FALSE)) ;
1756 put_resource(R_REG6, make_number(v->MPmvals[6], FALSE)) ;
1757 put_resource(R_REG7, make_number(v->MPmvals[7], FALSE)) ;
1758 put_resource(R_REG8, make_number(v->MPmvals[8], FALSE)) ;
1759 put_resource(R_REG9, make_number(v->MPmvals[9], FALSE)) ;
1761 mpcdm(&(v->MPfvals[0]), MPtemp);
1762 put_resource(R_FREG0, make_number(MPtemp, FALSE)) ;
1763 mpcdm(&(v->MPfvals[1]), MPtemp);
1764 put_resource(R_FREG1, make_number(MPtemp, FALSE)) ;
1765 mpcdm(&(v->MPfvals[2]), MPtemp);
1766 put_resource(R_FREG2, make_number(MPtemp, FALSE)) ;
1767 mpcdm(&(v->MPfvals[3]), MPtemp);
1768 put_resource(R_FREG3, make_number(MPtemp, FALSE)) ;
1769 mpcdm(&(v->MPfvals[4]), MPtemp);
1770 put_resource(R_FREG4, make_number(MPtemp, FALSE)) ;
1771 mpcdm(&(v->MPfvals[5]), MPtemp);
1772 put_resource(R_FREG5, make_number(MPtemp, FALSE)) ;
1774 save_resources(filename) ;