Link with C++ linker
[oweals/cde.git] / cde / programs / dtcalc / calctool.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: calctool.c /main/9 1996/09/25 11:28:16 rswiston $ */
24 /*                                                                      *
25  *  calctool.c                                                          *
26  *   Contains the none user interface portion of the Desktop            *
27  *   Calculator.                                                        *
28  *                                                                      *
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.                                *
33  */
34
35 #include <stdio.h>
36 #include <ctype.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <malloc.h>
41 #include <sys/types.h>
42 #include <sys/file.h>
43 #include <sys/param.h>
44 #include <pwd.h>
45 #include <math.h>
46 #include "patchlevel.h"
47 #include "calctool.h"
48 #include "ds_common.h"
49
50 #ifdef sun
51
52 /* Copied from math.h */
53 struct exception {
54         int type;
55         char *name;
56         double arg1;
57         double arg2;
58         double retval;
59 };
60
61 #endif
62
63 time_t time() ;
64
65 double max_fix[4] = {
66           6.871947674e+10, 3.245185537e+32,
67           1.000000000e+36, 2.230074520e+43
68 } ;
69 double min_fix0[4] = {
70           2.500000000e-1, 3.750000000e-1,
71           1.000000000e-1, 4.375000000e-1
72 } ;
73 double min_fix1[4] = {
74           1.250000000e-1, 4.687500000e-2,
75           1.000000000e-2, 2.734375000e-2
76 } ;
77 double min_fix2[4] = {
78           6.250000000e-2, 5.859375000e-3,
79           1.000000000e-3, 1.708984375e-3
80 } ;
81 double min_fix3[4] = {
82           3.125000000e-2, 7.324218750e-4,
83           1.000000000e-4, 1.068115234e-4
84 } ;
85 double min_fix4[4] = {
86           1.562500000e-2, 9.155273437e-5,
87           1.000000000e-5, 6.675720215e-6
88 } ;
89 double min_fix5[4] = {
90           7.812500000e-3, 1.144409180e-5,
91           1.000000000e-6, 4.172325134e-7
92 } ;
93 double min_fix6[4] = {
94           6.906250000e-3, 1.430511475e-6,
95           1.000000000e-7, 2.607703209e-8
96 } ;
97 double min_fix7[4] = {
98           1.953125000e-3, 1.788139343e-7,
99           1.000000000e-8, 1.629814506e-9
100 } ;
101 double min_fix8[4] = {
102           9.765625000e-4, 2.235174179e-8,
103           1.000000000e-9, 1.018634066e-10
104 } ;
105 double min_fix9[4] = {
106           4.882812500e-4, 2.793967724e-9,
107           1.000000000e-10, 6.366462912e-12
108 } ;
109
110 extern char *base_str[] ;       /* Strings for each base value. */
111 extern char *cmdstr[] ;         /* Strings for each command line option. */
112 extern char *dtype_str[] ;      /* Strings for each display mode value. */
113 extern char *lstrs[] ;          /* Labels for various Motif items. */
114 extern char *mess[] ;           /* Message strings. */
115 extern char *mode_str[] ;       /* Strings for each mode value. */
116 extern char *opts[] ;           /* Command line option strings. */
117 extern char *ttype_str[] ;      /* Strings for each trig type value. */
118 extern char *ustrs[] ;          /* Usage message strings. */
119 extern char *vstrs[] ;          /* Various strings. */
120
121 char digits[] = "0123456789ABCDEF" ;
122 int basevals[4] = { 2, 8, 10, 16 } ;
123
124 int left_pos[BCOLS]  = { 3, 2, 1, 0 } ;  /* Left positions. */
125 int right_pos[BCOLS] = { 0, 1, 2, 3 } ;  /* "Right" positions. */
126
127 /* Valid keys when an error condition has occured. */
128 /*                            MEM  KEYS clr     clr     QUIT REDRAW */
129 char validkeys[MAXVKEYS]  = { 'm', 'k', '\177', '\013', 'q', '\f' } ;
130
131 Vars v ;            /* Calctool variables and options. */
132
133 struct menu_entry menu_entries[MAXENTRIES] ;
134
135 struct menu cmenus[MAXMENUS] = {                 /* Calculator menus. */
136 /*      title     total index defval                           */
137   { (char *) NULL, 10,    0,    2  /* 2 places */    },    /* ACC */
138   { (char *) NULL,  4,   20,    2  /* Decimal  */    },    /* BASE TYPE */
139   { (char *) NULL, 10,    0,    0  /* Con. 0   */    },    /* CON */
140   { (char *) NULL, 10,   10,    0  /* Reg. 0   */    },    /* EXCH */
141   { (char *) NULL, 10,    0,    0  /* Fun. 0   */    },    /* FUN */
142   { (char *) NULL,  4,   30,    0  /* Basic    */    },    /* MODE */
143   { (char *) NULL,  3,   24,    1  /* Fixed    */    },    /* NUM TYPE */
144   { (char *) NULL, 10,   10,    0  /* Reg. 0   */    },    /* RCL */
145   { (char *) NULL, 10,   10,    0  /* Reg. 0   */    },    /* STO */
146   { (char *) NULL,  3,   27,    0  /* Degrees  */    },    /* TRIG TYPE */
147 } ;
148
149 /*  This table shows the keyboard values that are currently being used:
150  *
151  *           | 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
152  *-------------+--------------------------------------------------
153  *  Control: | a   c d   f   h i     l m         r s t u       y
154  *  Lower:   | a b c d e f   h i   k   m n   p q r s     v   x y
155  *  Upper:   | A B C D E F G           M N   P Q R S T       X
156  *  Numeric: | 0 1 2 3 4 5 6 7 8 9
157  *  Other:   | @ . + - * / = % ( ) # < > [ ] { } | & ~ ^ ? ! \177
158  *----------------------------------------------------------------
159  */
160
161 /* Calculator button values. */
162
163 struct button buttons[TITEMS] = {
164 /*     str       str2      value opdisp   menutype   resname  func */
165
166 /* Row 1. */
167 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "blank",  do_none },
168 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_FUN,    "fun",    do_pending },
169 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_CON,    "con",    do_pending },
170 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "keys",   do_keys    },
171
172 /* Row 2. */
173 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "int",    do_portion },
174 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "frac",   do_portion },
175 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "abs",    do_portion },
176 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "exp",    do_expno   },
177
178 /* Row 3. */
179 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_ACC,    "acc",    do_pending },
180 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_STO,    "sto",    do_pending },
181 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_RCL,    "rcl",    do_pending },
182 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_EXCH,   "exch",   do_pending },
183
184 /* Row 4. */
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 },
188 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "blank",  do_none },
189
190 /* Row 5. */ 
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 },
194 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "blank",  do_none },
195
196 /* Row 6. */ 
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 },
200 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "blank",  do_none },
201
202 /* Row 7. */
203 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "recip",   do_immed   },
204 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "square",  do_immed   },
205 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "sqrt",    do_immed   },
206 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "percent", do_calc   },
207
208 /* Row 8. */
209 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "lparen", do_paren   },
210 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "rparen", do_paren   },
211 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "bsp",    do_delete  },
212 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "clr",    do_clear   },
213
214 /* Row 9. */
215 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "numd",   do_number  },
216 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "nume",   do_number  },
217 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "numf",   do_number  },
218 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "chs",    do_immed   },
219
220 /* Row 10. */
221 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "numa",   do_number  },
222 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "numb",   do_number  },
223 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "numc",   do_number  },
224 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "mul",    do_calc    },
225
226 /* Row 11. */
227 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "num7",   do_number  },
228 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "num8",   do_number  },
229 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "num9",   do_number  },
230 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "div",    do_calc    },
231
232 /* Row 12. */
233 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "num4",   do_number  },
234 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "num5",   do_number  },
235 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "num6",   do_number  },
236 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "sub",    do_calc    },
237
238 /* Row 13. */
239 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "num1",   do_number  },
240 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "num2",   do_number  },
241 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "num3",   do_number  },
242 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "add",    do_calc    },
243
244 /* Row 14. */
245 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "num0",   do_number  },
246 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "point",  do_point   },
247 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "equals", do_calc    },
248 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "quit",   do_frame   },
249
250 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_BASE,   "base",   do_pending },
251 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NUM,    "disp",   do_pending },
252 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_MODE,   "mode",   do_pending },
253 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_TRIG,   "trig",   do_pending },
254 } ; 
255
256 struct button mode_buttons[MAXMODES * MODEKEYS] = {
257 /*     str       str2      value opdisp   menutype   resname  func */
258
259 /* Financial. */
260 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "term",   do_business},
261 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "rate",   do_business},
262 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "pv",     do_business},
263 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "pmt",    do_business},
264 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "fv",     do_business},
265 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "ppy",    do_business},
266 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "clrreg", do_business},
267 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "ctrm",   do_business},
268 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "ddb",    do_business},
269 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "sln",    do_business},
270 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "syd",    do_business},
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    },
275 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "",       do_none    },
276
277 /* Logical. */
278 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "lshift", do_pending },
279 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "rshift", do_pending },
280 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "and16",  do_immed   },
281 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "and32",  do_immed   },
282 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "or",     do_calc    },
283 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "and",    do_calc    },
284 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "not",    do_immed   },
285 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "xor",    do_calc    },
286 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "xnor",   do_calc    },
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    },
293 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "",       do_none    },
294
295 /* Scientific. */
296 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "inv",    do_immed   },
297 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "hyp",    do_immed   },
298 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "etox",   do_immed   },
299 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "tentox", do_immed   },
300 { (char *)NULL, (char *)NULL, 0, OP_SET,   M_NONE,   "ytox",   do_calc    },
301 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "xfact",  do_immed   },
302 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "cos",    do_trig    },
303 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "sin",    do_trig    },
304 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "tan",    do_trig    },
305 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "ln",     do_immed   },
306 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "log",    do_immed   },
307 { (char *)NULL, (char *)NULL, 0, OP_CLEAR, M_NONE,   "rand",   do_immed   },
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    },
311 { (char *)NULL, (char *)NULL, 0, OP_NOP,   M_NONE,   "",       do_none    },
312 } ;
313
314
315 int
316 char_val(chr)
317 char chr ;
318 {
319        if (chr >= '0' && chr <= '9') return(chr - '0') ;
320   else if (chr >= 'a' && chr <= 'f') return(chr - 'a' + 10) ;
321   else if (chr >= 'A' && chr <= 'F') return(chr - 'A' + 10) ;
322   else return(-1) ;
323 }
324
325
326 void
327 clear_display()
328 {
329   int i ;
330  
331   v->pointed = 0 ;
332   v->toclear = 1 ;
333   v->defState = 1 ;
334   i = 0 ;
335   mpcim(&i, v->MPdisp_val) ;
336   STRCPY(v->display, make_number(v->MPdisp_val, FALSE)) ;
337   set_item(DISPLAYITEM, v->display) ;
338   
339   v->hyperbolic = 0 ;
340   v->inverse    = 0 ;
341   v->show_paren = 0 ;
342   v->opsptr     = 0 ;            /* Clear parentheses stacks. */
343   v->numsptr    = 0 ;
344   set_item(HYPITEM, "    ") ;
345   set_item(INVITEM, "    ") ;
346 }
347
348
349 char *
350 convert(line)              /* Convert .dtcalcrc line to ascii values. */
351 char *line ;               /* Input line to be converted. */
352 {
353   static char output[MAXLINE] ;   /* Converted output record. */
354   int ctrl = 0       ;     /* Set if we are processing a control character. */
355   int i ;                  /* Position within input line. */
356   int len ;
357   int n = 0 ;              /* Position within output line. */
358  
359   len = strlen(line) ;
360   for (i = 0; i < len; i++)
361     {
362            if (line[i] == ' ') continue ;
363       else if (line[i] == '\\') ctrl = 1 ;
364       else if (ctrl)
365         {
366           output[n++] = CTL(line[i]) ;
367           ctrl = 0 ;
368         }
369       else output[n++] = line[i] ;
370     }
371   output[n] = '\0' ;
372   return(output) ;
373 }
374
375
376 void
377 do_dtcalc(argc, argv)
378 int argc ;
379 char **argv ;
380 {
381   char *ptr ;
382   int i ;
383
384   v->progname = argv[0] ;     /* Save programs name. */
385   v->appname  = NULL ;
386   init_cmdline_opts() ;       /* Initialise command line option strings. */
387
388   if ((ptr = strrchr(argv[0], '/')) != NULL)
389     read_str(&v->appname, ptr+1) ;
390   else read_str(&v->appname, argv[0]) ;
391
392   init_text() ;               /* Setup text strings depending upon language. */
393   init_vars() ;               /* Setup default values for variables. */
394   key_init() ;                /* Determine numeric function keys. */
395   load_resources() ;          /* Get resources from various places. */
396   read_resources() ;          /* Read resources from merged database. */
397   get_options(argc, argv) ;   /* Get command line arguments. */
398   if(application_args.session != NULL)
399   {
400       RestoreSession(); 
401   }
402   read_rcfiles() ;            /* Read .dtcalcrc's files. */
403   init_graphics() ;
404   make_frames() ;             /* Create dtcalc window frames. */
405
406   v->shelf      = NULL ;      /* No selection for shelf initially. */
407   v->noparens   = 0 ;         /* No unmatched brackets initially. */
408   v->opsptr     = 0 ;         /* Nothing on the parentheses op stack. */
409   v->numsptr    = 0 ;         /* Nothing on the parenthese numeric stack. */
410   v->pending    = 0 ;         /* No initial pending command. */
411   if(application_args.session == NULL)
412      v->tstate     = 0 ;      /* Button values displayed first. */
413   v->hyperbolic = 0 ;         /* Normal trig functions initially. */
414   v->inverse    = 0 ;         /* No inverse functions initially. */
415
416   srand48((long) time((time_t *) 0)) ;   /* Seed random number generator. */
417
418   make_items() ;              /* Create server images and fir frames. */
419   if(v->display[0] == NULL)
420      do_clear() ;                /* Initialise and clear display. */
421
422   if (v->rstate == TRUE)      /* Show the memory register window? */
423     {
424       make_registers(MEM) ;
425       if (!v->iconic) win_display(FCP_REG, TRUE) ;
426     }
427   if (!v->iconic) win_display(FCP_MODE, TRUE) ;
428   show_display(v->MPdisp_val) ;     /* Output in correct display mode. */
429   save_cmdline(argc, argv) ;        /* Setup dtcalc command line. */
430   start_tool() ;                    /* Display the calculator. */
431 }
432
433
434 /* Dtcalc's customised math library error-handling routine. */
435
436 void
437 doerr(errmes)
438 char *errmes ;
439 {
440   if (!v->started) return ;
441   STRCPY(v->display, errmes) ;
442   set_item(DISPLAYITEM, v->display) ;
443   v->error = 1 ;
444   beep() ;
445   set_item(OPITEM, vstrs[(int) V_CLR]) ;
446 }
447
448
449 int
450 get_bool_resource(rtype, boolval)   /* Get boolean resource from database. */
451 enum res_type rtype ;
452 int *boolval ;
453 {
454   char *val, tempstr[MAXLINE] ;
455   int len, n ;
456  
457   if ((val = get_resource(rtype)) == NULL) return(0) ;
458   STRCPY(tempstr, val) ;
459   len = strlen(tempstr) ;
460   for (n = 0; n < len; n++)
461     if (isupper(tempstr[n])) tempstr[n] = tolower(tempstr[n]) ;
462   if (EQUAL(tempstr, vstrs[(int) V_TRUE])) *boolval = TRUE ;
463   else                                     *boolval = FALSE ;
464   return(1) ;
465 }
466
467
468 /*  Get button index for given character value, setting curwin,
469  *  row and column appropriately. Note that if the value isn't found,
470  *  then a value of TITEMS is returned. This is "chucked out" by
471  *  process_item as being invalid.
472  *
473  *  XXX: This routine can be improved by using a hash lookup table.
474  */
475  
476 int
477 get_index(ch)
478 char ch ;
479 {
480   int n, val ;
481  
482   for (n = 0; n < TITEMS; n++) {
483     if (ch == buttons[n].value)  
484        break ;
485   }
486   if (n < TITEMS) 
487      v->curwin = FCP_KEY ;
488   else
489   {
490      return(TITEMS) ;
491   }
492   v->row = n / MAXCOLS ;
493   v->column = n - (v->row * MAXCOLS) ;
494   return(n) ;
495 }
496
497
498 int
499 get_int_resource(rtype, intval)   /* Get integer resource from database. */
500 enum res_type rtype ;
501 int *intval ;
502 {
503   char *val ;
504
505   if ((val = get_resource(rtype)) == NULL) return(0) ;
506   *intval = atoi(val) ;
507   return(1) ;
508 }
509
510
511 /* Get keyboard equivalent from first character of localised string. */
512
513 void
514 get_key_val(val, str)
515 char *val, *str ;
516 {
517   *val = str[0] ;
518 }
519
520
521 void
522 get_label(n)
523 int n ;
524 {
525   int val ;
526   char *temp;
527
528   val = buttons[n].value ;
529   if (v->tstate)
530      temp = buttons[n].str2;
531   else 
532      temp = buttons[n].str;
533
534   if(temp != NULL)
535      STRCPY(v->pstr, temp) ;
536   else
537      STRCPY(v->pstr, "");
538 }
539
540
541 void
542 get_options(argc, argv)      /* Extract command line options. */
543 int argc ;
544 char *argv[] ;
545 {
546   char next[MAXLINE] ;       /* The next command line parameter. */
547   char strval[MAXLINE] ;
548   char *msg;
549   int i, len;
550
551   INC ;
552   while (argc > 0)
553     {
554       if (argv[0][0] == '-' || argv[0][0] == '+')
555         {
556           switch (argv[0][1])
557             {
558               case 'D' : v->MPdebug = TRUE ;   /* MP debug info. to stderr. */
559                          break ;
560               case 'a' : INC ;
561                          getparam(next, argv, opts[(int) O_ACCVAL]) ;
562                          v->accuracy = atoi(next) ;
563                          if (v->accuracy < 0 || v->accuracy > 9)
564                            {
565                              msg = (char *) XtMalloc(strlen(
566                                                    opts[(int) O_ACCRANGE]) + 3);
567                              sprintf(msg, opts[(int) O_ACCRANGE]);
568                              _DtSimpleError (v->appname, DtWarning, NULL, msg);
569                              XtFree(msg);
570                              v->accuracy = 2 ;
571                            }
572                          break ;
573               case 'm' : INC ;
574                          msg = (char *) XtMalloc(strlen(opts[(int) O_MODE])+
575                                                              strlen(next) + 3);
576                          sprintf(msg, opts[(int) O_MODE], next);
577                          getparam(next, argv, msg) ;
578                          XtFree(msg);
579                          STRCPY(strval, next) ;
580                          len = strlen(strval) ;
581                          for (i = 0; i < len; i++)
582                          {
583                            if (islower(strval[i])) 
584                               strval[i] = toupper(strval[i]) ;
585                          }
586                          if(strcmp(strval, "FINANCIAL") == 0)
587                              v->modetype = FINANCIAL ;
588                          else if(strcmp(strval, "LOGICAL") == 0)
589                              v->modetype = LOGICAL ;
590                          else if(strcmp(strval, "SCIENTIFIC") == 0)
591                              v->modetype = SCIENTIFIC ;
592                          else
593                            {
594                              msg = (char *) XtMalloc(strlen(opts[(int) O_MODE])+
595                                                     strlen(next) + 3);
596                              sprintf(msg, opts[(int) O_MODE], next);
597                              _DtSimpleError (v->appname, DtWarning, NULL, msg);
598                              XtFree(msg);
599                              v->modetype = SCIENTIFIC ;
600                            }
601                          break ;
602               case 'b' : INC ;
603                          getparam(next, argv, opts[(int) O_BASE]) ;
604                          STRCPY(strval, next) ;
605                          len = strlen(strval) ;
606                          for (i = 0; i < len; i++)
607                          {
608                            if (islower(strval[i]))
609                               strval[i] = toupper(strval[i]) ;
610                          }
611                          if(strncmp(strval, "BIN", 3) == 0)
612                              v->base = BIN ;
613                          else if(strncmp(strval, "OCT", 3) == 0)
614                              v->base = OCT ;
615                          else if(strncmp(strval, "DEC", 3) == 0)
616                              v->base = DEC ;
617                          else if(strncmp(strval, "HEX", 3) == 0)
618                              v->base = HEX ;
619                          else
620                            {
621                              msg = (char *) XtMalloc(strlen(
622                                                     opts[(int) O_BASE]) + 3);
623                              sprintf(msg, opts[(int) O_BASE]);
624                              _DtSimpleError (v->appname, DtWarning, NULL, msg);
625                              XtFree(msg);
626                              v->base = DEC ;
627                            }
628                          break ;
629               case 'n' : if(strcmp(&argv[0][1], "notation") == 0) 
630                          {
631                             INC ;
632                             msg = (char *) XtMalloc(strlen(
633                                                  opts[(int) O_DISPLAY]) + 
634                                                  strlen(next) + 3);
635                             sprintf(msg, opts[(int) O_DISPLAY], next);
636                             getparam(next, argv, msg) ;
637                             XtFree(msg);
638                             STRCPY(strval, next) ;
639                             len = strlen(strval) ;
640                             for (i = 0; i < len; i++)
641                             {
642                               if (islower(strval[i]))
643                                  strval[i] = toupper(strval[i]) ;
644                             }
645                             if(strncmp(strval, "FIX", 3) == 0)
646                                 v->dtype = FIX ;
647                             else if(strncmp(strval, "ENG", 3) == 0)
648                                 v->dtype = ENG ;
649                             else if(strncmp(strval, "SCI", 3) == 0)
650                                 v->dtype = SCI ;
651                             else
652                               {
653                                 msg = (char *) XtMalloc(strlen(
654                                                     opts[(int) O_DISPLAY]) + 
655                                                     strlen(next) + 3);
656                                 sprintf(msg, opts[(int) O_DISPLAY], next);
657                                 _DtSimpleError (v->appname, DtWarning, NULL, msg);
658                                 XtFree(msg);
659                                 v->dtype = FIX ;
660                               }
661                             break ;
662                          }
663                          else if(strcmp(&argv[0][1], "no_menu_bar") == 0)
664                          {
665                             INC ;
666                             application_args.menuBar = False;
667                             break ;
668                          }
669               case 't' : if(strcmp(&argv[0][1], "trig") == 0)
670                          {
671                             INC ;
672                             msg = (char *) XtMalloc(strlen(
673                                                     opts[(int) O_TRIG]) + 
674                                                     strlen(next) + 3);
675                             sprintf(msg, opts[(int) O_TRIG], next);
676                             getparam(next, argv, msg) ;
677                             XtFree(msg);
678                             STRCPY(strval, next) ;
679                             len = strlen(strval) ;
680                             for (i = 0; i < len; i++)
681                             {
682                               if (islower(strval[i]))
683                                  strval[i] = toupper(strval[i]) ;
684                             }
685                             if(strncmp(strval, "DEG", 3) == 0)
686                                 v->ttype = DEG ;
687                             else if(strncmp(strval, "RAD", 3) == 0)
688                                 v->ttype = RAD ;
689                             else if(strncmp(strval, "GRAD", 4) == 0)
690                                 v->ttype = GRAD ;
691                             else
692                               {
693                                 msg = (char *) XtMalloc(strlen(
694                                                     opts[(int) O_TRIG]) + 
695                                                     strlen(next) + 3);
696                                 sprintf(msg, opts[(int) O_TRIG], next);
697                                 _DtSimpleError (v->appname, DtWarning, NULL, msg);
698                                 XtFree(msg);
699                                 v->ttype = DEG ;
700                               }
701                             break ;
702                          }
703               case 's' : if(strcmp(&argv[0][1], "session") == 0)
704                          {
705                             INC ;
706                             getparam(next, argv, opts[(int) O_SESSION]) ;
707                             application_args.session = XtNewString(next);
708                             break ;
709                          }
710               case '?' :
711               case 'v' : usage(v->progname) ;
712                          break ;
713               default  :
714               toolarg  :             /* Pick up generic tool arguments. */
715                          usage(v->progname) ;
716             }
717           INC ;
718         }
719       else INC ;
720     }
721 }
722
723
724 void
725 getparam(s, argv, errmes)
726 char *s, *argv[], *errmes ;
727 {
728   char *msg;
729
730   if (*argv != NULL && argv[0][0] != '-') STRCPY(s, *argv) ;
731   else
732     { 
733       msg = (char *) XtMalloc(strlen(mess[(int) MESS_PARAM]) + 
734                               strlen(errmes) + 3);
735       sprintf(msg, mess[(int) MESS_PARAM], errmes);
736       _DtSimpleError (v->appname, DtError, NULL, msg);
737       FPRINTF(stderr, mess[(int) MESS_PARAM], errmes) ;
738       exit(1) ;
739     }
740 }
741
742
743 void
744 get_rcfile(name)          /* Read .dtcalcrc file. */
745 char *name ;
746 {
747   char line[MAXLINE] ;    /* Current line from the .dtcalcrc file. */
748   char tmp[MAXLINE] ;     /* Used to extract definitions. */
749   double cval ;           /* Current constant value being converted. */
750   int i ;                 /* Index to constant or function array. */
751   int isval ;             /* Set to 'c' or 'f' for convertable line. */
752   int len, n ;            
753   FILE *rcfd ;            /* File descriptor for dtcalc rc file. */
754  
755   if ((rcfd = fopen(name, "r")) == NULL) return ;
756  
757 /*  Process the .dtcalcrc file. There are currently four types of
758  *  records to look for:
759  *
760  *  1) Those starting with a hash in the first column are comments.
761  *
762  *  2) Lines starting with 'c' or 'C' in the first column are
763  *     definitions for constants. The cC is followed by a digit in
764  *     the range 0-9, then a space. This is followed by a number
765  *     in fixed or scientific notation. Following this is an optional
766  *     comment, which if found, will be used in the popup menu for
767  *     the constants. If the comment is present, there must be at
768  *     least one space between this and the preceding number.
769  *
770  *  3) Those starting with a 'f' or a 'F' in the first column are
771  *     definitions for functions. The fF is followed by a digit in
772  *     the range 0-9, then a space. This is followed by a function
773  *     definition. Following this is an optional comment, which if
774  *     found, will be used in the popup menu for the functions.
775  *     If the comment is present, there must be at least one space
776  *     between this and the preceding function definition.
777  *
778  *  4) Lines starting with a 'r' or a 'R' in the first column are
779  *     definitions for the initial contents of the calculators
780  *     memory registers. The rR is followed by a digit in the
781  *     range 0-9, then a space. This is followed by a number in
782  *     fixed or scientific notation. The rest of the line is ignored.
783  *
784  *  All other lines are ignored.
785  *
786  *  Two other things to note. There should be no embedded spaces in
787  *  the function definitions, and whenever a backslash is found, that
788  *  and the following character signify a control character, for
789  *  example \g would be ascii 7.
790  */
791
792   while (fgets(line, MAXLINE, rcfd) != NULL)
793     {
794       isval = 0 ;
795            if (line[0] == 'c' || line[0] == 'C') isval = 'c' ;
796       else if (line[0] == 'f' || line[0] == 'F') isval = 'f' ;
797       else if (line[0] == 'r' || line[0] == 'R') isval = 'r' ;
798       if (isval)
799         if (line[1] >= '0' && line[1] <= '9' && line[2] == ' ')
800           {
801             i = char_val(line[1]) ;
802             if (isval == 'c')
803               {  
804                 n = sscanf(&line[3], "%lf", &cval) ;
805                 if (n == 1) 
806                 {
807                    if(line[3] == '-')
808                    {
809                       MPstr_to_num(&line[4], DEC, v->MPcon_vals[i]) ;
810                       mpneg(v->MPcon_vals[i], v->MPcon_vals[i]) ;
811                    }
812                    else
813                       MPstr_to_num(&line[3], DEC, v->MPcon_vals[i]) ;
814                 }
815               }  
816             else if (isval == 'f')
817               {
818                 SSCANF(&line[3], "%s", tmp) ;
819                 STRCPY(v->fun_vals[i], convert(tmp)) ;
820               }  
821             else if (isval == 'r')
822               {  
823                 n = sscanf(&line[3], "%lf", &cval) ;
824                 if (n == 1) MPstr_to_num(&line[3], DEC, v->MPmvals[i]) ;
825                 continue ;
826               }  
827             len = strlen(line) ;
828             for (n = 3; n < len; n++)
829               if (line[n] == ' ' || line[n] == '\n')
830                 {
831                   while (line[n] == ' ') n++ ;
832                   line[strlen(line)-1] = '\0' ;
833                   if (isval == 'c')
834                     {
835                       STRCPY(tmp, make_number(v->MPcon_vals[i], TRUE)) ;
836                       SPRINTF(v->con_names[i], "%1d: %s [%s]",
837                               i, tmp, &line[n]) ;
838                     }
839                   else
840                     SPRINTF(v->fun_names[i], "%1d: %s [%s]",
841                             i, tmp, &line[n]) ;
842                   break ;
843                 }
844           }
845     }
846   FCLOSE(rcfd) ;
847 }
848
849
850 int
851 get_str_resource(rtype, strval)   /* Get a string resource from database. */
852 enum res_type rtype ;
853 char *strval ;
854 {
855   char *val ;
856   int i, len ;
857
858   if ((val = get_resource(rtype)) == NULL) return(0) ;
859   STRCPY(strval, val) ;
860   len = strlen(strval) ;
861   if(rtype != R_TRIG && rtype != R_DISPLAY)
862   {
863      for (i = 0; i < len; i++)
864        if (islower(strval[i])) strval[i] = toupper(strval[i]) ;
865   }
866   return(1) ;
867 }
868
869
870 void
871 grey_buttons(base)     /* Grey out numeric buttons depending upon base. */
872 enum base_type base ;
873 {
874   char val ;
875   int column, dim, i, n, row ;
876
877   for (i = 0; i < 16; i++)
878     {
879       val = digits[i] ;
880       if (isupper(val)) val = tolower(val) ;
881       for (n = 0; n < TITEMS; n++)
882         if (val == buttons[n].value) break ;
883       row = n / MAXCOLS ;
884       column = n - (row * MAXCOLS) ;
885
886       if (i < basevals[(int) base]) dim = FALSE ;
887       else                          dim = TRUE ;
888       grey_button(row, column, dim) ;
889     }
890 }
891
892
893 void
894 handle_menu_selection(n, item)   /* Process right button menu selection. */
895 int n, item ;
896 {
897   if (item != -1)
898     {
899       if (IS_KEY(v->pending, KEY_LPAR))     /* Are we inside parentheses? */
900         {
901           v->current = buttons[n].value ;
902           do_paren() ;
903           v->current = item ;
904           do_paren() ;
905         }
906       else
907         { 
908           save_pending_values(buttons[n].value) ;
909           v->current = item ;
910           v->ismenu = 1 ;       /* To prevent grey buttons being redrawn. */
911           do_pending() ;
912           v->ismenu = 0 ;
913         }
914     }
915 }
916
917
918 void
919 init_vars()    /* Setup default values for various variables. */
920 {
921   int acc, i, n, size ;
922
923   v->accuracy   = 2 ;        /* Initial accuracy. */
924   v->base       = DEC ;      /* Initial base. */
925   v->dtype      = FIX ;      /* Initial number display mode. */
926   v->ttype      = DEG ;      /* Initial trigonometric type. */
927   v->modetype   = SCIENTIFIC;    /* Initial calculator mode. */
928   v->rstate     = 0 ;        /* No memory register frame display initially. */
929   v->frstate    = 0 ;        /* No fin. memory register frame display 
930                                 initially. */
931   v->iconic     = FALSE ;    /* Calctool not iconic by default. */
932   v->MPdebug    = FALSE ;    /* No debug info by default. */
933   v->MPerrors   = TRUE ;               /* No error information. */
934   acc           = MAX_DIGITS + 12 ;     /* MP internal accuracy. */
935   size          = MP_SIZE ;
936   mpset(&acc, &size, &size) ;
937
938   v->hasicon     = FALSE ;        /* Use standard dtcalc icon by default. */
939   v->beep        = TRUE ;         /* Beep on error by default. */
940   v->error       = 0 ;            /* No calculator error initially. */
941   v->key_exp     = 0 ;            /* Not entering an exponent number. */
942   v->pending_op  = 0 ;            /* No pending arithmetic operation. */
943   v->titleline   = NULL ;         /* No User supplied title line. */
944   v->display[0]  = NULL ;         
945
946   v->x  = 0;
947   v->x  = 0;
948   v->width  = 0;
949   v->height = 0; 
950
951   v->workspaces = NULL; 
952
953   read_str(&v->iconlabel, lstrs[(int) L_LCALC]) ;  /* Default icon label. */
954
955   MPstr_to_num("0.621", DEC, v->MPcon_vals[0]) ;  /* kms/hr <=> miles/hr. */
956   MPstr_to_num("1.4142135623", DEC, v->MPcon_vals[1]) ;  /* square root of 2 */
957   MPstr_to_num("2.7182818284", DEC, v->MPcon_vals[2]) ;  /* e */
958   MPstr_to_num("3.1415926535", DEC, v->MPcon_vals[3]) ;  /* pi */
959   MPstr_to_num("2.54",         DEC, v->MPcon_vals[4]) ;  /* cms <=> inch. */
960   MPstr_to_num("57.295779513", DEC, v->MPcon_vals[5]) ;  /* degrees/radian. */
961   MPstr_to_num("1048576.0",    DEC, v->MPcon_vals[6]) ;  /* 2 ^ 20. */
962   MPstr_to_num("0.0353", DEC, v->MPcon_vals[7]) ;  /* grams <=> ounce. */
963   MPstr_to_num("0.948",  DEC, v->MPcon_vals[8]) ;  /* Kjoules <=> BTU's. */
964   MPstr_to_num("0.0610", DEC, v->MPcon_vals[9]) ;  /* cms3 <=> inches3. */
965
966   n = 0 ;
967   for (i = 0; i < MAXREGS; i++) mpcim(&n, v->MPmvals[i]) ;
968   for (i = 0; i < FINREGS; i++)  
969      v->MPfvals[i] = (double)n;
970   v->MPfvals[FINREGS - 1] = (double)12;
971 }
972
973
974 void
975 initialise()
976 {
977   int i ;
978
979   v->error         = 0 ;           /* Currently no display error. */
980   v->cur_op        = '?' ;         /* No arithmetic operator defined yet. */
981   v->old_cal_value = '?' ;
982   i = 0 ;
983   mpcim(&i, v->MPresult) ;         /* No previous result yet. */
984   mpcim(&i, v->MPlast_input) ;
985 }
986
987
988 char *
989 make_eng_sci(MPnumber)      /* Convert engineering or scientific number. */
990 int *MPnumber ;
991 {
992   char fixed[MAX_DIGITS+1], *optr ;
993   int MP1[MP_SIZE], MPatmp[MP_SIZE], MPval[MP_SIZE] ;
994   int MP1base[MP_SIZE], MP3base[MP_SIZE], MP10base[MP_SIZE] ;
995   int i, dval, len, n ;
996   int MPmant[MP_SIZE] ;        /* Mantissa. */
997   int ddig ;                   /* Number of digits in exponent. */
998   int eng = 0 ;                /* Set if this is an engineering number. */
999   int exp = 0 ;                /* Exponent */
1000  
1001   if (v->dtype == ENG) eng = 1 ;
1002   optr = v->snum ;
1003   mpabs(MPnumber, MPval) ;
1004   n = 0 ;
1005   mpcim(&n, MP1) ;
1006   if (mplt(MPnumber, MP1)) *optr++ = '-' ;
1007   mpstr(MPval, MPmant) ;
1008  
1009   mpcim(&basevals[(int) v->base], MP1base) ;
1010   n = 3 ;
1011   mppwr(MP1base, &n, MP3base) ;
1012  
1013   n = 10 ;
1014   mppwr(MP1base, &n, MP10base) ;
1015  
1016   n = 1 ;
1017   mpcim(&n, MP1) ;
1018   mpdiv(MP1, MP10base, MPatmp) ;
1019  
1020   n = 0 ;
1021   mpcim(&n, MP1) ;
1022   if (!mpeq(MPmant, MP1))
1023     {
1024       while (mpge(MPmant, MP10base))
1025         {
1026           exp += 10 ;
1027           mpmul(MPmant, MPatmp, MPmant) ;
1028         }
1029
1030       while ((!eng &&  mpge(MPmant, MP1base)) ||
1031               (eng && (mpge(MPmant, MP3base) || exp % 3 != 0)))
1032         {
1033           exp += 1 ;
1034           mpdiv(MPmant, MP1base, MPmant) ;
1035         }
1036
1037       while (mplt(MPmant, MPatmp))
1038         {
1039           exp -= 10 ;
1040           mpmul(MPmant, MP10base, MPmant) ;
1041         }
1042
1043       n = 1 ;
1044       mpcim(&n, MP1) ;
1045       while (mplt(MPmant, MP1) || (eng && exp % 3 != 0))
1046         {
1047           exp -= 1 ;
1048           mpmul(MPmant, MP1base, MPmant) ;
1049         }
1050     }    
1051
1052   STRCPY(fixed, make_fixed(MPmant, MAX_DIGITS-6)) ;
1053   len = strlen(fixed) ;
1054   for (i = 0; i < len; i++) *optr++ = fixed[i] ;
1055
1056   *optr++ = 'e' ;
1057
1058   if (exp < 0)
1059     {
1060       exp = -exp ;
1061       *optr++ = '-' ;
1062     }
1063   else *optr++ = '+' ;
1064
1065   MPstr_to_num("0.5", DEC, MP1) ;
1066   mpaddi(MP1, &exp, MPval) ;
1067   n = 1 ;
1068   mpcim(&n, MP1) ;
1069   for (ddig = 0; mpge(MPval, MP1); ddig++)
1070     mpdiv(MPval, MP1base, MPval) ;
1071
1072   if (ddig == 0) *optr++ = '0' ;
1073
1074   while (ddig-- > 0)
1075     {
1076       mpmul(MPval, MP1base, MPval) ;
1077       mpcmi(MPval, &dval) ;
1078       *optr++ = digits[dval] ;
1079       dval = -dval ;
1080       mpaddi(MPval, &dval, MPval) ;
1081     }
1082   *optr++    = '\0' ;
1083   v->toclear = 1 ;
1084   v->pointed = 0 ;
1085   return(v->snum) ;
1086 }
1087
1088
1089 char *
1090 make_fixed(MPnumber, cmax)     /* Convert MP number to fixed number string. */
1091 int *MPnumber ;
1092 int cmax ;                     /* Maximum characters to generate. */
1093 {
1094   char *optr ;
1095   int MP1base[MP_SIZE], MP1[MP_SIZE], MP2[MP_SIZE], MPval[MP_SIZE] ;
1096   int ndig ;                   /* Total number of digits to generate. */
1097   int ddig ;                   /* Number of digits to left of . */
1098   int dval, n ;
1099  
1100   optr = v->fnum ;
1101   mpabs(MPnumber, MPval) ;
1102   n = 0 ;
1103   mpcim(&n, MP1) ;
1104   if (mplt(MPnumber, MP1)) *optr++ = '-' ;
1105  
1106   mpcim(&basevals[(int) v->base], MP1base) ;
1107  
1108   mppwr(MP1base, &v->accuracy, MP1) ;
1109   MPstr_to_num("0.5", DEC, MP2) ;
1110   mpdiv(MP2, MP1, MP1) ;
1111   mpadd(MPval, MP1, MPval) ;
1112  
1113   n = 1 ;
1114   mpcim(&n, MP2) ;
1115   if (mplt(MPval, MP2))
1116     {
1117       ddig = 0 ;
1118       *optr++ = '0' ;
1119       cmax-- ;
1120     }
1121   else
1122     for (ddig = 0; mpge(MPval, MP2); ddig++)
1123       mpdiv(MPval, MP1base, MPval) ;
1124
1125   ndig = MIN(ddig + v->accuracy, --cmax) ;
1126
1127   while (ndig-- > 0)
1128     {
1129       if (ddig-- == 0) *optr++ = '.' ;
1130       mpmul(MPval, MP1base, MPval) ;
1131       mpcmi(MPval, &dval) ;
1132       *optr++ = digits[dval] ;
1133       dval = -dval ;
1134       mpaddi(MPval, &dval, MPval) ;
1135     }
1136   *optr++    = '\0' ;
1137   v->toclear = 1 ;
1138   v->pointed = 0 ;
1139   return(v->fnum) ;
1140 }
1141
1142
1143 void
1144 make_items()
1145 {
1146   set_item(DISPLAYITEM, v->display) ;
1147   set_item(OPITEM,      "    ") ;
1148   set_item(HYPITEM,     "    ") ;
1149   set_item(INVITEM,     "    ") ;
1150 }
1151
1152
1153 char *
1154 make_number(MPnumber, mkFix)     /* Convert MP number to character string. */
1155 int *MPnumber ;
1156 BOOLEAN mkFix ;
1157 {
1158   double number, val ;
1159
1160 /*  NOTE: make_number can currently set v->error when converting to a double.
1161  *        This is to provide the same look&feel as V3 even though dtcalc
1162  *        now does internal arithmetic to "infinite" precision.
1163  *
1164  *  XXX:  Needs to be improved. Shouldn't need to convert to a double in
1165  *        order to do these tests.
1166  */  
1167      
1168   mpcmd(MPnumber, &number) ;
1169   val = fabs(number) ;
1170   if (v->error) return(vstrs[(int) V_ERROR]) ;
1171   if (v->dtype == ENG || v->dtype == SCI ||
1172        v->dtype == FIX && val != 0.0 && (val > max_fix[(int) v->base]))
1173      return(make_eng_sci(MPnumber)) ;
1174   else if (v->dtype == FIX && val != 0.0 && mkFix)
1175   {
1176      if(v->accuracy == 0)
1177      {
1178         if(val <= min_fix0[(int) v->base])
1179            return(make_eng_sci(MPnumber)) ;
1180         else
1181            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1182      }
1183      else if(v->accuracy == 1)
1184      {
1185         if(val <= min_fix1[(int) v->base])
1186            return(make_eng_sci(MPnumber)) ;
1187         else
1188            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1189      }
1190      else if(v->accuracy == 2)
1191      {
1192         if(val <= min_fix2[(int) v->base])
1193            return(make_eng_sci(MPnumber)) ;
1194         else
1195            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1196      }
1197      else if(v->accuracy == 3)
1198      {
1199         if(val <= min_fix3[(int) v->base])
1200            return(make_eng_sci(MPnumber)) ;
1201         else
1202            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1203      }
1204      else if(v->accuracy == 4)
1205      {
1206         if(val <= min_fix4[(int) v->base])
1207            return(make_eng_sci(MPnumber)) ;
1208         else
1209            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1210      }
1211      else if(v->accuracy == 5)
1212      {
1213         if(val <= min_fix5[(int) v->base])
1214            return(make_eng_sci(MPnumber)) ;
1215         else
1216            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1217      }
1218      else if(v->accuracy == 6)
1219      {
1220         if(val <= min_fix6[(int) v->base])
1221            return(make_eng_sci(MPnumber)) ;
1222         else
1223            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1224      }
1225      else if(v->accuracy == 7)
1226      {
1227         if(val <= min_fix7[(int) v->base])
1228            return(make_eng_sci(MPnumber)) ;
1229         else
1230            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1231      }
1232      else if(v->accuracy == 8)
1233      {
1234         if(val <= min_fix8[(int) v->base])
1235            return(make_eng_sci(MPnumber)) ;
1236         else
1237            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1238      }
1239      else if(v->accuracy == 9)
1240      {
1241         if(val <= min_fix9[(int) v->base])
1242            return(make_eng_sci(MPnumber)) ;
1243         else
1244            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1245      }
1246   }
1247   else 
1248      return(make_fixed(MPnumber, MAX_DIGITS)) ;
1249 }
1250
1251
1252 /*ARGSUSED*/
1253 int
1254 matherr(exc)        /* Default math library exception handling routine. */
1255 struct exception *exc ;
1256 {
1257   char msg[100];
1258   
1259 #if 0
1260   if (exc) {
1261           strcpy(msg, exc->name);
1262           strcat(msg, ": ");
1263           if(exc->type == DOMAIN)
1264              strcat(msg, "DOMAIN ");
1265           else if(exc->type == SING)
1266              strcat(msg, "SING ");
1267           else if(exc->type == OVERFLOW)
1268              strcat(msg, "OVERFLOW ");
1269           else if(exc->type == UNDERFLOW)
1270              strcat(msg, "UNDERFLOW ");
1271           else if(exc->type == TLOSS)
1272              strcat(msg, "TLOSS ");
1273           else if(exc->type == PLOSS)
1274              strcat(msg, "PLOSS ");
1275           
1276           strcat(msg, vstrs[(int) V_ERROR]);
1277
1278           _DtSimpleError (v->appname, DtWarning, NULL, msg);
1279   }
1280 #endif
1281
1282   doerr(vstrs[(int) V_ERROR]) ;
1283   return(1) ;                     /* Value ignored. */
1284 }
1285
1286
1287 void
1288 MPstr_to_num(str, base, MPval)    /* Convert string into an MP number. */
1289 char *str ;
1290 enum base_type base ;
1291 int *MPval ;
1292 {
1293   char   *optr ;
1294   int MP1[MP_SIZE], MP2[MP_SIZE], MPbase[MP_SIZE] ;
1295   int    i, inum ;
1296   int    neg      = 0 ;
1297   int    exp      = 0 ;
1298   int    exp_sign = 1 ;
1299
1300   i = 0 ;
1301   mpcim(&i, MPval) ;
1302   mpcim(&basevals[(int) base], MPbase) ;
1303   optr = str ;
1304   while (*optr == ' ') optr++ ;
1305   if(*optr == '-')
1306   {
1307      /* negative number */
1308      optr++ ;
1309      neg = 1;
1310   }
1311   while ((inum = char_val(*optr)) >= 0)
1312     {
1313       mpmul(MPval, MPbase, MPval) ;
1314       mpaddi(MPval, &inum, MPval) ;
1315       optr++ ;
1316     }
1317
1318   if (*optr == '.')
1319     for (i = 1; (inum = char_val(*++optr)) >= 0; i++)
1320       {  
1321         mppwr(MPbase, &i, MP1) ;
1322         mpcim(&inum, MP2) ;
1323         mpdiv(MP2, MP1, MP1) ;
1324         mpadd(MPval, MP1, MPval) ;
1325       }
1326  
1327   while (*optr == ' ') optr++ ;
1328
1329   if (*optr != '\0')
1330     {
1331       if (*optr == '-') exp_sign = -1 ;
1332
1333       while ((inum = char_val(*++optr)) >= 0)
1334         exp = exp * basevals[(int) base] + inum ;
1335     }
1336   exp *= exp_sign ;
1337
1338   if (v->key_exp || exp_sign == -1) 
1339     {
1340       mppwr(MPbase, &exp, MP1) ;
1341       mpmul(MPval, MP1, MPval) ;
1342     }
1343   if( neg == 1)
1344   {
1345       i = -1 ;
1346       mpcim(&i, MP1) ;
1347       mpmul(MPval, MP1, MPval) ;
1348   }
1349 }
1350
1351
1352 void
1353 paren_disp(c)   /* Append the latest parenthesis char to the display item. */
1354 char c ;
1355 {
1356   int i, n ;
1357
1358 /*  If the character is a Delete, clear the whole line, and exit parenthesis
1359  *  processing.
1360  *
1361  *  If the character is a Back Space, remove the last character. If the last
1362  *  character was a left parenthesis, decrement the parentheses count. If
1363  *  the parentheses count is zero, exit parenthesis processing.
1364  *
1365  *  If the character is a control character (not Ctrl-h), then append ^(char).
1366  *
1367  *  Otherwise just append the character.
1368  */
1369  
1370   n = strlen(v->display) ;
1371   if (IS_KEY(c, KEY_CLR))             /* Is it a Delete character? */
1372     {
1373       v->noparens = v->pending = v->opsptr = v->numsptr = 0 ;
1374       v->cur_op = '?' ;
1375       set_item(OPITEM, "") ;
1376       i = 0 ;
1377       mpcim(&i, v->MPdisp_val) ;
1378       show_display(v->MPdisp_val) ;
1379       set_base(v->base);
1380       set_numtype(v->dtype);
1381       set_option_menu((int) TTYPEITEM, (int)v->ttype);
1382       make_modewin() ;
1383       v->curwin = FCP_KEY ;
1384       v->defState = 1;
1385       return ;
1386     }
1387   else if (IS_KEY(c, KEY_BSP))        /* Is is a Back Space character? */
1388     {
1389       if (!n) return ;
1390       if (v->display[n-1] == '(')
1391         {
1392           v->noparens-- ;
1393           if (!v->noparens)
1394             {
1395               v->pending = v->opsptr = v->numsptr = 0 ;
1396               v->cur_op = '?' ;
1397               set_item(OPITEM, "") ;
1398               show_display(v->MPdisp_val) ;
1399               return ;
1400             }
1401         }
1402       v->display[n-1] = '\0' ;
1403     }
1404   else if (c <= CTL('z'))             /* Is it a control character? */
1405     {
1406       if (n < MAXLINE-2)
1407         {
1408           v->display[n]   = '^' ;
1409           v->display[n+1] = c + 96 ;
1410           v->display[n+2] = '\0' ;
1411         }
1412     }    
1413   else                                /* It must be an ordinary character. */
1414     {
1415       if (n < MAXLINE-1)
1416         {
1417           v->display[n]   = c ;
1418           v->display[n+1] = '\0' ;
1419         }
1420     }    
1421
1422   n = (n < MAX_DIGITS) ? 0 : n - MAX_DIGITS ;
1423   v->show_paren = 1 ;       /* Hack to get set_item to really display it. */
1424   set_item(DISPLAYITEM, &v->display[n]) ;
1425   v->show_paren = 0 ;
1426 }
1427
1428
1429 void
1430 process_event(type)       /* Process this event. */
1431 int type ;
1432 {
1433   int ival ;
1434
1435   switch (type)
1436     {
1437       case KEYBOARD_DOWN   : if (v->pending)
1438                                {
1439                                  v->current = v->cur_ch ;
1440                                  do_pending() ;
1441                                }
1442                              else
1443                                { 
1444                                  ival = get_index(v->cur_ch) ;
1445                                  if (ival < TITEMS - EXTRA) {
1446                                     if ((v->modetype == FINANCIAL && 
1447                                                                  ival == 23) ||
1448                                         (v->modetype == LOGICAL && (
1449                                                     ival == 21 || ival == 22 || 
1450                                                                  ival == 23)))
1451                                        break;
1452                                     else
1453                                        /* go arm the button */
1454                                        draw_button(ival, v->curwin, v->row, 
1455                                                    v->column, TRUE) ;
1456                                  }
1457                                  process_item(ival) ;
1458                                }
1459                              break ;
1460
1461       case KEYBOARD_UP     : ival = get_index(v->cur_ch) ;
1462                              if (ival < TITEMS - EXTRA) {
1463                                  if ((v->modetype == FINANCIAL && 
1464                                                               ival == 23) ||
1465                                      (v->modetype == LOGICAL && (
1466                                                  ival == 21 || ival == 22 ||
1467                                                               ival == 23)))
1468                                     break;
1469                                  else
1470                                     /* go disarm the button */
1471                                     draw_button(ival, v->curwin, v->row, 
1472                                                 v->column, FALSE) ;
1473                              }
1474                              /* go disarm the button */
1475                              draw_button(ival, v->curwin, v->row, 
1476                                                 v->column, FALSE) ;
1477                              break ;
1478  
1479     }
1480 }
1481
1482
1483 void
1484 process_item(n)
1485 int n ;
1486 {
1487   int i,isvalid ;
1488
1489   if (n < 0 || n >= TITEMS)
1490     {
1491       beep() ;
1492       v->error = TRUE;
1493     }
1494
1495   v->current = buttons[n].value ;
1496   if (v->current == '*') v->current = 'x' ;      /* Reassign "extra" values. */
1497   if (v->current == '\015') v->current = '=' ;
1498   if (v->current == 'Q') v->current = 'q' ;
1499
1500   if (v->error)
1501     {
1502       isvalid = 0 ;                    /* Must press a valid key first. */
1503       for (i = 0; i < MAXVKEYS; i++)
1504         if (v->current == validkeys[i]) isvalid = 1 ;
1505       if (v->pending == '?') isvalid = 1 ;
1506       if (!isvalid) return ;
1507       v->error = 0 ;
1508     }
1509
1510   if (v->pending)
1511     {
1512       if (v->pending_win == FCP_KEY) (*buttons[v->pending_n].func)() ;
1513       else (*mode_buttons[MODEKEYS * ((int) v->pending_mode - 1) +
1514             v->pending_n].func)() ;
1515       return ;
1516     }
1517   switch (buttons[n].opdisp)
1518     {
1519       case OP_SET   : 
1520          if (v->current == 'T') 
1521          {
1522              if (v->modetype == SCIENTIFIC)
1523                 set_item(OPITEM, buttons[n].str) ;
1524              else
1525                 v->pending = 0;
1526          }
1527          else
1528             set_item(OPITEM, buttons[n].str) ;
1529          break ;
1530       case OP_CLEAR : 
1531          if (v->error) 
1532             set_item(OPITEM, vstrs[(int) V_CLR]) ;
1533          else 
1534             set_item(OPITEM, "") ;
1535     }
1536   (*buttons[n].func)() ;
1537
1538   if(strcmp(buttons[n].resname, "clr") != 0)
1539       v->defState = 0;
1540 }
1541
1542
1543 /* Process a portion of the parentheses stack. */
1544
1545 void
1546 process_stack(startop, startnum, n)
1547 int startop ;         /* Initial position in the operand stack. */
1548 int startnum ;        /* Initial position in the numeric stack. */
1549 int n ;               /* Number of items to process. */
1550 {
1551   char sdisp[MAXLINE] ;     /* Used to save display contents. */
1552   int i ;
1553   int nptr ;                /* Pointer to next number from numeric stack. */
1554
1555   STRCPY(sdisp, v->display) ;  /* Save current display. */
1556   nptr = startnum ;
1557   v->pending = 0 ;
1558   v->cur_op = '?' ;            /* Current operation is initially undefined. */
1559   for (i = 0; i < n; i++)
1560     {
1561       if (v->opstack[startop + i] == -1)
1562         {
1563           mpstr(v->MPnumstack[nptr++], v->MPdisp_val) ;
1564         }
1565       else
1566         { 
1567           v->cur_ch = v->opstack[startop + i] ;
1568           if (v->cur_ch == '^')                    /* Control character? */
1569             {
1570               i++ ;
1571               v->cur_ch = CTL(v->opstack[startop + i]) ;
1572             }
1573           if (v->pending)
1574             {
1575               v->current = v->cur_ch ;
1576               do_pending() ;
1577             }
1578           else process_item(get_index(v->cur_ch)) ;
1579         }
1580     }    
1581   v->numsptr = startnum ;
1582   push_num(v->MPdisp_val) ;
1583   v->opsptr = startop - 1 ;
1584   push_op(-1) ;
1585   save_pending_values(KEY_LPAR) ;
1586   STRCPY(v->display, sdisp) ;  /* Restore current display. */
1587 }
1588
1589
1590 void
1591 process_str(str, mtype)
1592 char *str ;
1593 enum menu_type mtype ;
1594 {
1595   int i, len ;
1596   char save[80];
1597
1598   len = strlen(str) ;
1599   STRCPY(save, v->display) ;
1600   STRCPY(v->display, " ") ;
1601   set_item(DISPLAYITEM, v->display);
1602   for (i = 0 ; i < len; i++)
1603     {    
1604       if(str[i] == '*')
1605          str[i] = 'x';
1606       if (v->error) 
1607       {
1608         if(mtype == M_FUN)
1609         {
1610            STRCPY(v->display, save);
1611            set_item(DISPLAYITEM, v->display);
1612            v->error = 0;
1613         }
1614         return ;
1615       }
1616       if (v->pending)
1617         {
1618           v->current = str[i] ;
1619           do_pending() ;
1620         }
1621       else 
1622         switch(v->base)
1623         {
1624            case DEC:
1625               if(str[i] == 'a' ||
1626                  str[i] == 'b' ||
1627                  str[i] == 'c' ||
1628                  str[i] == 'd' ||
1629                  str[i] == 'e' ||
1630                  str[i] == 'f')
1631               {
1632                  v->error = True;
1633                  beep();
1634                  break;
1635               }
1636            default:
1637               process_item(get_index(str[i])) ;
1638         }
1639     }
1640 }
1641
1642
1643 void
1644 read_rcfiles()   /* Read .dtcalcrc's from home and current directories. */
1645 {
1646   char *home ;                  /* Pathname for users home directory. */
1647   char name[MAXPATHLEN + 50] ;          /* Full name of users .dtcalcrc file. */
1648   char pathname[MAXPATHLEN + 5] ;   /* Current working directory. */
1649   char tmp[MAXLINE] ;           /* For temporary constant string creation. */
1650   int n ;
1651   struct passwd *entry ;
1652
1653   for (n = 0; n < MAXREGS; n++)
1654     {
1655       STRCPY(tmp, make_number(v->MPcon_vals[n], FALSE)) ;
1656       SPRINTF(name, "%1d: %s [%s]", n, tmp, v->con_names[n]) ;
1657
1658       STRCPY(v->con_names[n], name) ;
1659       STRCPY(v->fun_vals[n], "") ;    /* Initially empty function strings. */
1660     }
1661
1662   if ((home = getenv("HOME")) == NULL)
1663     {
1664       if ((entry = getpwuid(getuid())) == NULL) return ;
1665       home = entry->pw_dir ;
1666     }
1667   SPRINTF(name, "%s/%s", home, RCNAME) ;
1668   get_rcfile(name) ;      /* Read .dtcalcrc from users home directory. */
1669  
1670   SPRINTF(name, "%s/%s", getcwd(pathname, MAXPATHLEN+1), RCNAME) ;
1671   get_rcfile(name) ;      /* Read .dtcalcrc file from current directory. */
1672 }
1673
1674
1675 void
1676 show_display(MPval)
1677 int *MPval ;
1678 {
1679   if (!v->error)
1680     {
1681       STRCPY(v->display, make_number(MPval, TRUE)) ;
1682       set_item(DISPLAYITEM, v->display) ;
1683     }
1684 }
1685
1686
1687 void
1688 usage(progname)
1689 char *progname ;
1690 {
1691   FPRINTF(stderr, ustrs[(int) USAGE1], PATCHLEVEL) ;
1692   FPRINTF(stderr, ustrs[(int) USAGE2]) ;
1693   FPRINTF(stderr, ustrs[(int) USAGE3]) ;
1694   exit(1) ;
1695 }
1696
1697 void
1698 write_rcfile(mtype, exists, cfno, val, comment)
1699 enum menu_type mtype ;
1700 int exists, cfno ;
1701 char *val, *comment ;
1702 {
1703   char *home ;                  /* Pathname for users home directory. */
1704   char pathname[MAXPATHLEN] ;   /* Current working directory. */
1705   char rcname[MAXPATHLEN] ;     /* Full name of users .dtcalcrc file. */
1706   char str[MAXLINE] ;           /* Temporary buffer. */
1707   char sval[3] ;                /* Used for string comparisons. */
1708   char tmp_filename[MAXLINE] ;  /* Used to construct temp filename. */
1709   int rcexists ;                /* Set to 1, if .dtcalcrc file exists. */
1710   FILE *rcfd ;                  /* File descriptor for .dtcalcrc file. */
1711   FILE *tmpfd ;                 /* File descriptor for new temp .dtcalcrc. */
1712   struct passwd *entry ;        /* The user's /etc/passwd entry. */
1713
1714   rcexists = 0 ;
1715   SPRINTF(rcname, "%s/%s", getcwd(pathname, MAXPATHLEN), RCNAME) ;
1716   if (access(rcname, F_OK) == 0) rcexists = 1 ;
1717   else
1718     { 
1719       if ((home = getenv("HOME")) == NULL)
1720         {
1721           if ((entry = getpwuid(getuid())) == NULL) return ;
1722           home = entry->pw_dir ;
1723         }
1724       SPRINTF(rcname, "%s/%s", home, RCNAME) ;
1725       if (access(rcname, F_OK) == 0) rcexists = 1 ;
1726     }
1727   STRCPY(tmp_filename, "/tmp/.dtcalcrcXXXXXX") ;
1728   MKTEMP(tmp_filename) ;
1729   if ((tmpfd = fopen(tmp_filename, "w+")) == NULL) return ;
1730
1731   if (rcexists)
1732     {
1733       rcfd = fopen(rcname, "r") ;
1734       SPRINTF(sval, " %1d", cfno) ;
1735       while (fgets(str, MAXLINE, rcfd))
1736         {
1737           if (exists)
1738             {
1739               switch (mtype)
1740                 {
1741                   case M_CON : sval[0] = 'c' ;
1742                                if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1743                                sval[0] = 'C' ;
1744                                if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1745                                break ;
1746                   case M_FUN : sval[0] = 'f' ;
1747                                if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1748                                sval[0] = 'F' ;
1749                                if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1750                 }
1751             }    
1752           FPRINTF(tmpfd, "%s", str) ;
1753         }
1754       FCLOSE(rcfd) ;
1755     }
1756
1757   switch (mtype)
1758     {
1759       case M_CON : FPRINTF(tmpfd, "\nC%1d %s %s\n", cfno, val, comment) ;
1760                    break ;
1761       case M_FUN : 
1762                if(strcmp(val, "") != 0)
1763                   FPRINTF(tmpfd, "\nF%1d %s %s\n", cfno, val, comment) ;
1764     }
1765   UNLINK(rcname) ;
1766   rcfd = fopen(rcname, "w") ;
1767   REWIND(tmpfd) ;
1768   while (fgets(str, MAXLINE, tmpfd)) FPRINTF(rcfd, "%s", str) ;
1769   FCLOSE(rcfd) ;
1770   FCLOSE(tmpfd);
1771   UNLINK(tmp_filename) ;
1772 }
1773
1774
1775 void
1776 write_resources(filename)
1777 char *filename;
1778 {
1779   char regval[5] ;
1780   char intval[5] ;
1781   int i;
1782   int MPtemp[MP_SIZE];
1783
1784   SPRINTF(intval, "%d", v->accuracy) ;
1785   put_resource(R_ACCURACY, intval) ;
1786   put_resource(R_DISPLAYED, v->display) ;
1787   put_resource(R_BASE,     base_str[(int) v->base]) ;
1788   put_resource(R_DISPLAY,  dtype_str[(int) v->dtype]) ;
1789   put_resource(R_MODE,     mode_str[(int) v->modetype]) ;
1790   put_resource(R_TRIG,     ttype_str[(int) v->ttype]) ;
1791   put_resource(R_REGS,     set_bool(v->rstate     == TRUE)) ;
1792
1793   put_resource(R_REG0,     make_number(v->MPmvals[0], FALSE)) ;
1794   put_resource(R_REG1,     make_number(v->MPmvals[1], FALSE)) ;
1795   put_resource(R_REG2,     make_number(v->MPmvals[2], FALSE)) ;
1796   put_resource(R_REG3,     make_number(v->MPmvals[3], FALSE)) ;
1797   put_resource(R_REG4,     make_number(v->MPmvals[4], FALSE)) ;
1798   put_resource(R_REG5,     make_number(v->MPmvals[5], FALSE)) ;
1799   put_resource(R_REG6,     make_number(v->MPmvals[6], FALSE)) ;
1800   put_resource(R_REG7,     make_number(v->MPmvals[7], FALSE)) ;
1801   put_resource(R_REG8,     make_number(v->MPmvals[8], FALSE)) ;
1802   put_resource(R_REG9,     make_number(v->MPmvals[9], FALSE)) ;
1803
1804   mpcdm(&(v->MPfvals[0]), MPtemp);
1805   put_resource(R_FREG0,     make_number(MPtemp, FALSE)) ;
1806   mpcdm(&(v->MPfvals[1]), MPtemp);
1807   put_resource(R_FREG1,     make_number(MPtemp, FALSE)) ;
1808   mpcdm(&(v->MPfvals[2]), MPtemp);
1809   put_resource(R_FREG2,     make_number(MPtemp, FALSE)) ;
1810   mpcdm(&(v->MPfvals[3]), MPtemp);
1811   put_resource(R_FREG3,     make_number(MPtemp, FALSE)) ;
1812   mpcdm(&(v->MPfvals[4]), MPtemp);
1813   put_resource(R_FREG4,     make_number(MPtemp, FALSE)) ;
1814   mpcdm(&(v->MPfvals[5]), MPtemp);
1815   put_resource(R_FREG5,     make_number(MPtemp, FALSE)) ;
1816
1817   save_resources(filename) ;
1818 }