Remove legacysun code blocks
[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 libraries 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 <sys/types.h>
41 #include <sys/file.h>
42 #include <sys/param.h>
43 #include <pwd.h>
44 #include <math.h>
45 #include "patchlevel.h"
46 #include "calctool.h"
47 #include "ds_common.h"
48
49 time_t time() ;
50
51 double max_fix[4] = {
52           6.871947674e+10, 3.245185537e+32,
53           1.000000000e+36, 2.230074520e+43
54 } ;
55 double min_fix0[4] = {
56           2.500000000e-1, 3.750000000e-1,
57           1.000000000e-1, 4.375000000e-1
58 } ;
59 double min_fix1[4] = {
60           1.250000000e-1, 4.687500000e-2,
61           1.000000000e-2, 2.734375000e-2
62 } ;
63 double min_fix2[4] = {
64           6.250000000e-2, 5.859375000e-3,
65           1.000000000e-3, 1.708984375e-3
66 } ;
67 double min_fix3[4] = {
68           3.125000000e-2, 7.324218750e-4,
69           1.000000000e-4, 1.068115234e-4
70 } ;
71 double min_fix4[4] = {
72           1.562500000e-2, 9.155273437e-5,
73           1.000000000e-5, 6.675720215e-6
74 } ;
75 double min_fix5[4] = {
76           7.812500000e-3, 1.144409180e-5,
77           1.000000000e-6, 4.172325134e-7
78 } ;
79 double min_fix6[4] = {
80           6.906250000e-3, 1.430511475e-6,
81           1.000000000e-7, 2.607703209e-8
82 } ;
83 double min_fix7[4] = {
84           1.953125000e-3, 1.788139343e-7,
85           1.000000000e-8, 1.629814506e-9
86 } ;
87 double min_fix8[4] = {
88           9.765625000e-4, 2.235174179e-8,
89           1.000000000e-9, 1.018634066e-10
90 } ;
91 double min_fix9[4] = {
92           4.882812500e-4, 2.793967724e-9,
93           1.000000000e-10, 6.366462912e-12
94 } ;
95
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. */
106
107 char digits[] = "0123456789ABCDEF" ;
108 int basevals[4] = { 2, 8, 10, 16 } ;
109
110 int left_pos[BCOLS]  = { 3, 2, 1, 0 } ;  /* Left positions. */
111 int right_pos[BCOLS] = { 0, 1, 2, 3 } ;  /* "Right" positions. */
112
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' } ;
116
117 Vars v ;            /* Calctool variables and options. */
118
119 struct menu_entry menu_entries[MAXENTRIES] ;
120
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 */
133 } ;
134
135 /*  This table shows the keyboard values that are currently being used:
136  *
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  *----------------------------------------------------------------
145  */
146
147 /* Calculator button values. */
148
149 struct button buttons[TITEMS] = {
150 /*     str       str2      value opdisp   menutype   resname  func */
151
152 /* Row 1. */
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    },
157
158 /* Row 2. */
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   },
163
164 /* Row 3. */
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 },
169
170 /* Row 4. */
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 },
175
176 /* Row 5. */ 
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 },
181
182 /* Row 6. */ 
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 },
187
188 /* Row 7. */
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   },
193
194 /* Row 8. */
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   },
199
200 /* Row 9. */
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   },
205
206 /* Row 10. */
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    },
211
212 /* Row 11. */
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    },
217
218 /* Row 12. */
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    },
223
224 /* Row 13. */
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    },
229
230 /* Row 14. */
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   },
235
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 },
240 } ; 
241
242 struct button mode_buttons[MAXMODES * MODEKEYS] = {
243 /*     str       str2      value opdisp   menutype   resname  func */
244
245 /* Financial. */
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    },
262
263 /* Logical. */
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    },
280
281 /* Scientific. */
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    },
298 } ;
299
300
301 int
302 char_val(char chr)
303 {
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) ;
307   else return(-1) ;
308 }
309
310
311 void
312 clear_display(void)
313 {
314   int i ;
315  
316   v->pointed = 0 ;
317   v->toclear = 1 ;
318   v->defState = 1 ;
319   i = 0 ;
320   mpcim(&i, v->MPdisp_val) ;
321   STRCPY(v->display, make_number(v->MPdisp_val, FALSE)) ;
322   set_item(DISPLAYITEM, v->display) ;
323   
324   v->hyperbolic = 0 ;
325   v->inverse    = 0 ;
326   v->show_paren = 0 ;
327   v->opsptr     = 0 ;            /* Clear parentheses stacks. */
328   v->numsptr    = 0 ;
329   set_item(HYPITEM, "    ") ;
330   set_item(INVITEM, "    ") ;
331 }
332
333 /* Convert .dtcalcrc line to ascii values. */
334 /* line    Input line to be converted. */
335 char *
336 convert(char *line)
337 {
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. */
341   int len ;
342   int n = 0 ;              /* Position within output line. */
343  
344   len = strlen(line) ;
345   for (i = 0; i < len; i++)
346     {
347            if (line[i] == ' ') continue ;
348       else if (line[i] == '\\') ctrl = 1 ;
349       else if (ctrl)
350         {
351           output[n++] = CTL(line[i]) ;
352           ctrl = 0 ;
353         }
354       else output[n++] = line[i] ;
355     }
356   output[n] = '\0' ;
357   return(output) ;
358 }
359
360
361 void
362 do_dtcalc(int argc, char **argv)
363 {
364   char *ptr ;
365
366   v->progname = argv[0] ;     /* Save programs name. */
367   v->appname  = NULL ;
368   init_cmdline_opts() ;       /* Initialize command line option strings. */
369
370   if ((ptr = strrchr(argv[0], '/')) != NULL)
371     read_str(&v->appname, ptr+1) ;
372   else read_str(&v->appname, argv[0]) ;
373
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)
381   {
382       RestoreSession(); 
383   }
384   read_rcfiles() ;            /* Read .dtcalcrc's files. */
385   init_graphics() ;
386   make_frames() ;             /* Create dtcalc window frames. */
387
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. */
397
398   srand48((long) time((time_t *) 0)) ;   /* Seed random number generator. */
399
400   make_items() ;              /* Create server images and fir frames. */
401   if(v->display[0] == 0)
402      do_clear() ;                /* Initialize and clear display. */
403
404   if (v->rstate == TRUE)      /* Show the memory register window? */
405     {
406       make_registers(MEM) ;
407       if (!v->iconic) win_display(FCP_REG, TRUE) ;
408     }
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. */
413 }
414
415
416 /* Dtcalc's customised math library error-handling routine. */
417
418 void
419 doerr(char *errmes)
420 {
421   if (!v->started) return ;
422   STRCPY(v->display, errmes) ;
423   set_item(DISPLAYITEM, v->display) ;
424   v->error = 1 ;
425   beep() ;
426   set_item(OPITEM, vstrs[(int) V_CLR]) ;
427 }
428
429 /* Get boolean resource from database. */
430 int
431 get_bool_resource(enum res_type rtype, int *boolval)
432 {
433   char *val, tempstr[MAXLINE] ;
434   int len, n ;
435  
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 ;
443   return(1) ;
444 }
445
446
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.
451  *
452  *  XXX: This routine can be improved by using a hash lookup table.
453  */
454  
455 int
456 get_index(char ch)
457 {
458   int n ;
459  
460   for (n = 0; n < TITEMS; n++) {
461     if (ch == buttons[n].value)  
462        break ;
463   }
464   if (n < TITEMS) 
465      v->curwin = FCP_KEY ;
466   else
467   {
468      return(TITEMS) ;
469   }
470   v->row = n / MAXCOLS ;
471   v->column = n - (v->row * MAXCOLS) ;
472   return(n) ;
473 }
474
475  /* Get integer resource from database. */
476 int
477 get_int_resource(enum res_type rtype, int *intval)
478 {
479   char *val ;
480
481   if ((val = get_resource(rtype)) == NULL) return(0) ;
482   *intval = atoi(val) ;
483   return(1) ;
484 }
485
486
487 /* Get keyboard equivalent from first character of localised string. */
488
489 void
490 get_key_val(char *val, char *str)
491 {
492   *val = str[0] ;
493 }
494
495
496 void
497 get_label(int n)
498 {
499   char *temp;
500
501   if (v->tstate)
502      temp = buttons[n].str2;
503   else 
504      temp = buttons[n].str;
505
506   if(temp != NULL)
507      STRCPY(v->pstr, temp) ;
508   else
509      STRCPY(v->pstr, "");
510 }
511
512 /* Extract command line options. */
513 void
514 get_options(int argc, char *argv[])
515 {
516   char next[MAXLINE] ;       /* The next command line parameter. */
517   char strval[MAXLINE] ;
518   char *msg;
519   int i, len;
520
521   INC ;
522   while (argc > 0)
523     {
524       if (argv[0][0] == '-' || argv[0][0] == '+')
525         {
526           switch (argv[0][1])
527             {
528               case 'D' : v->MPdebug = TRUE ;   /* MP debug info. to stderr. */
529                          break ;
530               case 'a' : INC ;
531                          getparam(next, argv, opts[(int) O_ACCVAL]) ;
532                          v->accuracy = atoi(next) ;
533                          if (v->accuracy < 0 || v->accuracy > 9)
534                            {
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);
539                              XtFree(msg);
540                              v->accuracy = 2 ;
541                            }
542                          break ;
543               case 'm' : INC ;
544                          msg = (char *) XtMalloc(strlen(opts[(int) O_MODE])+
545                                                              strlen(next) + 3);
546                          sprintf(msg, opts[(int) O_MODE], next);
547                          getparam(next, argv, msg) ;
548                          XtFree(msg);
549                          STRCPY(strval, next) ;
550                          len = strlen(strval) ;
551                          for (i = 0; i < len; i++)
552                          {
553                            if (islower(strval[i])) 
554                               strval[i] = toupper(strval[i]) ;
555                          }
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 ;
562                          else
563                            {
564                              msg = (char *) XtMalloc(strlen(opts[(int) O_MODE])+
565                                                     strlen(next) + 3);
566                              sprintf(msg, opts[(int) O_MODE], next);
567                              _DtSimpleError (v->appname, DtWarning, NULL, msg);
568                              XtFree(msg);
569                              v->modetype = SCIENTIFIC ;
570                            }
571                          break ;
572               case 'b' : INC ;
573                          getparam(next, argv, opts[(int) O_BASE]) ;
574                          STRCPY(strval, next) ;
575                          len = strlen(strval) ;
576                          for (i = 0; i < len; i++)
577                          {
578                            if (islower(strval[i]))
579                               strval[i] = toupper(strval[i]) ;
580                          }
581                          if(strncmp(strval, "BIN", 3) == 0)
582                              v->base = BIN ;
583                          else if(strncmp(strval, "OCT", 3) == 0)
584                              v->base = OCT ;
585                          else if(strncmp(strval, "DEC", 3) == 0)
586                              v->base = DEC ;
587                          else if(strncmp(strval, "HEX", 3) == 0)
588                              v->base = HEX ;
589                          else
590                            {
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);
595                              XtFree(msg);
596                              v->base = DEC ;
597                            }
598                          break ;
599               case 'n' : if(strcmp(&argv[0][1], "notation") == 0) 
600                          {
601                             INC ;
602                             msg = (char *) XtMalloc(strlen(
603                                                  opts[(int) O_DISPLAY]) + 
604                                                  strlen(next) + 3);
605                             sprintf(msg, opts[(int) O_DISPLAY], next);
606                             getparam(next, argv, msg) ;
607                             XtFree(msg);
608                             STRCPY(strval, next) ;
609                             len = strlen(strval) ;
610                             for (i = 0; i < len; i++)
611                             {
612                               if (islower(strval[i]))
613                                  strval[i] = toupper(strval[i]) ;
614                             }
615                             if(strncmp(strval, "FIX", 3) == 0)
616                                 v->dtype = FIX ;
617                             else if(strncmp(strval, "ENG", 3) == 0)
618                                 v->dtype = ENG ;
619                             else if(strncmp(strval, "SCI", 3) == 0)
620                                 v->dtype = SCI ;
621                             else
622                               {
623                                 msg = (char *) XtMalloc(strlen(
624                                                     opts[(int) O_DISPLAY]) + 
625                                                     strlen(next) + 3);
626                                 sprintf(msg, opts[(int) O_DISPLAY], next);
627                                 _DtSimpleError (v->appname, DtWarning, NULL, msg);
628                                 XtFree(msg);
629                                 v->dtype = FIX ;
630                               }
631                             break ;
632                          }
633                          else if(strcmp(&argv[0][1], "no_menu_bar") == 0)
634                          {
635                             INC ;
636                             application_args.menuBar = False;
637                             break ;
638                          }
639               case 't' : if(strcmp(&argv[0][1], "trig") == 0)
640                          {
641                             INC ;
642                             msg = (char *) XtMalloc(strlen(
643                                                     opts[(int) O_TRIG]) + 
644                                                     strlen(next) + 3);
645                             sprintf(msg, opts[(int) O_TRIG], next);
646                             getparam(next, argv, msg) ;
647                             XtFree(msg);
648                             STRCPY(strval, next) ;
649                             len = strlen(strval) ;
650                             for (i = 0; i < len; i++)
651                             {
652                               if (islower(strval[i]))
653                                  strval[i] = toupper(strval[i]) ;
654                             }
655                             if(strncmp(strval, "DEG", 3) == 0)
656                                 v->ttype = DEG ;
657                             else if(strncmp(strval, "RAD", 3) == 0)
658                                 v->ttype = RAD ;
659                             else if(strncmp(strval, "GRAD", 4) == 0)
660                                 v->ttype = GRAD ;
661                             else
662                               {
663                                 msg = (char *) XtMalloc(strlen(
664                                                     opts[(int) O_TRIG]) + 
665                                                     strlen(next) + 3);
666                                 sprintf(msg, opts[(int) O_TRIG], next);
667                                 _DtSimpleError (v->appname, DtWarning, NULL, msg);
668                                 XtFree(msg);
669                                 v->ttype = DEG ;
670                               }
671                             break ;
672                          }
673               case 's' : if(strcmp(&argv[0][1], "session") == 0)
674                          {
675                             INC ;
676                             getparam(next, argv, opts[(int) O_SESSION]) ;
677                             application_args.session = XtNewString(next);
678                             break ;
679                          }
680               case '?' :
681               case 'v' : usage(v->progname) ;
682                          break ;
683               default  :
684                          usage(v->progname) ;
685             }
686           INC ;
687         }
688       else INC ;
689     }
690 }
691
692
693 void
694 getparam(char *s, char *argv[], char *errmes)
695 {
696   char *msg;
697
698   if (*argv != NULL && argv[0][0] != '-') STRCPY(s, *argv) ;
699   else
700     { 
701       msg = (char *) XtMalloc(strlen(mess[(int) MESS_PARAM]) + 
702                               strlen(errmes) + 3);
703       sprintf(msg, mess[(int) MESS_PARAM], errmes);
704       _DtSimpleError (v->appname, DtError, NULL, msg);
705       FPRINTF(stderr, mess[(int) MESS_PARAM], errmes) ;
706       exit(1) ;
707     }
708 }
709
710
711 /* Read .dtcalcrc file. */
712 void
713 get_rcfile(char *name)
714 {
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. */
720   int len, n ;            
721   FILE *rcfd ;            /* File descriptor for dtcalc rc file. */
722  
723   if ((rcfd = fopen(name, "r")) == NULL) return ;
724  
725 /*  Process the .dtcalcrc file. There are currently four types of
726  *  records to look for:
727  *
728  *  1) Those starting with a hash in the first column are comments.
729  *
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.
737  *
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.
745  *
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.
751  *
752  *  All other lines are ignored.
753  *
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.
758  */
759
760   while (fgets(line, MAXLINE, rcfd) != NULL)
761     {
762       isval = 0 ;
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' ;
766       if (isval)
767         if (line[1] >= '0' && line[1] <= '9' && line[2] == ' ')
768           {
769             i = char_val(line[1]) ;
770             if (isval == 'c')
771               {  
772                 n = sscanf(&line[3], "%lf", &cval) ;
773                 if (n == 1) 
774                 {
775                    if(line[3] == '-')
776                    {
777                       MPstr_to_num(&line[4], DEC, v->MPcon_vals[i]) ;
778                       mpneg(v->MPcon_vals[i], v->MPcon_vals[i]) ;
779                    }
780                    else
781                       MPstr_to_num(&line[3], DEC, v->MPcon_vals[i]) ;
782                 }
783               }  
784             else if (isval == 'f')
785               {
786                 SSCANF(&line[3], "%s", tmp) ;
787                 STRCPY(v->fun_vals[i], convert(tmp)) ;
788               }  
789             else if (isval == 'r')
790               {  
791                 n = sscanf(&line[3], "%lf", &cval) ;
792                 if (n == 1) MPstr_to_num(&line[3], DEC, v->MPmvals[i]) ;
793                 continue ;
794               }  
795             len = strlen(line) ;
796             for (n = 3; n < len; n++)
797               if (line[n] == ' ' || line[n] == '\n')
798                 {
799                   while (line[n] == ' ') n++ ;
800                   line[strlen(line)-1] = '\0' ;
801                   if (isval == 'c')
802                     {
803                       STRCPY(tmp, make_number(v->MPcon_vals[i], TRUE)) ;
804                       SPRINTF(v->con_names[i], "%1d: %s [%s]",
805                               i, tmp, &line[n]) ;
806                     }
807                   else
808                     SPRINTF(v->fun_names[i], "%1d: %s [%s]",
809                             i, tmp, &line[n]) ;
810                   break ;
811                 }
812           }
813     }
814   FCLOSE(rcfd) ;
815 }
816
817 /* Get a string resource from database. */
818 int
819 get_str_resource(enum res_type rtype, char *strval)
820 {
821   char *val ;
822   int i, len ;
823
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)
828   {
829      for (i = 0; i < len; i++)
830        if (islower(strval[i])) strval[i] = toupper(strval[i]) ;
831   }
832   return(1) ;
833 }
834
835 /* Grey out numeric buttons depending upon base. */
836 void
837 grey_buttons(enum base_type base)
838 {
839   char val ;
840   int column, dim, i, n, row ;
841
842   for (i = 0; i < 16; i++)
843     {
844       val = digits[i] ;
845       if (isupper(val)) val = tolower(val) ;
846       for (n = 0; n < TITEMS; n++)
847         if (val == buttons[n].value) break ;
848       row = n / MAXCOLS ;
849       column = n - (row * MAXCOLS) ;
850
851       if (i < basevals[(int) base]) dim = FALSE ;
852       else                          dim = TRUE ;
853       grey_button(row, column, dim) ;
854     }
855 }
856
857 /* Process right button menu selection. */
858 void
859 handle_menu_selection(int n, int item)
860 {
861   if (item != -1)
862     {
863       if (IS_KEY(v->pending, KEY_LPAR))     /* Are we inside parentheses? */
864         {
865           v->current = buttons[n].value ;
866           do_paren() ;
867           v->current = item ;
868           do_paren() ;
869         }
870       else
871         { 
872           save_pending_values(buttons[n].value) ;
873           v->current = item ;
874           v->ismenu = 1 ;       /* To prevent grey buttons being redrawn. */
875           do_pending() ;
876           v->ismenu = 0 ;
877         }
878     }
879 }
880
881 /* Setup default values for various variables. */
882 void
883 init_vars(void)
884 {
885   int acc, i, n, size ;
886
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 
894                                 initially. */
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. */
899   size          = MP_SIZE ;
900   mpset(&acc, &size, &size) ;
901
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. */
908   v->display[0]  = 0 ;         
909
910   v->x  = 0;
911   v->x  = 0;
912   v->width  = 0;
913   v->height = 0; 
914
915   v->workspaces = NULL; 
916
917   read_str(&v->iconlabel, lstrs[(int) L_LCALC]) ;  /* Default icon label. */
918
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. */
929
930   n = 0 ;
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;
935 }
936
937
938 void
939 initialize(void)
940 {
941   int i ;
942
943   v->error         = 0 ;           /* Currently no display error. */
944   v->cur_op        = '?' ;         /* No arithmetic operator defined yet. */
945   v->old_cal_value = '?' ;
946   i = 0 ;
947   mpcim(&i, v->MPresult) ;         /* No previous result yet. */
948   mpcim(&i, v->MPlast_input) ;
949 }
950
951
952 /* Convert engineering or scientific number. */
953 char *
954 make_eng_sci(int *MPnumber)
955 {
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 */
964  
965   if (v->dtype == ENG) eng = 1 ;
966   optr = v->snum ;
967   mpabs(MPnumber, MPval) ;
968   n = 0 ;
969   mpcim(&n, MP1) ;
970   if (mplt(MPnumber, MP1)) *optr++ = '-' ;
971   mpstr(MPval, MPmant) ;
972  
973   mpcim(&basevals[(int) v->base], MP1base) ;
974   n = 3 ;
975   mppwr(MP1base, &n, MP3base) ;
976  
977   n = 10 ;
978   mppwr(MP1base, &n, MP10base) ;
979  
980   n = 1 ;
981   mpcim(&n, MP1) ;
982   mpdiv(MP1, MP10base, MPatmp) ;
983  
984   n = 0 ;
985   mpcim(&n, MP1) ;
986   if (!mpeq(MPmant, MP1))
987     {
988       while (mpge(MPmant, MP10base))
989         {
990           exp += 10 ;
991           mpmul(MPmant, MPatmp, MPmant) ;
992         }
993
994       while ((!eng &&  mpge(MPmant, MP1base)) ||
995               (eng && (mpge(MPmant, MP3base) || exp % 3 != 0)))
996         {
997           exp += 1 ;
998           mpdiv(MPmant, MP1base, MPmant) ;
999         }
1000
1001       while (mplt(MPmant, MPatmp))
1002         {
1003           exp -= 10 ;
1004           mpmul(MPmant, MP10base, MPmant) ;
1005         }
1006
1007       n = 1 ;
1008       mpcim(&n, MP1) ;
1009       while (mplt(MPmant, MP1) || (eng && exp % 3 != 0))
1010         {
1011           exp -= 1 ;
1012           mpmul(MPmant, MP1base, MPmant) ;
1013         }
1014     }    
1015
1016   STRCPY(fixed, make_fixed(MPmant, MAX_DIGITS-6)) ;
1017   len = strlen(fixed) ;
1018   for (i = 0; i < len; i++) *optr++ = fixed[i] ;
1019
1020   *optr++ = 'e' ;
1021
1022   if (exp < 0)
1023     {
1024       exp = -exp ;
1025       *optr++ = '-' ;
1026     }
1027   else *optr++ = '+' ;
1028
1029   MPstr_to_num("0.5", DEC, MP1) ;
1030   mpaddi(MP1, &exp, MPval) ;
1031   n = 1 ;
1032   mpcim(&n, MP1) ;
1033   for (ddig = 0; mpge(MPval, MP1); ddig++)
1034     mpdiv(MPval, MP1base, MPval) ;
1035
1036   if (ddig == 0) *optr++ = '0' ;
1037
1038   while (ddig-- > 0)
1039     {
1040       mpmul(MPval, MP1base, MPval) ;
1041       mpcmi(MPval, &dval) ;
1042       *optr++ = digits[dval] ;
1043       dval = -dval ;
1044       mpaddi(MPval, &dval, MPval) ;
1045     }
1046   *optr++    = '\0' ;
1047   v->toclear = 1 ;
1048   v->pointed = 0 ;
1049   return(v->snum) ;
1050 }
1051
1052 /* Convert MP number to fixed number string. */
1053 /* cmax    Maximum characters to generate. */
1054 char *
1055 make_fixed(int *MPnumber, int cmax)
1056 {
1057   char *optr ;
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 . */
1061   int dval, n ;
1062  
1063   optr = v->fnum ;
1064   mpabs(MPnumber, MPval) ;
1065   n = 0 ;
1066   mpcim(&n, MP1) ;
1067   if (mplt(MPnumber, MP1)) *optr++ = '-' ;
1068  
1069   mpcim(&basevals[(int) v->base], MP1base) ;
1070  
1071   mppwr(MP1base, &v->accuracy, MP1) ;
1072   MPstr_to_num("0.5", DEC, MP2) ;
1073   mpdiv(MP2, MP1, MP1) ;
1074   mpadd(MPval, MP1, MPval) ;
1075  
1076   n = 1 ;
1077   mpcim(&n, MP2) ;
1078   if (mplt(MPval, MP2))
1079     {
1080       ddig = 0 ;
1081       *optr++ = '0' ;
1082       cmax-- ;
1083     }
1084   else
1085     for (ddig = 0; mpge(MPval, MP2); ddig++)
1086       mpdiv(MPval, MP1base, MPval) ;
1087
1088   ndig = MIN(ddig + v->accuracy, --cmax) ;
1089
1090   while (ndig-- > 0)
1091     {
1092       if (ddig-- == 0) *optr++ = '.' ;
1093       mpmul(MPval, MP1base, MPval) ;
1094       mpcmi(MPval, &dval) ;
1095       *optr++ = digits[dval] ;
1096       dval = -dval ;
1097       mpaddi(MPval, &dval, MPval) ;
1098     }
1099   *optr++    = '\0' ;
1100   v->toclear = 1 ;
1101   v->pointed = 0 ;
1102   return(v->fnum) ;
1103 }
1104
1105
1106 void
1107 make_items(void)
1108 {
1109   set_item(DISPLAYITEM, v->display) ;
1110   set_item(OPITEM,      "    ") ;
1111   set_item(HYPITEM,     "    ") ;
1112   set_item(INVITEM,     "    ") ;
1113 }
1114
1115 /* Convert MP number to character string. */
1116 char *
1117 make_number(int *MPnumber, BOOLEAN mkFix)
1118 {
1119   double number, val ;
1120
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.
1124  *
1125  *  XXX:  Needs to be improved. Shouldn't need to convert to a double in
1126  *        order to do these tests.
1127  */  
1128      
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)
1136   {
1137      if(v->accuracy == 0)
1138      {
1139         if(val <= min_fix0[(int) v->base])
1140            return(make_eng_sci(MPnumber)) ;
1141         else
1142            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1143      }
1144      else if(v->accuracy == 1)
1145      {
1146         if(val <= min_fix1[(int) v->base])
1147            return(make_eng_sci(MPnumber)) ;
1148         else
1149            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1150      }
1151      else if(v->accuracy == 2)
1152      {
1153         if(val <= min_fix2[(int) v->base])
1154            return(make_eng_sci(MPnumber)) ;
1155         else
1156            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1157      }
1158      else if(v->accuracy == 3)
1159      {
1160         if(val <= min_fix3[(int) v->base])
1161            return(make_eng_sci(MPnumber)) ;
1162         else
1163            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1164      }
1165      else if(v->accuracy == 4)
1166      {
1167         if(val <= min_fix4[(int) v->base])
1168            return(make_eng_sci(MPnumber)) ;
1169         else
1170            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1171      }
1172      else if(v->accuracy == 5)
1173      {
1174         if(val <= min_fix5[(int) v->base])
1175            return(make_eng_sci(MPnumber)) ;
1176         else
1177            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1178      }
1179      else if(v->accuracy == 6)
1180      {
1181         if(val <= min_fix6[(int) v->base])
1182            return(make_eng_sci(MPnumber)) ;
1183         else
1184            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1185      }
1186      else if(v->accuracy == 7)
1187      {
1188         if(val <= min_fix7[(int) v->base])
1189            return(make_eng_sci(MPnumber)) ;
1190         else
1191            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1192      }
1193      else if(v->accuracy == 8)
1194      {
1195         if(val <= min_fix8[(int) v->base])
1196            return(make_eng_sci(MPnumber)) ;
1197         else
1198            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1199      }
1200      else if(v->accuracy == 9)
1201      {
1202         if(val <= min_fix9[(int) v->base])
1203            return(make_eng_sci(MPnumber)) ;
1204         else
1205            return(make_fixed(MPnumber, MAX_DIGITS)) ;
1206      }
1207      else 
1208      {
1209         return(make_fixed(MPnumber, MAX_DIGITS)) ;
1210      }
1211   }
1212   else 
1213      return(make_fixed(MPnumber, MAX_DIGITS)) ;
1214 }
1215
1216
1217 /*ARGSUSED*/
1218 /* Default math library exception handling routine. */
1219 int
1220 matherr(struct exception *exc)
1221 {
1222 #if 0
1223   char msg[100];
1224   
1225   if (exc) {
1226           strcpy(msg, exc->name);
1227           strcat(msg, ": ");
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 ");
1240           
1241           strcat(msg, vstrs[(int) V_ERROR]);
1242
1243           _DtSimpleError (v->appname, DtWarning, NULL, msg);
1244   }
1245 #endif
1246
1247   doerr(vstrs[(int) V_ERROR]) ;
1248   return(1) ;                     /* Value ignored. */
1249 }
1250
1251 /* Convert string into an MP number. */
1252 void
1253 MPstr_to_num(char *str, enum base_type base, int *MPval)
1254 {
1255   char   *optr ;
1256   int MP1[MP_SIZE], MP2[MP_SIZE], MPbase[MP_SIZE] ;
1257   int    i, inum ;
1258   int    neg      = 0 ;
1259   int    exp      = 0 ;
1260   int    exp_sign = 1 ;
1261
1262   i = 0 ;
1263   mpcim(&i, MPval) ;
1264   mpcim(&basevals[(int) base], MPbase) ;
1265   optr = str ;
1266   while (*optr == ' ') optr++ ;
1267   if(*optr == '-')
1268   {
1269      /* negative number */
1270      optr++ ;
1271      neg = 1;
1272   }
1273   while ((inum = char_val(*optr)) >= 0)
1274     {
1275       mpmul(MPval, MPbase, MPval) ;
1276       mpaddi(MPval, &inum, MPval) ;
1277       optr++ ;
1278     }
1279
1280   if (*optr == '.')
1281     for (i = 1; (inum = char_val(*++optr)) >= 0; i++)
1282       {  
1283         mppwr(MPbase, &i, MP1) ;
1284         mpcim(&inum, MP2) ;
1285         mpdiv(MP2, MP1, MP1) ;
1286         mpadd(MPval, MP1, MPval) ;
1287       }
1288  
1289   while (*optr == ' ') optr++ ;
1290
1291   if (*optr != '\0')
1292     {
1293       if (*optr == '-') exp_sign = -1 ;
1294
1295       while ((inum = char_val(*++optr)) >= 0)
1296         exp = exp * basevals[(int) base] + inum ;
1297     }
1298   exp *= exp_sign ;
1299
1300   if (v->key_exp || exp_sign == -1) 
1301     {
1302       mppwr(MPbase, &exp, MP1) ;
1303       mpmul(MPval, MP1, MPval) ;
1304     }
1305   if( neg == 1)
1306   {
1307       i = -1 ;
1308       mpcim(&i, MP1) ;
1309       mpmul(MPval, MP1, MPval) ;
1310   }
1311 }
1312
1313 /* Append the latest parenthesis char to the display item. */
1314 void
1315 paren_disp(char c)
1316 {
1317   int i, n ;
1318
1319 /*  If the character is a Delete, clear the whole line, and exit parenthesis
1320  *  processing.
1321  *
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.
1325  *
1326  *  If the character is a control character (not Ctrl-h), then append ^(char).
1327  *
1328  *  Otherwise just append the character.
1329  */
1330  
1331   n = strlen(v->display) ;
1332   if (IS_KEY(c, KEY_CLR))             /* Is it a Delete character? */
1333     {
1334       v->noparens = v->pending = v->opsptr = v->numsptr = 0 ;
1335       v->cur_op = '?' ;
1336       set_item(OPITEM, "") ;
1337       i = 0 ;
1338       mpcim(&i, v->MPdisp_val) ;
1339       show_display(v->MPdisp_val) ;
1340       set_base(v->base);
1341       set_numtype(v->dtype);
1342       set_option_menu((int) TTYPEITEM, (int)v->ttype);
1343       make_modewin() ;
1344       v->curwin = FCP_KEY ;
1345       v->defState = 1;
1346       return ;
1347     }
1348   else if (IS_KEY(c, KEY_BSP))        /* Is is a Back Space character? */
1349     {
1350       if (!n) return ;
1351       if (v->display[n-1] == '(')
1352         {
1353           v->noparens-- ;
1354           if (!v->noparens)
1355             {
1356               v->pending = v->opsptr = v->numsptr = 0 ;
1357               v->cur_op = '?' ;
1358               set_item(OPITEM, "") ;
1359               show_display(v->MPdisp_val) ;
1360               return ;
1361             }
1362         }
1363       v->display[n-1] = '\0' ;
1364     }
1365   else if (c <= CTL('z'))             /* Is it a control character? */
1366     {
1367       if (n < MAXLINE-2)
1368         {
1369           v->display[n]   = '^' ;
1370           v->display[n+1] = c + 96 ;
1371           v->display[n+2] = '\0' ;
1372         }
1373     }    
1374   else                                /* It must be an ordinary character. */
1375     {
1376       if (n < MAXLINE-1)
1377         {
1378           v->display[n]   = c ;
1379           v->display[n+1] = '\0' ;
1380         }
1381     }    
1382
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]) ;
1386   v->show_paren = 0 ;
1387 }
1388
1389 /* Process this event. */
1390 void
1391 process_event(int type)
1392 {
1393   int ival ;
1394
1395   switch (type)
1396     {
1397       case KEYBOARD_DOWN   : if (v->pending)
1398                                {
1399                                  v->current = v->cur_ch ;
1400                                  do_pending() ;
1401                                }
1402                              else
1403                                { 
1404                                  ival = get_index(v->cur_ch) ;
1405                                  if (ival < TITEMS - EXTRA) {
1406                                     if ((v->modetype == FINANCIAL && 
1407                                                                  ival == 23) ||
1408                                         (v->modetype == LOGICAL && (
1409                                                     ival == 21 || ival == 22 || 
1410                                                                  ival == 23)))
1411                                        break;
1412                                     else
1413                                        /* go arm the button */
1414                                        draw_button(ival, v->curwin, v->row, 
1415                                                    v->column, TRUE) ;
1416                                  }
1417                                  process_item(ival) ;
1418                                }
1419                              break ;
1420
1421       case KEYBOARD_UP     : ival = get_index(v->cur_ch) ;
1422                              if (ival < TITEMS - EXTRA) {
1423                                  if ((v->modetype == FINANCIAL && 
1424                                                               ival == 23) ||
1425                                      (v->modetype == LOGICAL && (
1426                                                  ival == 21 || ival == 22 ||
1427                                                               ival == 23)))
1428                                     break;
1429                                  else
1430                                     /* go disarm the button */
1431                                     draw_button(ival, v->curwin, v->row, 
1432                                                 v->column, FALSE) ;
1433                              }
1434                              /* go disarm the button */
1435                              draw_button(ival, v->curwin, v->row, 
1436                                                 v->column, FALSE) ;
1437                              break ;
1438  
1439     }
1440 }
1441
1442
1443 void
1444 process_item(int n)
1445 {
1446   int i,isvalid ;
1447
1448   if (n < 0 || n >= TITEMS)
1449     {
1450       beep() ;
1451       v->error = TRUE;
1452     }
1453
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' ;
1458
1459   if (v->error)
1460     {
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 ;
1466       v->error = 0 ;
1467     }
1468
1469   if (v->pending)
1470     {
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)() ;
1474       return ;
1475     }
1476   switch (buttons[n].opdisp)
1477     {
1478       case OP_SET   : 
1479          if (v->current == 'T') 
1480          {
1481              if (v->modetype == SCIENTIFIC)
1482                 set_item(OPITEM, buttons[n].str) ;
1483              else
1484                 v->pending = 0;
1485          }
1486          else
1487             set_item(OPITEM, buttons[n].str) ;
1488          break ;
1489       case OP_CLEAR : 
1490          if (v->error) 
1491             set_item(OPITEM, vstrs[(int) V_CLR]) ;
1492          else 
1493             set_item(OPITEM, "") ;
1494          break;
1495       default:
1496          break;
1497     }
1498   (*buttons[n].func)() ;
1499
1500   if(strcmp(buttons[n].resname, "clr") != 0)
1501       v->defState = 0;
1502 }
1503
1504
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.
1509 */
1510
1511 void
1512 process_stack(int startop, int startnum, int n)
1513 {
1514   char sdisp[MAXLINE] ;     /* Used to save display contents. */
1515   int i ;
1516   int nptr ;                /* Pointer to next number from numeric stack. */
1517
1518   STRCPY(sdisp, v->display) ;  /* Save current display. */
1519   nptr = startnum ;
1520   v->pending = 0 ;
1521   v->cur_op = '?' ;            /* Current operation is initially undefined. */
1522   for (i = 0; i < n; i++)
1523     {
1524       if (v->opstack[startop + i] == -1)
1525         {
1526           mpstr(v->MPnumstack[nptr++], v->MPdisp_val) ;
1527         }
1528       else
1529         { 
1530           v->cur_ch = v->opstack[startop + i] ;
1531           if (v->cur_ch == '^')                    /* Control character? */
1532             {
1533               i++ ;
1534               v->cur_ch = CTL(v->opstack[startop + i]) ;
1535             }
1536           if (v->pending)
1537             {
1538               v->current = v->cur_ch ;
1539               do_pending() ;
1540             }
1541           else process_item(get_index(v->cur_ch)) ;
1542         }
1543     }    
1544   v->numsptr = startnum ;
1545   push_num(v->MPdisp_val) ;
1546   v->opsptr = startop - 1 ;
1547   push_op(-1) ;
1548   save_pending_values(KEY_LPAR) ;
1549   STRCPY(v->display, sdisp) ;  /* Restore current display. */
1550 }
1551
1552
1553 void
1554 process_str(char *str, enum menu_type mtype)
1555 {
1556   int i, len ;
1557   char save[80];
1558
1559   len = strlen(str) ;
1560   STRCPY(save, v->display) ;
1561   STRCPY(v->display, " ") ;
1562   set_item(DISPLAYITEM, v->display);
1563   for (i = 0 ; i < len; i++)
1564     {    
1565       if(str[i] == '*')
1566          str[i] = 'x';
1567       if (v->error) 
1568       {
1569         if(mtype == M_FUN)
1570         {
1571            STRCPY(v->display, save);
1572            set_item(DISPLAYITEM, v->display);
1573            v->error = 0;
1574         }
1575         return ;
1576       }
1577       if (v->pending)
1578         {
1579           v->current = str[i] ;
1580           do_pending() ;
1581         }
1582       else 
1583         switch(v->base)
1584         {
1585            case DEC:
1586               if(str[i] == 'a' ||
1587                  str[i] == 'b' ||
1588                  str[i] == 'c' ||
1589                  str[i] == 'd' ||
1590                  str[i] == 'e' ||
1591                  str[i] == 'f')
1592               {
1593                  v->error = True;
1594                  beep();
1595                  break;
1596               }
1597            default:
1598               process_item(get_index(str[i])) ;
1599         }
1600     }
1601 }
1602
1603
1604 void
1605 read_rcfiles(void)   /* Read .dtcalcrc's from home and current directories. */
1606 {
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. */
1611   int n ;
1612   struct passwd *entry ;
1613
1614   for (n = 0; n < MAXREGS; n++)
1615     {
1616       STRCPY(tmp, make_number(v->MPcon_vals[n], FALSE)) ;
1617       SPRINTF(name, "%1d: %s [%s]", n, tmp, v->con_names[n]) ;
1618
1619       STRCPY(v->con_names[n], name) ;
1620       STRCPY(v->fun_vals[n], "") ;    /* Initially empty function strings. */
1621     }
1622
1623   if ((home = getenv("HOME")) == NULL)
1624     {
1625       if ((entry = getpwuid(getuid())) == NULL) return ;
1626       home = entry->pw_dir ;
1627     }
1628   snprintf(name, MAXPATHLEN, "%s/%s", home, RCNAME) ;
1629   get_rcfile(name) ;      /* Read .dtcalcrc from users home directory. */
1630  
1631   snprintf(name, MAXPATHLEN, "%s/%s", getcwd(pathname, MAXPATHLEN+1), RCNAME) ;
1632   get_rcfile(name) ;      /* Read .dtcalcrc file from current directory. */
1633 }
1634
1635
1636 void
1637 show_display(int *MPval)
1638 {
1639   if (!v->error)
1640     {
1641       STRCPY(v->display, make_number(MPval, TRUE)) ;
1642       set_item(DISPLAYITEM, v->display) ;
1643     }
1644 }
1645
1646
1647 void
1648 usage(char *progname)
1649 {
1650   FPRINTF(stderr, ustrs[(int) USAGE1], PATCHLEVEL) ;
1651   FPRINTF(stderr, "%s", ustrs[(int) USAGE2]) ;
1652   FPRINTF(stderr, "%s", ustrs[(int) USAGE3]) ;
1653   exit(1) ;
1654 }
1655
1656 void
1657 write_rcfile(enum menu_type mtype, int exists, int cfno, char *val, char *comment)
1658 {
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. */
1669
1670   rcexists = 0 ;
1671   SPRINTF(rcname, "%s/%s", getcwd(pathname, MAXPATHLEN), RCNAME) ;
1672   if (access(rcname, F_OK) == 0) rcexists = 1 ;
1673   else
1674     { 
1675       if ((home = getenv("HOME")) == NULL)
1676         {
1677           if ((entry = getpwuid(getuid())) == NULL) return ;
1678           home = entry->pw_dir ;
1679         }
1680       SPRINTF(rcname, "%s/%s", home, RCNAME) ;
1681       if (access(rcname, F_OK) == 0) rcexists = 1 ;
1682     }
1683   STRCPY(tmp_filename, "/tmp/.dtcalcrcXXXXXX") ;
1684   MKTEMP(tmp_filename) ;
1685   if ((tmpfd = fopen(tmp_filename, "w+")) == NULL) return ;
1686
1687   if (rcexists)
1688     {
1689       rcfd = fopen(rcname, "r") ;
1690       SPRINTF(sval, " %1d", cfno) ;
1691       while (fgets(str, MAXLINE, rcfd))
1692         {
1693           if (exists)
1694             {
1695               switch (mtype)
1696                 {
1697                   case M_CON : sval[0] = 'c' ;
1698                                if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1699                                sval[0] = 'C' ;
1700                                if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1701                                break ;
1702                   case M_FUN : sval[0] = 'f' ;
1703                                if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1704                                sval[0] = 'F' ;
1705                                if (!strncmp(str, sval, 2)) FPUTS("#", tmpfd) ;
1706                                break;
1707                   default: break;
1708                 }
1709             }    
1710           FPRINTF(tmpfd, "%s", str) ;
1711         }
1712       FCLOSE(rcfd) ;
1713     }
1714
1715   switch (mtype)
1716     {
1717       case M_CON : FPRINTF(tmpfd, "\nC%1d %s %s\n", cfno, val, comment) ;
1718                    break ;
1719       case M_FUN : 
1720                if(strcmp(val, "") != 0)
1721                   FPRINTF(tmpfd, "\nF%1d %s %s\n", cfno, val, comment) ;
1722                break;
1723       default: break;
1724     }
1725   UNLINK(rcname) ;
1726   rcfd = fopen(rcname, "w") ;
1727   REWIND(tmpfd) ;
1728   while (fgets(str, MAXLINE, tmpfd)) FPRINTF(rcfd, "%s", str) ;
1729   FCLOSE(rcfd) ;
1730   FCLOSE(tmpfd);
1731   UNLINK(tmp_filename) ;
1732 }
1733
1734
1735 void
1736 write_resources(char *filename)
1737 {
1738   char intval[5] ;
1739   int MPtemp[MP_SIZE];
1740
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)) ;
1749
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)) ;
1760
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)) ;
1773
1774   save_resources(filename) ;
1775 }