home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / maths / progs / hpcalc / !HPCalc / C / Calc
Encoding:
Text File  |  1992-05-07  |  56.4 KB  |  1,986 lines

  1. /* >$.!User.!HpCalc.c.calc
  2.  *
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <stdarg.h>
  9. #include <math.h>
  10. #include <limits.h>
  11. #include <float.h>
  12. #include <ctype.h>
  13.  
  14. #include "swis.h"
  15. #include "os.h"
  16. #include "flex.h"
  17. #include "wimpt.h"
  18. #include "wimp.h"
  19. #include "sprite.h"
  20. #include "font.h"
  21. #include "win.h"
  22. #include "event.h"
  23. #include "baricon.h"
  24. #include "res.h"
  25. #include "resspr.h"
  26. #include "menu.h"
  27. #include "template.h"
  28. #include "dbox.h"
  29. #include "werr.h"
  30.  
  31. /********************************* CONSTANTS *******************************/
  32.  
  33. #define calc_menu_info        1
  34. #define calc_menu_quit        2
  35. #define calc_menu_single      2
  36. #define calc_menu_double      3
  37. #define calc_menu_exit        4
  38. #define calc_info_field       4
  39. #define Menu_MAXITEMS 24
  40.  
  41. /******************************** GLOBAL DATA ******************************/
  42.  
  43. static char     *calc_Version_String  = "1.00";
  44. static menu      calc_bar_menu;
  45. static menu      calc_win_menu;
  46. static char     *calc_win_text        = ">Info,Single,Double,Exit";
  47.  
  48. static wimp_i xicon;
  49. static wimp_i dicon    [2];
  50. static wimp_i yicon;
  51. static wimp_i ricon;
  52. static wimp_i gicon;
  53. static wimp_i hpicon;
  54. static wimp_i icon     [3] [40];
  55. static wimp_w calc;
  56. static wimp_w keyboard [3];
  57. static wimp_w header;
  58. static wimp_w display_x;
  59. static wimp_w display_y;
  60. static font   tfont;
  61. static int sflag [10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  62. static sprite_area *sprite [3];
  63. static int backdrop       = 0;
  64. static int harddisk       = 0;
  65. static int calc_active    = 0;
  66. static int initialised    = 0;
  67. static int trig_mode      = 0;
  68. static int scientific     = 0;
  69. static int engineering    = 0;
  70. static int hex            = 0;
  71. static int precision      = 2;
  72. static int board          = 0;
  73. static int which_register = 0;
  74. static int prefix         = 0;
  75. static int clear_imag     = 0;
  76. static int entered        = 1;
  77. static int stack_lift     = 1;
  78. static int single         = 0;
  79. static int eex            = 0;
  80. static int seed;
  81. /*static double euler       = 0.5772156649901532860606512; */
  82. static char  lbuf     [400];
  83. static char  display  [2] [25];
  84. static char  operation    = '0';
  85. static char  title    []  = "!HpCalc";
  86. static char  Re_var   []  = "HpCalc$Re";
  87. static char  Im_var   []  = "HpCalc$Im";
  88.  
  89. static char *icons [] = {
  90.    "on", "ff", "fg", "sto", "rcl", "enter", "0", "dot", "s+", "plus",
  91.    "bl", "bl", "rd", "x<>y", "bsp", "5", "1", "2", "3", "minus",
  92.    "bl", "bl", "sin", "cos", "tan", "eex", "4", "5", "6", "times",
  93.    "!x", "ex", "10x", "yx", "1/x", "chs", "7", "8", "9", "divide",
  94.  
  95.    "f", "ff", "fg", "frac", "bl", "ran#", "x!", "le", "lr", "py,x",
  96.    "bl", "sum", "bl", "reg", "prefix", "bl", "tor", "tohms", "torad",
  97.    "re<>im",
  98.    "bl", "hyp", "bl", "(i)", "i", "bl", "x<>", "bl", "bl", "bl",
  99.    "a", "b", "c", "d", "e", "bl", "fix", "sci", "eng", "bl",
  100.  
  101.    "hex", "ff", "fg", "int", "bl", "lstx", "mean", "sd", "s-", "cy,x",
  102.    "bl", "bl", "ru", "rnd", "clx", "bl", "top", "toh", "todeg", "bl",
  103.    "bl", "ahyp", "asin", "acos", "atan", "pi", "sf", "cf", "bl", "bl",
  104.    "x2", "ln", "log", "%", "d%", "abs", "deg", "rad", "grd", "bl"
  105. };
  106.  
  107. static char *error_message [] = {
  108.   "Square root of negative number",
  109.   "Divide by zero",
  110.   "arc sine, cosine or (hyperbolic) arc tangent out of range",
  111.   "Logarithm of negative number",
  112.   "Improper Register Number",
  113.   "Arithmetic Overflow in ",
  114.   "Arithmetic Underflow in "
  115. };
  116.  
  117. static double gamma_fn_coefficient [] = {
  118.   1.0000000000000000,  0.5772156649015329, -0.6558780715202538,
  119.  -0.0420026350340952,  0.1665386113822915, -0.0421977345555443,
  120.  -0.0096219715278770,  0.0072189432466630, -0.0011651675918591,
  121.  -0.0002152416741149,  0.0001280502823882, -0.0000201348547807,
  122.  -0.0000012504934821,  0.0000011330272320, -0.0000002056338417,
  123.   0.0000000061160950,  0.0000000050020075, -0.0000000011812746,
  124.   0.0000000001043427,  0.0000000000077823, -0.0000000000036968,
  125.   0.0000000000005100, -0.0000000000000206, -0.0000000000000054,
  126.   0.0000000000000014, -0.000000000000000184
  127. };
  128.  
  129. /*
  130.  * Definition of working register stack;
  131.  */
  132.  
  133. static struct stack_register {
  134.   double value   [2];
  135.   char   string  [25];
  136. } stack_registers [4];
  137.  
  138. static double last_x = 0.0;
  139. static double store [68];
  140. static struct stack_register *x, *y, *z, *t;
  141.  
  142. static FILE *fin, *fout;
  143.   
  144. static void cant (char *s)
  145. {
  146.   os_error e;
  147.  
  148.   strcpy (e.errmess,"? Warning: File - ");
  149.   strcat (e.errmess,s);
  150.   e.errnum = 1;
  151.   wimpt_reporterror (&e,wimp_EOK);
  152. }
  153.  
  154. static void calc_error (char *s)
  155. {
  156.   os_error e;
  157.  
  158.   strcpy (e.errmess,s);
  159.   e.errnum = 1;
  160.   wimpt_reporterror (&e,wimp_EOK);
  161. }
  162.  
  163. static void setvar (char *s, char *p)
  164. {
  165.   os_regset r;
  166.   r.r [0] = (int) s;
  167.   r.r [1] = (int) p;
  168.   r.r [2] = (strlen (p) > 0) ? strlen (p) : -1;
  169.   r.r [3] = 0;
  170.   r.r [4] = 0;
  171.   os_swix (OS_SetVarVal,&r);
  172. }
  173.  
  174. static int texticon (window,x0,y0,x1,y1,flags,name,length)
  175. int  x0,y0,x1,y1,flags,window,length;
  176. char *name;
  177. {
  178.   wimp_icreate i;
  179.   wimp_i       handle;
  180.  
  181.   i.w        = window;
  182.   i.i.box.x0 = x0;
  183.   i.i.box.y0 = y0;
  184.   i.i.box.x1 = x1;
  185.   i.i.box.y1 = y1;
  186.   i.i.flags  = flags;
  187.   i.i.data.indirecttext.buffer      = name;
  188.   i.i.data.indirecttext.validstring = (char *) -1;
  189.   i.i.data.indirecttext.bufflen     = length;
  190.   wimpt_noerr (wimp_create_icon (&i, &handle));
  191.   return (handle);
  192. }
  193.  
  194. static int spriteicon (wimp_w window, int x0, int y0, int x1, int y1,
  195.                        wimp_iconflags flags, void *sptr, char *name)
  196. {
  197.   wimp_icreate i;
  198.   wimp_i       handle;
  199.  
  200.   i.w        = window;
  201.   i.i.box.x0 = x0;
  202.   i.i.box.y0 = y0;
  203.   i.i.box.x1 = x1;
  204.   i.i.box.y1 = y1;
  205.   i.i.flags  = flags;
  206.   i.i.data.indirectsprite.name       = name;
  207.   i.i.data.indirectsprite.spritearea = sptr;
  208.   i.i.data.indirectsprite.nameisname = strlen (name);
  209.   wimpt_noerr (wimp_create_icon (&i, &handle));
  210.   return (handle);
  211. }
  212.  
  213. static void change_complex (int i)
  214. {
  215.   wimp_wstate o;
  216.  
  217.   if (single) {
  218.     wimpt_noerr (wimp_delete_icon (header, xicon));
  219.     wimpt_noerr (wimp_delete_icon (header, yicon));
  220.   } else {
  221.     if (sflag [8]) wimpt_noerr (wimp_delete_icon (header, yicon));
  222.   }
  223.   sflag [8] = i;
  224.   if (sflag [8]) {
  225.     if (!single) {
  226.       yicon = texticon (header, 5,- 84,40,-16,0x04003109,"Re",2);
  227.     } else {
  228.       xicon = texticon (header, 5,- 84,40,-16,0x04003109,"Im",2);
  229.       yicon = texticon (header, 5,-174,40,-90,0x04003109,"Re",2);
  230.     }
  231.   } else {
  232.     if (single) {
  233.       xicon = texticon (header,20,- 84,40,-16,0x04003109,"Y",1);
  234.       yicon = texticon (header,20,-174,40,-90,0x04003109,"X",1);
  235.     }
  236.   }
  237.   wimpt_noerr (wimp_get_wind_state (header,&o));
  238.   wimpt_noerr (wimp_close_wind     (header));
  239.   wimpt_noerr (wimp_open_wind      (&o.o));
  240. }
  241.  
  242. static void change_trig (int i)
  243. {
  244.   wimp_iconflags value,mask;
  245.   wimp_wstate    o;
  246.  
  247.   trig_mode = i;
  248.   value = 0x00000000;
  249.   mask  = 0x0f000000;
  250.   wimpt_noerr (wimp_set_icon_state (header, gicon, value, mask));
  251.   wimpt_noerr (wimp_set_icon_state (header, ricon, value, mask));
  252.   switch (i) {
  253.     case 1 : /* Radians */
  254.       value = 0x04000000;
  255.       mask  = 0x00000000;
  256.       wimpt_noerr (wimp_set_icon_state (header,ricon,value,mask));
  257.     break;
  258.     case 2 : /* Grads   */
  259.       value = 0x04000000;
  260.       mask  = 0x00000000;
  261.       wimpt_noerr (wimp_set_icon_state (header,gicon,value,mask));
  262.     break;
  263.     default : break;
  264.   }  
  265.   wimpt_noerr (wimp_get_wind_state (header,&o));
  266.   wimpt_noerr (wimp_close_wind     (header));
  267.   wimpt_noerr (wimp_open_wind      (&o.o));
  268.   prefix = 0;
  269. }
  270.  
  271. static void value_to_string (char *p,double value)
  272. {
  273.   char format [20], *s;
  274.   int  j;
  275.  
  276. /*** Sort out display format ***/
  277.   if (scientific || engineering)
  278.     sprintf (format,"%s.%de","%s%",precision);
  279.   else if (hex)
  280.     sprintf (format,"%s.%dx","%s%",precision);
  281.   else {
  282.     if (value == 0 || abs ((int) floor(log10(fabs(value)))) + precision < 15)
  283.       sprintf (format,"%s.%df","%s%",precision);
  284.     else
  285.       sprintf (format,"%s.%de","%s%",precision);
  286.   }
  287. /*** Translate current value ***/
  288.   if (!hex) {
  289.     if (value >= 0) 
  290.       sprintf (p,format," ", value);
  291.     else
  292.       sprintf (p,format,"-",-value);
  293.   } else {
  294.     sprintf (p,format," ",(long) fabs (floor (value)));
  295.     for (s = p; *s; s++) *s = toupper (*s);
  296.   }
  297. /*** Shift exponential ***/
  298.   if (!hex && (s = strchr (p,'e')) != NULL) {
  299.     strcpy (format,s);
  300.     if (format[1] == '+') format[1] = ' ';
  301.     for (j = (int) (s - p); j < 16; j++) p[j] = ' ';
  302.     p[j] = 0;
  303.     strcat (p,&format[1]);
  304.   }
  305. }
  306.  
  307. static void select_keyboard (int b)
  308. {
  309.   int         old_board;
  310.   wimp_wstate o;
  311.  
  312.   wimpt_noerr (wimp_get_wind_state (keyboard[board],&o));
  313.   old_board = board;
  314.   board     = b;
  315.   o.o.w     = keyboard [board];
  316.   wimpt_noerr (wimp_open_wind (&o.o));
  317.   wimpt_noerr (wimp_close_wind (keyboard [old_board]));
  318. }
  319.  
  320. static double check (double x, char *s)
  321. {
  322.   double temp;
  323.  
  324.   if (x != 0) {
  325.     int fault = 0;
  326.     if ((temp = log10(fabs(x))) >= DBL_MAX_10_EXP) {
  327.       strcpy (lbuf,error_message [5]);
  328.       fault++;
  329.     } else if (temp <= DBL_MIN_10_EXP) {
  330.       strcpy (lbuf,error_message [6]);
  331.       fault++;
  332.     }
  333.     if (fault) {
  334.       strcat (lbuf,s);
  335.       strcat (lbuf,", value set to 0");
  336.       calc_error (lbuf);
  337.       return (0);
  338.     }
  339.   }
  340.   return (x);
  341. }
  342.  
  343. static void refresh_display ()
  344. {
  345.   wimp_wstate o;
  346.  
  347.   if (single) {
  348.     if (!sflag [8]) {
  349.       y->value [0] = check (y->value [0],"Y");
  350.       value_to_string (display [1],y->value [0]);
  351.     } else {
  352.       x->value [1] = check (x->value [1],"Imaginary X");
  353.       value_to_string (display [1],x->value [1]);
  354.     }
  355.     wimpt_noerr (wimp_get_wind_state (display_y,&o));
  356.     wimpt_noerr (wimp_close_wind     (display_y));
  357.     wimpt_noerr (wimp_open_wind      (&o.o));
  358.   }
  359.   if (entered) {
  360.     if (!sflag [8])
  361.       x->value [0] = check (x->value [0],"X");
  362.     else
  363.       x->value [0] = check (x->value [0],"Real X");
  364.     value_to_string (x->string,x->value [0]);
  365.   }
  366.   strcpy (display [0],x->string);
  367.   wimpt_noerr (wimp_get_wind_state (display_x,&o));
  368.   wimpt_noerr (wimp_close_wind     (display_x));
  369.   wimpt_noerr (wimp_open_wind      (&o.o));
  370. /*
  371.  * Save real x value as system variable
  372.  */
  373.   sprintf (lbuf,"%.15g",x->value [0]);
  374.   setvar (Re_var,lbuf);
  375. /*
  376.  * Save imaginary x value as system variable if in complex mode,
  377.  * otherwise delete the variable
  378.  */
  379.   if (sflag[8]) {
  380.     sprintf (lbuf,"%.15g",x->value [1]);
  381.     setvar (Im_var,lbuf);
  382.   } else setvar (Im_var,"");
  383. }
  384.  
  385. static void lift_stack ()
  386. {
  387.   struct stack_register *ts;
  388.  
  389.   if (stack_lift) {
  390.     ts = t;
  391.     t  = z;
  392.     z  = y;
  393.     y  = x;
  394.     x  = ts;
  395.     x->value [0] = y->value [0];
  396.     x->value [1] = 0;
  397.   }
  398.   stack_lift = 1;
  399. }
  400.  
  401. static void drop_stack ()
  402. {
  403.   struct stack_register *ts;
  404.  
  405.   ts = x;
  406.   x  = y;
  407.   y  = z;
  408.   z  = t;
  409.   t  = ts;
  410.   t->value [0] = z->value [0];
  411.   t->value [1] = z->value [1];
  412. }
  413.  
  414. static void add_to_x_string (char *key)
  415. {            
  416.   if (entered) {
  417.     lift_stack ();
  418.     strcpy (x->string," ");
  419.     entered = 0;
  420.   }
  421.   if (clear_imag) {
  422.     x->value [1] = (double) 0;
  423.     clear_imag  = 0;
  424.   }
  425.   if (*key == '.') {
  426.     if (!hex && !eex) {
  427.       if (strlen (x->string) == 1)
  428.         strcat (x->string,"0.");
  429.       else if (!strchr (x->string,'.'))
  430.         strcat (x->string,".");
  431.     }
  432.   } else {
  433.     if (hex) *key = toupper (*key);
  434.     if (eex) {
  435.       x->string [17] = x->string [18];
  436.       x->string [18] = *key;
  437.     } else strncat (x->string,key,1);
  438.   }
  439.   refresh_display ();
  440. }  
  441.  
  442. static double string_to_value (char *s)
  443. {
  444.   char *p,*t;
  445.  
  446.   if (!entered) {
  447.     entered    = 1;
  448.     clear_imag = 0;
  449.     if (hex)
  450.       return ((double) strtol (s, (char**) NULL,16));
  451.     else {
  452.       if (eex && (p = strchr (&s[1],' ')) != NULL) {
  453.         *p++ = 'e';
  454.         if ((t = strrchr (p,' ')) != NULL) strcpy (p,&t[1]);
  455.         eex = 0;
  456.       }
  457.       return (strtod (s, (char**) NULL));
  458.     }
  459.   } else return (x->value [0]);
  460. }
  461.  
  462. static void enter_x_string (char *s)
  463. {
  464.   double temp;
  465.  
  466.   x->value [0] = string_to_value (s);
  467.   last_x       = x->value [0];
  468.   temp         = x->value [1];
  469.   stack_lift   = 1;
  470.   clear_imag   = 1;
  471.   lift_stack ();
  472.   stack_lift   = 0;
  473.   x->value [1] = temp;
  474.   refresh_display ();
  475. }
  476.  
  477. static void clear (int i)
  478. {
  479.   int j;
  480.   char *p;
  481.  
  482.   switch (i) {
  483.  
  484.     case 0 : /* back space */
  485.       if (entered) {
  486.         x->value  [0] = (double) 0;
  487.         eex           = 0;
  488.         x->string [0] = 0;
  489.         stack_lift    = 0;
  490.       } else {
  491.         if (!eex) {
  492.           if (strlen (x->string) > 2) {
  493.             x->string [strlen (x->string) - 1] = 0;
  494.           } else {
  495.             x->value [0] = (double) 0;
  496.             entered      = 1;
  497.             stack_lift   = 0;
  498.           }
  499.         } else {
  500.           if (x->string [17] == '0' && x->string [18] == '0') {
  501.             p   = strchr (&x->string[1],' ');
  502.             *p  = 0;
  503.             eex = 0;
  504.           } else {
  505.             x->string [18] = x->string [17];
  506.             x->string [17] = '0';
  507.           }
  508.         }
  509.       }
  510.     break;
  511.  
  512.     case 1 : /* clear x */
  513.       x->value [0] = (double) 0;
  514.       eex         = 0;
  515.       entered     = 1;
  516.       stack_lift  = 0;
  517.     break;
  518.  
  519.     case 2 : /* clear prefix */
  520.       prefix = 0;
  521.     break;
  522.  
  523.     case 3 : /* clear registers */
  524.       for (j = 0; j < 67; j++) store [j] = 0;
  525.     break;
  526.  
  527.     case 4 : /* clear statistics registers */
  528.       for (j = 2; j < 8; j++)  store [j] = 0;
  529.     break;
  530.  
  531.     default : break;
  532.   }
  533.     
  534.   refresh_display ();
  535. }   
  536.  
  537. static void roll (int i)
  538. {
  539.   struct stack_register *temp;
  540.  
  541.   x->value [0] = string_to_value (x->string);
  542.   switch (i) {
  543.     case 0: /* down */
  544.       temp = x;
  545.       x    = y;
  546.       y    = z;
  547.       z    = t;
  548.       t    = temp;
  549.     break;
  550.     case 1: /* up */
  551.       temp = t;
  552.       t    = z;
  553.       z    = y;
  554.       y    = x;
  555.       x    = temp;
  556.     break;
  557.     default : break;
  558.   }
  559.   stack_lift = 1;
  560.   refresh_display ();
  561. }
  562.  
  563. static void change_sign ()
  564. {
  565.   if (entered)
  566.     x->value [0] = -x->value [0];
  567.   else if (!eex)
  568.     x->string [0]  = (x->string [0]  == ' ') ? '-' : ' ';
  569.   else
  570.     x->string [16] = (x->string [16] == ' ') ? '-' : ' ';
  571.   refresh_display ();
  572. }
  573.  
  574. static void onefunction (int i)
  575. {
  576.   struct stack_register *ts;
  577.   double temp,divisor,a,b,r,angle;
  578.   int    j;
  579.  
  580.   x->value [0] = string_to_value (x->string);
  581.   temp         = x->value [0];
  582.   if (i != 6) last_x = x->value [0];
  583.   switch (i) {
  584.     case 0  : /* Integer Portion */
  585.       x->value [0] = floor (x->value [0]);
  586.     break;
  587.     case 1  : /* Fractional Portion */
  588.       if (x->value [0] < 0)
  589.         x->value [0] -= ceil  (x->value [0]);
  590.       else
  591.         x->value [0] -= floor (x->value [0]);
  592.     break;
  593.     case 2  : /* Rounding */
  594.       value_to_string (lbuf,x->value [0]);
  595.       entered      = 0;
  596.       x->value [0] = string_to_value (lbuf);
  597.     break;
  598.     case 3  : /* reciprocal */
  599.       divisor = x->value [0] * x->value [0] + x->value [1] * x->value [1];
  600.       if (fabs(divisor) > DBL_MIN) {
  601.         x->value [0] = x->value [0] / divisor;
  602.         x->value [1] = x->value [1] / divisor;
  603.       } else calc_error (error_message [1]);
  604.     break;
  605.     case 4  : /* 10 to power of x */
  606.       a = exp ( x->value [0] * log (10));
  607.       b =       x->value [1] * log (10);
  608.       x->value [0] = a * cos (b);
  609.       x->value [1] = a * sin (b);
  610.     break;
  611.     case 5  : /* exponential */
  612.       x->value [0] = exp (temp) * cos (x->value [1]);
  613.       x->value [1] = exp (temp) * sin (x->value [1]);
  614.     break;
  615.     case 6  : /* exchange x <> y */
  616.       ts = x;
  617.       x  = y;
  618.       y  = ts;
  619.     break;
  620.     case 7  : /* square root */
  621.       if (sflag [8]) {
  622.         r     = sqrt (pow (x->value [0],2) + pow (x->value [1],2));
  623.         angle = atan2 (x->value [1], x->value [0]);
  624.         if (r >= 0) {
  625.           x->value [0] = sqrt (r) * cos (angle / 2);
  626.           x->value [1] = sqrt (r) * sin (angle / 2);
  627.         } else calc_error (error_message [0]);
  628.       } else {
  629.         if (x->value [0] > 0) {
  630.           x->value [0] = sqrt (x->value [0]);
  631.         } else calc_error (error_message [0]);
  632.       } 
  633.     break;
  634.     case 8  : /* factorial */
  635.       temp = x->value [0];
  636.       for (a = 1.0; temp >  1.0; a *=   temp--);
  637.       for (b = 1.0; temp < -2.0; b /= ++temp  );
  638.       if (temp != 1.0) {
  639.         for (j = 0, divisor = 0, temp++; j < 26; j++) 
  640.           divisor += gamma_fn_coefficient [j] * pow (temp,j + 1);
  641.         if (fabs (divisor) > DBL_MIN && temp != -1.0) {
  642.           x->value [0] = a * b / divisor;
  643.         } else calc_error (error_message [1]);
  644.       } else x->value [0] = a * b;
  645.     break;
  646.     case 11 : /* common logarithm */
  647.     case 12 : /* natural logarithm */
  648.       r     = sqrt (pow (x->value [0],2) + pow (x->value [1],2));
  649.       angle = atan2 (x->value [1], x->value [0]);
  650.       if (r > 0) {
  651.         if (i == 11) {
  652.           x->value [0] = log (r) / log (10);
  653.           x->value [1] = angle   / log (10);
  654.         } else {
  655.           x->value [0] = log (r);
  656.           x->value [1] = angle;
  657.         }
  658.       } else calc_error (error_message [3]);           
  659.     break;
  660.     case 13 : /* square */
  661.       temp         = x->value [0];
  662.       x->value [0] = pow (x->value [0],2) - pow (x->value [1],2);
  663.       x->value [1] = 2 * temp * x->value [1];
  664.     break;
  665.     case 14 : /* absolute value */
  666.       x->value [0] = sqrt (pow (x->value [0],2) + pow (x->value [1],2));
  667.       x->value [1] = 0;
  668.     break;
  669.     default : break;
  670.   }
  671.   prefix     = 0;
  672.   stack_lift = 1;
  673.   refresh_display ();
  674. }
  675.       
  676. static void twofunction (char c)
  677. {
  678.   double temp,a,b,r,angle,divisor;
  679.  
  680.   x->value [0] = string_to_value (x->string);
  681.   last_x       = x->value [0];
  682.   switch (c) {
  683.     case '-' :
  684.       x->value [0] = y->value [0] - x->value [0];
  685.       x->value [1] = y->value [1] - x->value [1];
  686.     break;
  687.     case '+' :
  688.       x->value [0] = x->value [0] + y->value [0];
  689.       x->value [1] = x->value [1] + y->value [1];
  690.     break;
  691.     case 'x' :
  692.       temp         = x->value [0];
  693.       x->value [0] = x->value [0]*y->value [0] - x->value [1]*y->value [1];
  694.       x->value [1] = temp        *y->value [1] + x->value [1]*y->value [0];
  695.     break;
  696.     case '/' :
  697.       divisor = x->value [0] * x->value [0] + x->value [1] * x->value [1];
  698.       if (fabs(divisor) > DBL_MIN) {
  699.         temp         = x->value [0];
  700.         x->value [0] = x->value [0]*y->value [0] + x->value [1]*y->value [1];
  701.         x->value [1] = temp        *y->value [1] - x->value [1]*y->value [0];
  702.         x->value [0] /= divisor;
  703.         x->value [1] /= divisor;
  704.       } else  calc_error (error_message [1]);
  705.       break;
  706.     case '^' : /* y to the power of x */
  707.       r     = sqrt (pow (y->value [0],2) + pow (y->value [1],2));
  708.       angle = atan2 (y->value [1], y->value [0]);
  709.       a     = exp (x->value [0] * log (r)) / (exp (x->value [1] * angle));
  710.       b     = x->value [0] * angle + x->value [1] * log (r);
  711.       x->value [0] = a * cos (b);
  712.       x->value [1] = a * sin (b);
  713.     break;
  714.     default  : break;
  715.   }
  716.   y->value [0] = z->value [0];
  717.   z->value [0] = t->value [0];
  718.   y->value [1] = z->value [1];
  719.   z->value [1] = t->value [1];
  720.   prefix     = 0;
  721.   stack_lift = 1;
  722.   refresh_display ();
  723. }
  724.  
  725. double modetoradians (double angle)
  726. {
  727.   switch (trig_mode) {
  728.     case 0  : return (angle * asin (1) /  90); break;
  729.     case 2  : return (angle * asin (1) / 100); break;
  730.     default : return (angle);                  break;
  731.   }
  732. }
  733.  
  734. static double radianstomode (double angle)
  735. {
  736.   switch (trig_mode) {
  737.     case 0  : return (angle *  90 / asin (1)); break;
  738.     case 2  : return (angle * 100 / asin (1)); break;
  739.     default : return (angle);                  break;
  740.   }
  741. }
  742.  
  743. static void trigfunctions (int i)
  744. {
  745.   double x_temp,temp,divisor,a,b,r;
  746.  
  747.   x_temp = last_x = x->value [0] = string_to_value (x->string);
  748.   switch (i) {
  749.     case 0  : /* (hyperbolic (arc)) sine */
  750.       if (!prefix) {
  751.         x_temp = (sflag [8]) ? x->value [0] : modetoradians (x->value [0]);
  752.         x->value [0] = sin (x_temp) * cosh (x->value [1]);
  753.         x->value [1] = cos (x_temp) * sinh (x->value [1]);
  754.       } else if (prefix == 7) {
  755.         x_temp = (sflag [8]) ? x->value [0] : modetoradians (x->value [0]);
  756.         x->value [0] = sinh (x_temp) * cos (x->value [1]);
  757.         x->value [1] = cosh (x_temp) * sin (x->value [1]);
  758.       } e (&f (prefix == 8) {
  759.         temp = 0.5 * sqrt (pow (x->value [1] - 1,2) + pow (x_temp,2));
  760.         b    = 0.5 * sqrt (pow (x->value [1] + 1,2) + pow (x_temp,2));
  761.         a    = b + temp;
  762.         b    = b - temp;
  763.         x->value [0] = log (a + sqrt (pow (a,2) - 1));
  764.         x->value [1] = asin (b);
  765.         if (!sflag [8]) x->value [0] = radianstomode (x->value [0]);
  766.       }
  767.     break;
  768.     case 1  : /* (hyperbolic (arc)) cosine */
  769.       if (!prefix) {
  770.         x_temp = (sflag [8]) ? x->value [0] : modetoradians (x->value [0]);
  771.         x->value [0] =  cos (x_temp) * cosh (x->value [1]);
  772.         x->value [1] = -sin (x_temp) * sinh (x->value [1]);
  773.       } else if (prefix == 7) {
  774.         x_temp = (sflag [8]) ? x->value [0] : modetoradians (x->value [0]);
  775.         x->value [0] = cosh (x_temp) * cos (x->value [1]);
  776.         x->value [1] = sinh (x_temp) * sin (x->value [1]);
  777.       } else if (prefix == 8) {
  778.         temp = 0.5 * sqrt (pow (x_temp - 1,2) + pow (x->value [1],2));
  779.         b    = 0.5 * sqrt (pow (x_temp + 1,2) + pow (x->value [1],2));
  780.         a    = b + temp;
  781.         b    = b - temp;
  782.         x->value [0] = log (a + sqrt (pow (a,2) - 1));
  783.         x->value [1] = acos (b);
  784.         if (!sflag [8]) x->value [0] = radianstomode (x->value [0]);
  785.       }
  786.     break;
  787.     case 2  : /* (hyperbolic (arc)) tangent */
  788.       if (!prefix) {
  789.         x_temp = (sflag [8]) ? x->value [0] : modetoradians (x->value [0]);
  790.         divisor = cos (2 * x_temp) + cosh (2 * x->value [1]);
  791.         if (fabs(divisor) > DBL_MIN) {
  792.           x->value [0] = sin  (2 * x_temp) / divisor;
  793.           x->value [1] = sinh (2 * x->value [1]) / divisor;
  794.         } else calc_error (error_message [1]);
  795.       } e se if (prefix == 7) {
  796.         x_temp = (sflag [8]) ? x->value [0] : modetoradians (x->value [0]);
  797.         divisor = cosh (2 * x_temp) + cos (2 * x->value [1]);
  798.         if (fabs(divisor) > DBL_MIN) {
  799.           x->value [0] = sinh (2 * x_temp) / divisor;
  800.           x->value [1] = sin  (2 * x->value [1]) / divisor;
  801.         } else calc_error (error_message [1]);
  802.       } else if (prefix == 8) {
  803.         if (x->value [1] != 0 || fabs (x_temp) != 1) {
  804.           r = pow (x_temp,2)      + pow (x->value [1],2);
  805.           a = pow (x->value [1],2) + pow (x_temp + 1,2);
  806.           b = pow (x->value [1],2) + pow (x_temp - 1,2);
  807.           x->value [0] = 0.25 * log (a / b);
  808.           x_temp      = x->value [1];
  809.           if (fabs (1 - r) > DBL_MIN) {
  810.             x->value [1] = 0.5 * atan (2 * x_temp / (1 - r));
  811.           } else x->value [1] = -0.5 * asin (1);
  812.           if (x_temp > 0 && x->value [1] < 0) x->value [1] += asin (1);
  813.           if (!sflag [8]) x->value [0] = radianstomode (x->value [0]);
  814.         } else calc_error (error_message [2]);
  815.       }          
  816.     break;
  817.     case 8  : /* arc sine */
  818.     case 9  : /* arc cosine */
  819.       temp = 0.5 * sqrt (pow (x_temp - 1,2) + pow (x->value [1],2));
  820.       b    = 0.5 * sqrt (pow (x_temp + 1,2) + pow (x->value [1],2));
  821.       a    = b + temp;
  822.       b    = b - temp;
  823.       if (b <= 1.0) {
  824.         temp = log (a + sqrt (pow (a,2) - 1));
  825.         switch (i) {
  826.           case 8  : /* arc sine */
  827.             x->value [0] = asin (b);
  828.                  if (x->value [1] > 0) x->value [1] =  temp;
  829.             e (&f (x->value [1] < 0) x->value [1] = -temp;
  830.             else x->value [1] = (x_temp >= 0) ? -temp : temp;
  831.             if (!sflag [8]) x->value [0] = radianstomode (x->value [0]);
  832.           break;
  833.           case 9  : /* arc cosine */
  834.               x->value [0] = acos (b);
  835.                  if (x->value [1] > 0) x->value [1] = -temp;
  836.             e se if (x->value [1] < 0) x->value [1] =  temp;
  837.             else x->value [1] = (x_temp >= 0) ? temp : -temp;
  838.             if (!sflag [8]) x->value [0] = radianstomode (x->value [0]);
  839.           break;
  840.           default : break;
  841.         }
  842.       } else calc_error (error_message [2]);
  843.     break;
  844.     case 10 : /* arc tangent */
  845.       if (sflag [8]) {
  846.         if (x_temp != 0 || fabs (x->value [1]) != 1) {
  847.           r = pow (x_temp,2) + pow (x->value [1],2);
  848.           a = pow (x_temp,2) + pow (x->value [1] + 1,2);
  849.           b = pow (x_temp,2) + pow (x->value [1] - 1,2);
  850.           if (fabs (1 - r) > DBL_MIN) {
  851.             x->value [0] = 0.5 * atan (2 * x_temp / (1 - r));
  852.           } else x->value [0] = -0.5 * asin (1);
  853.           if (x_temp > 0 && x->value [0] < 0) x->value [0] += asin (1);
  854.           x->value [1] = 0.25 * log (a / b);
  855.         } else calc_error (error_message [2]);
  856.       } else x->value [0] = radianstomode (atan (x_temp));           
  857.     break;
  858.     default : break;
  859.   }
  860.   prefix     = 0;
  861.   stack_lift = 1;
  862.   refresh_display ();
  863. }
  864.  
  865. static void register_op (char *s)
  866. {
  867.   x->value [0] = string_to_value (x->string);
  868.  
  869.   if ( *s >= '0' && *s <= '9') which_register += (int) (*s - '0');
  870.   e (&f (*s == '.')          which_register += 10;
  871.   else if (*s == 'i')          which_register  = 67;
  872.   else if (!strcmp (s,"(i)"))  which_register  = (int) store [67];
  873.  
  874.   if (which_register <= 67 && which_register >= 0) {
  875.     switch (prefix) {
  876.  
  877.       case 1  :  /* Store X in register */
  878.         if ( *s != '.') {
  879.           switch (operation) {
  880.             case '-' : store [which_register] -= x->value [0]; break;
  881.             case '+' : store [which_register] += x->value [0]; break;
  882.             case 'x' : store [which_register] *= x->value [0]; break;
  883.             case '/' :
  884.               if (fabs(x->value [0]) <= DBL_MIN)
  885.                 calc_error (error_message [1]);
  886.               else
  887.                 store [which_register] /= x->value [0];
  888.               break;
  889.             default  : store [which_register]  = x->value [0]; break;
  890.           }        
  891.         }
  892.       break;
  893.  
  894.       case 2  : /* Restore X from register */
  895.         if ( *s != '.') {
  896.           switch (operation) {
  897.             case '-' : x->value [0] -= store [which_register]; break;
  898.             case '+' : x->value [0] += store [which_register]; break;
  899.             case 'x' : x->value [0] *= store [which_register]; break;
  900.             case '/' :
  901.               if (fabs (store [which_register]) <= DBL_MIN)
  902.                 calc_error (error_message [1]);
  903.               else
  904.                 x->value [0] /= store [which_register];
  905.               break;
  906.             default  : 
  907.               lift_stack ();
  908.               x->value [0] = store [which_register];
  909.             break;
  910.           }
  911.         }
  912.       break;
  913.  
  914.       case 9 : /* Exchange X with register */
  915.         if ( *s != '.') {
  916.           double temp            = x->value [0];
  917.           x->value [0]           = store [which_register];
  918.           store [which_register] = temp;
  919.         }
  920.       break;
  921.     }
  922.   } else calc_error (error_message [4]);
  923.   if ( *s != '.') {
  924.     stack_lift = 1;        
  925.     operation  = '0';
  926.     prefix = which_register = 0;
  927.     refresh_display ();
  928.   }
  929. }
  930.  
  931. static void eval_prefix (char *s)
  932. {
  933.   double temp;
  934.   char  *p;
  935.  
  936.   x->value [0] = string_to_value (x->string);
  937.   switch (prefix) {
  938.  
  939.     case 3  : /* fixed point */
  940.     case 4  : /* scientific */
  941.     case 5  : /* engineering */
  942.     case 6  : /* hex */
  943.       if (*s != '.') {
  944.         precision = (int) *s - '0';
  945.         if (hex)
  946.           temp = (double) strtol (x->string, (char**) NULL,16);
  947.         else
  948.           temp = strtod (x->string, (char**) NULL);
  949.         switch (prefix) {
  950.           case 3  : scientific = 0; engineering = 0; hex = 0; break;
  951.           case 4  : scientific = 1; engineering = 0; hex = 0; break;
  952.           case 5  : scientific = 0; engineering = 1; hex = 0; break;
  953.           case 6  : scientific = 0; engineering = 0; hex = 1; break;
  954.           default : break;
  955.         }
  956.         if (hex) {
  957.           sprintf (x->string," %lx",(long) fabs (floor (temp)));
  958.           for (p = x->string; *p; p++) *p = toupper (*p);
  959.         } else {
  960.           if (temp >= 0)
  961.             sprintf (x->string," %f", temp);
  962.           else
  963.             sprintf (x->string,"-%f",-temp);
  964.         }
  965.         prefix = 0;
  966.       }
  967.     break;
  968.  
  969.     case 10 : /* Set Flag */
  970.       if ( *s >= '0' && *s <= '9') {
  971.         int which_flag = (int) (*s - '0');
  972.         if (which_flag == 8) change_complex (1); else sflag [which_flag] = 1;
  973.         prefix = 0;
  974.       } 
  975.      break;
  976.  
  977.     case 11 : /* Clear Flag */
  978.       if ( *s >= '0' && *s <= '9') {
  979.         int which_flag = (int) (*s - '0');
  980.         if (which_flag == 8) change_complex (0); else sflag [which_flag] = 0;
  981.         prefix = 0;
  982.       } 
  983.     break;
  984.  
  985.     default : prefix = 0; break;
  986.   }
  987.   refresh_display ();
  988. }
  989.  
  990. static void constant (int i)
  991. {
  992.   x->value [0] = string_to_value (x->string);
  993.   lift_stack ();
  994.   switch (i) {
  995.     case  0 : x->value [0] = 2 * asin (1); break;
  996.     default : break;
  997.   }
  998.   refresh_display ();
  999. }
  1000.  
  1001. static void percent (int i)
  1002. {
  1003.   x->value [0] = string_to_value (x->string);
  1004.   last_x      = x->value [0];
  1005.   switch (i) {
  1006.     case  0 :
  1007.       x->value [0] = x->value [0] * y->value [0] / 100;
  1008.     break;
  1009.     case  1 :
  1010.       x->value [0] = (x->value [0] - y->value [0]) * 100 / y->value [0];
  1011.     break; 
  1012.     default : break;
  1013.   }
  1014.   stack_lift = 1;
  1015.   refresh_display ();
  1016. }
  1017.  
  1018. static void statistics (int code)
  1019. {
  1020.   double M,N,O,P,C,divisor,temp;
  1021.  
  1022.   x->value [0] = string_to_value (x->string);
  1023.   switch (code) {
  1024.  
  1025.     case  0 : /* sum + */
  1026.       if (prefix == 2) {
  1027.         lift_stack ();
  1028.         lift_stack ();
  1029.         x->value [0] = store [3];
  1030.         y->value [0] = store [5];
  1031.       } e se { 
  1032.         last_x     = x->value [0];
  1033.         store [2] += 1;
  1034.         store [3] += x->value [0];
  1035.         store [4] += x->value [0] * x->value [0];
  1036.         store [5] += y->value [0];
  1037.         store [6] += y->value [0] * y->value [0];
  1038.         store [7] += x->value [0] * y->value [0];
  1039.         x->value [0] = store [2];
  1040.         stack_lift = 0;
  1041.       }
  1042.     break;
  1043.  
  1044.     case  1 : /* sum - */
  1045.       last_x     = x->value [0];
  1046.       store [2] -= 1;
  1047.       store [3] -= x->value [0];
  1048.       store [4] -= x->value [0] * x->value [0];
  1049.       store [5] -= y->value [0];
  1050.       store [6] -= y->value [0] * y->value [0];
  1051.       store [7] -= x->value [0] * y->value [0];
  1052.       x->value [0] = store [2];
  1053.       stack_lift = 0;
  1054.     break;
  1055.  
  1056.     case  2 :
  1057.     case  3 :
  1058.     case  4 :
  1059.     case  5 :
  1060.       lift_stack ();
  1061.       lift_stack ();
  1062.       M = store [2] * store [4] - store [3] * store [3];
  1063.       N = store [2] * store [6] - store [5] * store [5];
  1064.       P = store [2] * store [7] - store [3] * store [5];
  1065.       switch (code) {
  1066.  
  1067.         case  2 : /* mean */
  1068.           if (fabs (store [2]) <= DBL_MIN)
  1069.             calc_error (error_message [1]);
  1070.           else {
  1071.             x->value [0] = store [3] / store [2];
  1072.             y->value [0] = store [5] / store [2];
  1073.           }
  1074.         break;
  1075.  
  1076.         case  3 : /* standard deviation about mean */
  1077.           divisor = store [2] * (store [2] - (double) 1);
  1078.           if (fabs (divisor) <= DBL_MIN)
  1079.             calc_error (error_message [1]);
  1080.           else {
  1081.             M /= divisor;
  1082.             N /= divisor;
  1083.             if (M < 0 || N < 0)
  1084.               calc_error (error_message [0]);
  1085.             else {
  1086.               x->value [0] = sqrt (M);
  1087.               y->value [0] = sqrt (N);
  1088.             }            
  1089.           }
  1090.         break;
  1091.  
  1092.         case  4 : /* Linear Regression */
  1093.           divisor = store [2] * M;
  1094.           if (fabs (divisor) <= DBL_MIN || fabs (M) <= DBL_MIN)
  1095.             calc_error (error_message [1]);
  1096.           else {
  1097.             x->value [0] = (M * store [5] - P * store [3]) / divisor;
  1098.             y->value [0] = P / M;
  1099.           }
  1100.         break;
  1101.  
  1102.         case  5 : /* Linear Estimation & Correlation Coefficient */
  1103.           last_x  = x->value [0];
  1104.           divisor = store [2] * M;
  1105.           temp    = M * N;
  1106.           if (fabs (divisor) <= DBL_MIN || fabs (temp) <= DBL_MIN)
  1107.             calc_error (error_message [1]);
  1108.           else {
  1109.             if (temp < 0)
  1110.               calc_error (error_message [0]);
  1111.             else {
  1112.               x->value [0]  = (M * store[5] +
  1113.                               P * (store[2] * x->value [0] - store[3])) /
  1114.                               divisor;
  1115.               y->value [0]  = P / sqrt (temp);
  1116.             }
  1117.           }
  1118.         break;
  1119.  
  1120.         default : break;
  1121.       }
  1122.     break;
  1123.  
  1124.     case  6 : /* Permutations & Combinations*/
  1125.     case  7 :
  1126.       last_x = x->value [0];
  1127.       P = C = (double) 1;
  1128.       O = x->value [0];
  1129.       M = y->value [0];
  1130.       N = y->value [0] - x->value [0];
  1131.       while (N > 1 || M > 1 || O > 1) {
  1132.         P *= M / N;
  1133.         C *= M / (N * O);
  1134.         if (N > 1) N--;
  1135.         if (M > 1) M--;
  1136.         if (O > 1) O--;
  1137.       }
  1138.       drop_stack ();
  1139.       x->value [0] = (code == 6) ? P : C;
  1140.     break;
  1141.         
  1142.     case 8  : /* Random Number */
  1143.       last_x = x->value [0];
  1144.       switch (prefix) {
  1145.         case  1 :
  1146.           temp = fabs (x->value [0]);
  1147.           seed = (int) ((temp - floor (temp)) * RAND_MAX);
  1148.           srand (seed);
  1149.         break;
  1150.         case  2 :
  1151.           x->value [0] = ((double) seed) / RAND_MAX;
  1152.         break;
  1153.         default :
  1154.           seed         = rand ();
  1155.           x->value [0] = ((double) seed) / RAND_MAX;
  1156.         break;
  1157.       }
  1158.     break;
  1159.  
  1160.     default : break;
  1161.   }
  1162.   prefix = 0;
  1163.   refresh_display ();
  1164. }                   
  1165.  
  1166. static void make_complex (int i)
  1167. {
  1168.   double temp;
  1169.  
  1170.   x->value [0] = string_to_value (x->string);
  1171.   change_complex (1);
  1172.   switch (i) {
  1173.  
  1174.     case 0  : /* I */
  1175.       temp         = x->value [0];
  1176.       drop_stack ();
  1177.       x->value [1] = temp;
  1178.     break;
  1179.  
  1180.     case 1  : /* real <> imaginary */
  1181.       temp         = x->value [0];
  1182.       x->value [0] = x->value [1];
  1183.       x->value [1] = temp;
  1184.     default : break;
  1185.   }
  1186.   prefix = 0;
  1187.   refresh_display ();
  1188. }
  1189.  
  1190. static void to_something (int i)
  1191. {
  1192.   double hours,minutes,seconds,a,b,r,angle;
  1193.  
  1194.   x->value [0] = string_to_value (x->string);
  1195.   last_x       = x->value [0];
  1196.   switch (i) {
  1197.  
  1198.     case 0  : /* Rectangular Coordinates */
  1199.       angle = modetoradians ((sflag [8]) ? x->value [1] : y->value [0]);
  1200.       a = x->value [0] * cos (angle);
  1201.       b = x->value [0] * sin (angle);
  1202.       x->value [0] = a;
  1203.       if (!sflag [8]) y->value [0] = b; else x->value [1] = b;
  1204.     break;
  1205.  
  1206.     case 1  : /* Polar Coordinates */
  1207.       if (!sflag [8]) {
  1208.         r     = sqrt (pow (x->value [0],2) + pow (y->value [0],2));
  1209.         angle = radianstomode (atan2 (y->value [0], x->value [0]));
  1210.         x->value [0] = r;
  1211.         y->value [0] = angle;
  1212.       } else {
  1213.         r     = sqrt (pow (x->value [0],2) + pow (x->value [1],2));
  1214.         angle = radianstomode (atan2 (x->value [1], x->value [0]));
  1215.         x->value [0] = r;
  1216.         x->value [1] = angle;
  1217.       }
  1218.     break;
  1219.  
  1220.     case 2  : /* Hours, Minutes and Seconds */
  1221.       hours        = floor (x->value [0]);
  1222.       minutes      = floor ((x->value [0] - hours) * 60);
  1223.       seconds      = (x->value [0] - hours - minutes / 60) * 3600;
  1224.       x->value [0] = hours + minutes / 100 + seconds / 10000;
  1225.     break;
  1226.  
  1227.     case 3  : /* Hours */
  1228.       hours        = floor (x->value [0]);
  1229.       minutes      = floor ((x->value [0] - hours) * 100);
  1230.       seconds      = (x->value [0] - hours - minutes / 100) * 10000;
  1231.       x->value [0] = hours + minutes / 60 + seconds / 3600;
  1232.     break;
  1233.  
  1234.     case 4  : /* Radians */
  1235.       x->value [0] = x->value [0] * asin (1) / 90;
  1236.     break;
  1237.  
  1238.     case 5  : /* Degrees */
  1239.       x->value [0] = x->value [0] * 90 / asin (1);
  1240.     break;
  1241.  
  1242.     default : break;
  1243.   }
  1244.   prefix = 0;
  1245.   refresh_display ();
  1246. }
  1247.  
  1248. static void restore_x ()
  1249. {
  1250.   x->value [0] = string_to_value (x->string);
  1251.   lift_stack ();
  1252.   x->value [0] = last_x;
  1253.   prefix       = 0;
  1254.   refresh_display ();
  1255. }
  1256.  
  1257. static void set_eex ()
  1258. {
  1259.   int j;
  1260.  
  1261.   if (!eex && !hex && (strlen (x->string) < 15 || entered)) {
  1262.     if (entered) {
  1263.       lift_stack ();
  1264.       strcpy (x->string," 1");
  1265.     } else if (string_to_value (x->string) == 0) strcpy (x->string," 1");
  1266.     for (j = strlen (x->string); j < 17; j++) x->string [j] = ' ';
  1267.     x->string [17] = '0';
  1268.     x->string [18] = '0';
  1269.     x->string [19] =  0;
  1270.     eex     = 1;
  1271.     prefix  = 0;
  1272.     entered = 0;      
  1273.     refresh_display ();
  1274.   }
  1275. }
  1276.  
  1277. static void process_key (char *key)
  1278. {
  1279.        if (!strcmp (key,"ff") && board != 1) select_keyboard (1);
  1280.   else if (!strcmp (key,"fg") && board != 2) select_keyboard (2);
  1281.   e se if (!strcmp (key,"divide")) {
  1282.     if (!prefix) twofunction ('/'); else operation = '/';
  1283.   }
  1284.   else if (!strcmp (key,"times"))  {
  1285.     if (!prefix) twofunction ('x'); else operation = 'x';
  1286.   }
  1287.   e (&f (!strcmp (key,"minus"))  {
  1288.     if (!prefix) twofunction ('-'); else operation = '-';
  1289.   }
  1290.   e se if (!strcmp (key,"plus"))   {
  1291.     if (!prefix) twofunction ('+'); else operation = '+';
  1292.   }
  1293.   e se if (!strcmp (key,"yx"))     twofunction ('^');  
  1294.   else if (!strcmp (key,"sin"))    trigfunctions (0);
  1295.   e se if (!strcmp (key,"cos"))    trigfunctions (1);
  1296.   else if (!strcmp (key,"tan"))    trigfunctions (2);
  1297.   else if (!strcmp (key,"asin"))   trigfunctions (8);
  1298.   else if (!strcmp (key,"acos"))   trigfunctions (9);
  1299.   e se if (!strcmp (key,"atan"))   trigfunctions (10);
  1300.   e (&f (!strcmp (key,"int"))    onefunction (0);
  1301.   e (&f (!strcmp (key,"frac"))   onefunction (1);
  1302.   else if (!strcmp (key,"rnd"))    onefunction (2);
  1303.   else if (!strcmp (key,"1/x"))    onefunction (3);
  1304.   e se if (!strcmp (key,"10x"))    onefunction (4);
  1305.   e se if (!strcmp (key,"ex"))     onefunction (5);  
  1306.   else if (!strcmp (key,"x<>y"))   onefunction (6);  
  1307.   e se if (!strcmp (key,"!x"))     onefunction (7);  
  1308.   e se if (!strcmp (key,"x!"))     onefunction (8);  
  1309.   e se if (!strcmp (key,"log"))    onefunction (11);
  1310.   e se if (!strcmp (key,"ln"))     onefunction (12);  
  1311.   e se if (!strcmp (key,"x2"))     onefunction (13);  
  1312.   e se if (!strcmp (key,"abs"))    onefunction (14);
  1313.   else if (!strcmp (key,"chs"))    change_sign ();
  1314.   else if (!strcmp (key,"pi"))     constant (0);  
  1315.   e (&f (!strcmp (key,"%"))      percent (0);  
  1316.   e se if (!strcmp (key,"d%"))     percent (1);  
  1317.   e se if (!strcmp (key,"enter"))  enter_x_string (x->string);
  1318.   e se if (!strcmp (key,"bsp"))    clear (0);
  1319.   e se if (!strcmp (key,"clx"))    clear (1);
  1320.   else if (!strcmp (key,"prefix")) clear (2);
  1321.   e (&f (!strcmp (key,"reg"))    clear (3);
  1322.   else if (!strcmp (key,"sum"))    clear (4);
  1323.   e se if (!strcmp (key,"rd"))     roll (0);  
  1324.   e se if (!strcmp (key,"ru"))     roll (1);  
  1325.   else if (!strcmp (key,"sto"))    prefix = 1;
  1326.   else if (!strcmp (key,"rcl"))    prefix = 2;    
  1327.   e se if (!strcmp (key,"fix"))    prefix = 3;    
  1328.   e se if (!strcmp (key,"sci"))    prefix = 4;    
  1329.   e se if (!strcmp (key,"eng"))    prefix = 5;    
  1330.   e se if (!strcmp (key,"hex"))    prefix = 6;
  1331.   else if (!strcmp (key,"hyp"))    prefix = 7;
  1332.   else if (!strcmp (key,"ahyp"))   prefix = 8;
  1333.   else if (!strcmp (key,"x<>"))    prefix = 9;      
  1334.   e se if (!strcmp (key,"sf"))     prefix = 10;      
  1335.   e se if (!strcmp (key,"cf"))     prefix = 11;      
  1336.   e se if (!strcmp (key,"s+"))     statistics (0);    
  1337.   e se if (!strcmp (key,"s-"))     statistics (1);    
  1338.   e se if (!strcmp (key,"mean"))   statistics (2);    
  1339.   e se if (!strcmp (key,"sd"))     statistics (3);    
  1340.   e se if (!strcmp (key,"lr"))     statistics (4);    
  1341.   else if (!strcmp (key,"le"))     statistics (5);    
  1342.   e se if (!strcmp (key,"py,x"))   statistics (6);    
  1343.   else if (!strcmp (key,"cy,x"))   statistics (7);    
  1344.   else if (!strcmp (key,"ran#"))   statistics (8); 
  1345.   e se if (!strcmp (key,"re<>im")) make_complex (1);    
  1346.   e (&f (!strcmp (key,"tor"))    to_something (0);    
  1347.   else if (!strcmp (key,"top"))    to_something (1);    
  1348.   else if (!strcmp (key,"tohms"))  to_something (2);    
  1349.   e se if (!strcmp (key,"toh"))    to_something (3);    
  1350.   e se if (!strcmp (key,"torad"))  to_something (4);    
  1351.   e se if (!strcmp (key,"todeg"))  to_something (5);    
  1352.   else if (!strcmp (key,"rad"))    change_trig (1);    
  1353.   e (&f (!strcmp (key,"deg"))    change_trig (0);    
  1354.   else if (!strcmp (key,"grd"))    change_trig (2);    
  1355.   else if (!strcmp (key,"(i)"))    register_op (key);    
  1356.   else if (!strcmp (key,"lstx"))   restore_x ();    
  1357.   e (&f (!strcmp (key,"eex"))    set_eex ();    
  1358.   e se if (!strcmp (key,"bl"))     prefix = 0;    
  1359.   e (&f (!strcmp (key,"i")) {
  1360.     if (!prefix) make_complex (0); else register_op (key);
  1361.   }
  1362.   e se if (!strcmp (key,"dot")) {
  1363.     if (!prefix) add_to_x_string ("."); else register_op (".");
  1364.   }
  1365.   else if (*key >= '0' && *key <= '9') {
  1366.     if (!prefix) add_to_x_string (key);
  1367.     e (&f (prefix < 3 || prefix == 9) register_op (key);
  1368.     else eval_prefix (key);
  1369.   }
  1370.   else if ((*key >= 'a' && *key <= 'f') || (*key >= 'A' && *key <= 'F')) {
  1371.     if (hex) add_to_x_string (key);
  1372.   }
  1373.   if (strcmp (key,"ff") && strcmp (key,"fg") && board != 0) 
  1374.     select_keyboard (0);
  1375. }
  1376.  
  1377. static void load_sprite (sprite_area **p, char *name)
  1378. {
  1379.   os_filestr f;
  1380.   char file [80];
  1381.  
  1382.   res_findname (name, file);
  1383.   fclose (fout);
  1384.   f.action = 5;
  1385.   f.name   = file;
  1386.   wimpt_noerr (os_file (&f));
  1387.   if (f.action) {
  1388.     flex_alloc ((flex_ptr) p, 4 * f.start);
  1389.     sprite_area_initialise (*p, 4 * f.start);
  1390.     wimpt_noerr (sprite_area_load (*p, file));
  1391.   } else { cant (file); *p = NULL; }
  1392. }
  1393.  
  1394. static void calculator_off ()
  1395. {
  1396.   wimpt_noerr (wimp_close_wind (display_x));
  1397.   if (single) wimpt_noerr (wimp_close_wind (display_y));
  1398.   wimpt_noerr (wimp_close_wind (header));
  1399.   wimpt_noerr (wimp_close_wind (keyboard [board]));
  1400.   wimpt_noerr (wimp_close_wind (calc));
  1401. }
  1402.  
  1403. static void calculator_on (int dx,int dy)
  1404. {
  1405.   wimp_wstate o, w;
  1406.  
  1407.   wimpt_noerr (wimp_get_wind_state (calc, &o));
  1408.   o.o.box.x0 += dx; o.o.box.x1 += dx; o.o.box.y0 += dy;
  1409.   o.o.box.y1  = (!single) ? o.o.box.y0 + 405 : o.o.box.y0 + 485;
  1410.   wimpt_noerr (wimp_open_wind (&o.o));
  1411.   w.o.x = o.o.x; w.o.y = o.o.y; w.o.behind = o.o.behind;
  1412.   w.o.w = keyboard [board];
  1413.   w.o.box.x0 = o.o.box.x0 + 5;   w.o.box.x1 = w.o.box.x0 + 715;
  1414.   w.o.box.y0 = o.o.box.y0 + 5;   w.o.box.y1 = w.o.box.y0 + 295;
  1415.   wimpt_noerr (wimp_open_wind (&w.o));
  1416.   w.o.w = header;
  1417.   w.o.box.y0 = o.o.box.y0 + 300; w.o.box.y1 = o.o.box.y1 - 5;
  1418.   wimpt_noerr (wimp_open_wind (&w.o));
  1419.   w.o.w = display_x;
  1420.   w.o.box.x0 = o.o.box.x0 + 50;  w.o.box.x1 = w.o.box.x0 + 500;
  1421.   w.o.box.y0 = o.o.box.y0 + 316; w.o.box.y1 = w.o.box.y0 + 60;
  1422.   wimpt_noerr (wimp_open_wind (&w.o));
  1423.   if (single) {
  1424.     w.o.w = display_y;
  1425.     w.o.box.x0 = o.o.box.x0 + 50;  w.o.box.x1 = w.o.box.x0 + 500;
  1426.     w.o.box.y0 = o.o.box.y0 + 396; w.o.box.y1 = w.o.box.y0 + 60;
  1427.     wimpt_noerr (wimp_open_wind (&w.o));
  1428.   } 
  1429. }
  1430.  
  1431. static void change_calculator (int type)
  1432. {
  1433.   if (single != type) {
  1434.     calculator_off ();
  1435.     if (single) {
  1436.       wimpt_noerr (wimp_delete_icon (header, xicon));
  1437.       wimpt_noerr (wimp_delete_icon (header, yicon));
  1438.     } else {
  1439.       if (sflag [8]) wimpt_noerr (wimp_delete_icon (header, yicon));
  1440.     }
  1441.     single = type;
  1442.     if (sflag [8]) {
  1443.       if (!single) {
  1444.         yicon = texticon (header, 5,- 84,40,-16,0x04003109,"Re",2);
  1445.       } else {
  1446.         xicon = texticon (header, 5,- 84,40,-16,0x04003109,"Im",2);
  1447.         yicon = texticon (header, 5,-174,40,-90,0x04003109,"Re",2);
  1448.       }
  1449.     } else {
  1450.       if (single) {
  1451.         xicon = texticon (header,20,- 84,40,-16,0x04003109,"Y",1);
  1452.         yicon = texticon (header,20,-174,40,-90,0x04003109,"X",1);
  1453.       }
  1454.     }
  1455.     calculator_on (0,0);
  1456.   }
  1457. }
  1458.  
  1459. static void move_calculator ()
  1460. {
  1461.   wimp_dragstr d;
  1462.   wimp_wstate  o;
  1463.  
  1464.   wimpt_noerr (wimp_get_wind_state (calc, &o));
  1465.   d.window    = calc;
  1466.   d.type      = wimp_USER_FIXED;
  1467.   d.box.x0    = o.o.box.x0;
  1468.   d.box.y0    = o.o.box.y0;
  1469.   d.box.x1    = o.o.box.x1;
  1470.   d.box.y1    = o.o.box.y1;
  1471.   d.parent.x0 = 0;
  1472.   d.parent.y0 = 0;
  1473.   d.parent.x1 = 2280;
  1474.   d.parent.y1 = 1024;
  1475.   wimpt_noerr (wimp_drag_box (&d));
  1476. }
  1477.  
  1478. static char *which_key (wimp_i handle,int b)
  1479. {
  1480.   int j,found;
  1481.  
  1482.   for (j = 0, found = 0 ; !found && j < 40; j++) {
  1483.     if (handle == icon [b] [j]) found = 1;
  1484.   }
  1485.   return (icons [b * 40 + j - 1]);
  1486. }
  1487.  
  1488. static wimp_w createwindow (x0,y0,width,height,flags,bcol,fcol,title)
  1489. int   x0,y0,width,height,flags;
  1490. char *title,bcol,fcol;
  1491. {
  1492.   wimp_w       handle;
  1493.   wimp_wind    w;
  1494.  
  1495.   w.box.x0 = x0;
  1496.   w.box.y0 = y0;
  1497.   w.box.x1 = x0 + width;
  1498.   w.box.y1 = y0 + height;
  1499.   w.scx    = 0;
  1500.   w.scy    = 0;
  1501.   w.behind = -1;
  1502.   w.flags  = flags;
  1503.   w.colours [wimp_WCTITLEFORE]   = 7;
  1504.   w.colours [wimp_WCTITLEBACK]   = 2;
  1505.   w.colours [wimp_WCWKAREAFORE]  = fcol;
  1506.   w.colours [wimp_WCWKAREABACK]  = bcol;
  1507.   w.colours [wimp_WCSCROLLOUTER] = 3;
  1508.   w.colours [wimp_WCSCROLLINNER] = 1;
  1509.   w.colours [wimp_WCTITLEHI]     = 12;
  1510.   w.colours [wimp_WCRESERVED]    = 0;
  1511.   w.ex.x0 = 0;
  1512.   w.ex.y1 = 0;
  1513.   w.ex.y0 = -height;
  1514.   w.ex.x1 = width;
  1515.   w.titleflags = 0x0000013D;
  1516.   w.workflags  = 0x00003000;
  1517.   w.spritearea = 0;
  1518.   w.minsize    = 0;
  1519.   w.title.indirecttext.buffer      = (char *) title;
  1520.   w.title.indirecttext.validstring = (char *) -1;
  1521.   w.title.indirecttext.bufflen     = strlen (title);
  1522.   w.nicons = 0;
  1523.   wimpt_noerr (wimp_create_wind (&w,&handle));
  1524.   return (handle);
  1525. }
  1526.  
  1527. /*
  1528.  * Closedown Routines
  1529.  */
  1530.  
  1531. static void save_stores ()
  1532. {
  1533.   int j;
  1534.  
  1535.   x->value [0] = string_to_value (x->string);
  1536.   if ((fout = res_openfile ("stores","w")) != NULL) {
  1537. /*
  1538.  * Save registers
  1539.  */
  1540.     for (j = 0; j < 68; j++) fprintf (fout, "%.15g\n", store[j]);
  1541. /*
  1542.  * Save stack
  1543.  */
  1544.     for (j = 0; j < 2;  j++) {
  1545.       fprintf (fout, "%.15g\n", t->value [j]);
  1546.       fprintf (fout, "%.15g\n", z->value [j]);
  1547.       fprintf (fout, "%.15g\n", y->value [j]);
  1548.       fprintf (fout, "%.15g\n", x->value [j]);
  1549.     } 
  1550. /*
  1551.  * Save flags
  1552.  */
  1553.     for (j = 0; j < 10; j++) fprintf (fout, "%d\n", sflag[j]);
  1554.     fprintf (fout, "%d\n", trig_mode);
  1555.     fprintf (fout, "%d\n", scientific);
  1556.     fprintf (fout, "%d\n", engineering);
  1557.     fprintf (fout, "%d\n", hex);
  1558.     fprintf (fout, "%d\n", precision);
  1559.     fclose (fout);
  1560.   } else cant ("stores");
  1561. /*
  1562.  * Save real x value as system variable
  1563.  */
  1564.   sprintf (lbuf, "%.15g", x->value [0]);
  1565.   setvar  (Re_var, lbuf);
  1566. /*
  1567.  * Save imaginary x value as system variable if in complex mode,
  1568.  * otherwise delete the variable
  1569.  */
  1570.   if (sflag [8]) {
  1571.     sprintf (lbuf, "%.15g", x->value [1]);
  1572.     setvar  (Im_var, lbuf);
  1573.   } else setvar (Im_var, "");
  1574. }
  1575.  
  1576. /*
  1577.  * Initialisation Routines
  1578.  */
  1579.  
  1580. static void initialise_keyboard ()
  1581. {
  1582.   int i,j,k,l,m,x,y,x1,y1;
  1583.   wimp_iconflags basic_flags,flags;
  1584.   wimp_w      han;
  1585.   sprite_area *sp;
  1586.  
  1587.   load_sprite (&sprite [0], "Keyboard1");
  1588.   load_sprite (&sprite [1], "Keyboard2");
  1589.   load_sprite (&sprite [2], "Keyboard3");
  1590.   for (l = 0; l < 3; l++) {
  1591.     switch (l) {
  1592.       case 0  : basic_flags = 0x06019122; break;
  1593.       case 1  : basic_flags = 0x06029122; break;
  1594.       case 2  : basic_flags = 0x06039122; break;
  1595.       default : basic_flags = 0x06019122; break;
  1596.     }
  1597.     han = keyboard [l];
  1598.     sp  = sprite   [l];
  1599.     for (i = 0, y = 290; i < 4; i++,y -= 70) {
  1600.       for (j = 0, x = 15; j < 10; j++, x += 70) {
  1601.         if (i == 0) {
  1602.           switch (j) {
  1603.             case  1 : flags = basic_flags + 0x03000000; break;
  1604.             case  2 : flags = basic_flags + 0x02000000; break;
  1605.             default : flags = basic_flags;              break;
  1606.           }
  1607.         } else flags = basic_flags;
  1608.         if (i != 1 | j != 5) {
  1609.           m  = i * 10 + j;
  1610.           k  = l * 40 + m;                         
  1611.           x1 = x + 56;
  1612.           if (i != 0 | j != 5) y1 = y - 60; else y1 = y - 130;
  1613.           icon [l][m] = spriteicon (han,x,-y,x1,-y1,flags,sp,icons [k]);
  1614.         }
  1615.       }
  1616.     }
  1617.   }
  1618. }
  1619.  
  1620. static void initialise_window ()
  1621. {
  1622.   wimp_iconflags rflags,gflags,f;
  1623.  
  1624.   f            = 0x00000151 | (tfont << 24);
  1625.   calc         = createwindow ( 0,  0,725,485,0x10,7,2,&title [1]);
  1626.   keyboard [0] = createwindow ( 5,  5,715,295,0x30,4,7,&title [1]);
  1627.   keyboard [1] = createwindow ( 5,  5,715,295,0x30,4,7,&title [1]);
  1628.   keyboard [2] = createwindow ( 5,  5,715,295,0x30,4,7,&title [1]);
  1629.   header       = createwindow ( 5,300,715,180,0x30,0,7,&title [1]);
  1630.   display_x    = createwindow (50,320,500, 60,0x30,2,7,&title [1]);
  1631.   display_y    = createwindow (50,400,500, 60,0x30,2,7,&title [1]); 
  1632.   hpicon       = spriteicon   (header,632,-84,700,-16,0x9102,
  1633.                                (int *) 1,&title [1]);
  1634.   dicon    [0] = texticon     (display_x,10,-56,490,-4,f,display [0],25);
  1635.   dicon    [1] = texticon     (display_y,10,-56,490,-4,f,display [1],25);
  1636.   switch (trig_mode) {
  1637.     case 0  : gflags = 0x00003101; rflags = 0x00003101; break;
  1638.     case 1  : gflags = 0x00003101; rflags = 0x04003101; break;
  1639.     case 2  : gflags = 0x04003101; rflags = 0x00003101; break;
  1640.     default : gflags = 0x00003101; rflags = 0x00003101; break;
  1641.   }
  1642.   if (!single) {
  1643.     gicon = texticon (header,550,- 46,630,- 16,gflags,"GRAD",4);
  1644.     ricon = texticon (header,550,- 88,630,- 50,rflags,"RAD", 3);
  1645.   } else {
  1646.     gicon = texticon (header,550,-126,630,- 96,gflags,"GRAD",4);
  1647.     ricon = texticon (header,550,-164,630,-140,rflags,"RAD", 3);
  1648.   }
  1649.   if (sflag [8]) {
  1650.     if (!single) {
  1651.       yicon = texticon (header, 5,- 84,40,-16,0x04003109,"Re",2);
  1652.     } else {
  1653.       xicon = texticon (header, 5,- 84,40,-16,0x04003109,"Im",1);
  1654.       yicon = texticon (header, 5,-174,40,-90,0x04003109,"Re",2);
  1655.     }
  1656.   } else {
  1657.     if (single) {
  1658.       xicon = texticon (header,20,- 84,40,-16,0x04003109,"Y",1);
  1659.       yicon = texticon (header,20,-174,40,-90,0x04003109,"X",1);
  1660.     }
  1661.   } 
  1662. }
  1663.  
  1664. static void initialise_stores ()
  1665. {
  1666.   int j;
  1667.   char *s;
  1668.  
  1669.   board       = 0;
  1670.   x = &stack_registers [0];
  1671.   y = &stack_registers [1];
  1672.   z = &stack_registers [2];
  1673.   t = &stack_registers [3];
  1674.   if ((fin = res_openfile ("stores", "r")) != NULL) {
  1675. /*
  1676.  * Restore registers
  1677.  */
  1678.     for (j = 0; j < 68; j++) {
  1679.       fscanf (fin,"%s", lbuf);
  1680.       store [j] = strtod (lbuf, (char **) NULL);
  1681.     }
  1682. /*
  1683.  * Restore stack
  1684.  */
  1685.     for (j = 0; j < 2;  j++) {
  1686.       fscanf (fin, "%s", lbuf);
  1687.       t->value [j] = strtod (lbuf, (char **) NULL);
  1688.       fscanf (fin, "%s", lbuf);
  1689.       z->value [j] = strtod (lbuf, (char **) NULL);
  1690.       fscanf (fin, "%s", lbuf);
  1691.       y->value [j] = strtod (lbuf, (char **) NULL);
  1692.       fscanf (fin, "%s", lbuf);
  1693.       x->value [j] = strtod (lbuf, (char **) NULL);
  1694.     }
  1695. /*
  1696.  * Restore flags
  1697.  */
  1698.     for (j = 0; j < 10; j++) fscanf (fin, "%d", &sflag[j]);
  1699.     fscanf (fin, "%d", &trig_mode);
  1700.     fscanf (fin, "%d", &scientific);
  1701.     fscanf (fin, "%d", &engineering);
  1702.     fscanf (fin, "%d", &hex);
  1703.     fscanf (fin, "%d", &precision);
  1704.     fclose (fin);
  1705.   } else cant ("stores");
  1706. /*
  1707.  * Restore real variable if defined
  1708.  */ 
  1709.   if ((s = getenv (Re_var)) != NULL)
  1710.     x->value [0] = strtod (s, (char **) NULL);
  1711. /*
  1712.  * Restore imaginary variable if defined and set complex mode
  1713.  */ 
  1714.   if ((s = getenv (Im_var)) != NULL) {
  1715.     x->value [1] = strtod (s, (char **) NULL);
  1716.     sflag [8] = 1;
  1717.   }
  1718. /*
  1719.  * Restore display strings
  1720.  */
  1721.   if (!sflag [8]) {
  1722.     value_to_string (display [1], y->value [0]);
  1723.   } else {
  1724.     value_to_string (display [1], x->value [1]);
  1725.   }
  1726.   value_to_string (x->string, x->value [0]);
  1727.   strcpy (display [0], x->string);
  1728. }
  1729.  
  1730. /*
  1731.  * Wimp Routines
  1732.  */
  1733.  
  1734. static void Open_Window_Request (wimp_openstr *o)
  1735. {
  1736.   wimpt_noerr (wimp_open_wind (o));
  1737. }
  1738.  
  1739. static void Close_Window_Request (wimp_w handle)
  1740. {
  1741.   wimpt_noerr (wimp_close_wind (handle));
  1742. }
  1743.  
  1744. static void Pointer_Leaving_Window (wimp_w handle)
  1745. {
  1746.   wimp_caretstr c;
  1747.  
  1748.   if (handle == calc) {
  1749.     c.w = -1;
  1750.     c.i = -1;
  1751.     wimpt_noerr (wimp_set_caret_pos (&c));
  1752.   }
  1753. }
  1754.  
  1755. static void Pointer_Entering_Window ()
  1756. {
  1757.   wimp_caretstr c;
  1758.  
  1759.   c.w      = calc;
  1760.   c.i      = -1;
  1761.   c.x      =  40;
  1762.   c.y      = -40;
  1763.   c.height = -1;
  1764.   c.index  =  0;
  1765.   wimpt_noerr (wimp_set_caret_pos (&c));
  1766. }
  1767.  
  1768. static void Mouse_Button_Click (wimp_mousestr *event)
  1769. {
  1770.   if (event->bbits & wimp_BLEFT) {
  1771.     if (event->w == header) {
  1772.       move_calculator ();
  1773.     } else if (event->w == keyboard [board]) {
  1774.       if (event->i != -1)
  1775.         process_key (which_key (event->i, board));
  1776.       else move_calculator ();
  1777.     }
  1778.   } else if (event->bbits & wimp_BRIGHT) {
  1779.     if (event->w == keyboard [board] && event->i != -1)
  1780.       process_key (which_key (event->i, (!board) ? 2 : board));
  1781.   }   
  1782. }
  1783.  
  1784. static void User_Drag_Box (wimp_box *box)
  1785. {
  1786.   int         dx, dy;
  1787.   wimp_wstate o;
  1788.  
  1789.   wimpt_noerr (wimp_get_wind_state (calc,&o));
  1790.   dx = o.o.box.x0 - box->x0;
  1791.   dy = o.o.box.y0 - box->y0;
  1792.   calculator_off ();
  1793.   calculator_on  (-dx,-dy);
  1794. }
  1795.  
  1796. static void Key_Pressed (int c)
  1797. {
  1798.   char key [5];
  1799.  
  1800.   strcpy (key," ");
  1801.   *key = (char) c;
  1802.   if (*key == '/') {
  1803.     if (!prefix) twofunction ('/'); else operation = '/';
  1804.   }
  1805.   e (&f (*key == '*')  {
  1806.     if (!prefix) twofunction ('x'); else operation = 'x';
  1807.   }
  1808.   e se if (*key == '-')  {
  1809.     if (!prefix) twofunction ('-'); else operation = '-';
  1810.   }
  1811.   else if (*key == '+')   {
  1812.     if (!prefix) twofunction ('+'); else operation = '+';
  1813.   }
  1814.   else if (*key == 0xd) enter_x_string (x->string);
  1815.   else if (*key == '.') {
  1816.     if (!prefix) add_to_x_string ("."); else register_op (".");
  1817.   }
  1818.   e se if (*key >= '0' && *key <= '9') {
  1819.     if (!prefix) add_to_x_string (key);
  1820.     else if (prefix < 3 || prefix == 9) register_op (key);
  1821.     else eval_prefix (key);
  1822.   }
  1823.   else if ((*key >= 'a' && *key <= 'f') || (*key >= 'A' && *key <= 'F')) {
  1824.     if (hex) add_to_x_string (key);
  1825.   }
  1826.   e se if (c == 0x7f)  clear (0);
  1827.   else if (c == 0x18e) roll  (0);
  1828.   e se if (c == 0x18f) roll  (1);
  1829.   else wimpt_noerr (wimp_processkey (c));
  1830. }
  1831.  
  1832. static void User_Message (wimp_msgstr *msg)
  1833. {
  1834.   switch (msg->hdr.action) {
  1835.     case wimp_MCLOSEDOWN  : save_stores (); exit (0); break;
  1836.     case wimp_MDATASAVE   : break;
  1837.     case wimp_MDATASAVEOK : break;
  1838.     case wimp_MDATALOAD   : break;
  1839.     case wimp_MDATALOADOK : break;
  1840.     default               : break;
  1841.   }
  1842. }
  1843.  
  1844. static void calc_event_handler (wimp_eventstr *e, void *handle)
  1845. {
  1846.   handle = handle;
  1847.  
  1848.   switch (e->e) {
  1849.     case wimp_EOPEN :
  1850.       Open_Window_Request     (&e->data.o);
  1851.     break;
  1852.     case wimp_ECLOSE :
  1853.       Close_Window_Request    (e->data.o.w);
  1854.     break;
  1855.     case wimp_EPTRLEAVE:
  1856.       Pointer_Leaving_Window  (e->data.o.w);
  1857.     break;
  1858.     case wimp_EPTRENTER :
  1859.       Pointer_Entering_Window ();
  1860.     break;
  1861.     case wimp_EBUT :
  1862.       Mouse_Button_Click      (&e->data.but.m);
  1863.     break;
  1864.     case wimp_EKEY :
  1865.       Key_Pressed             (e->data.key.chcode);
  1866.     break;
  1867.     case wimp_ESEND :
  1868.     case wimp_ESENDWANTACK :
  1869.       User_Message            (&e->data.msg);
  1870.     break;
  1871.     default: break;
  1872.   }
  1873. }
  1874.  
  1875. static BOOL calc_unknown_handler (wimp_eventstr *e, void *handle)
  1876. {
  1877.   BOOL result = FALSE;
  1878.  
  1879.   if (handle == &calc) {
  1880.     switch (e->e) {
  1881.       case wimp_EUSERDRAG :
  1882.         User_Drag_Box (&e->data.dragbox);
  1883.         result = TRUE;
  1884.       break;
  1885.     }
  1886.   }
  1887.   return result;
  1888. }
  1889.  
  1890. static void calc_info_about_program (void)
  1891. {
  1892.   dbox  d; 
  1893.  
  1894.   if (d = dbox_new ("ProgInfo"), d != NULL) {
  1895.     dbox_setfield (d, calc_info_field, calc_Version_String);
  1896.     dbox_show     (d);
  1897.     dbox_fillin   (d);
  1898.     dbox_dispose  (&d);
  1899.   }
  1900. }
  1901.  
  1902. static void calc_menuproc (void *handle, char *hit)
  1903. {
  1904.   if (!handle) {
  1905.     switch (hit [0]) {
  1906.       case calc_menu_info: calc_info_about_program (); break;
  1907.       case calc_menu_quit: save_stores (); exit (0);
  1908.     }
  1909.   } else {
  1910.     switch (hit [0]) {
  1911.       case calc_menu_info  : calc_info_about_program (); break;
  1912.       case calc_menu_single: change_calculator (0);      break; 
  1913.       case calc_menu_double: change_calculator (1);      break;
  1914.       case calc_menu_exit  :
  1915.         calculator_off ();
  1916.         if (harddisk) {
  1917.           flex_free ((flex_ptr) &sprite [0]);
  1918.           flex_free ((flex_ptr) &sprite [1]);
  1919.           flex_free ((flex_ptr) &sprite [2]);
  1920.         }
  1921.         calc_active = 0;
  1922.       break;
  1923.     }
  1924.   }
  1925. }
  1926.  
  1927. static void calc_iconclick (wimp_i icon)
  1928. {
  1929.   icon = icon;
  1930.   if (!calc_active) {
  1931.     if (harddisk) initialise_keyboard (); 
  1932.     if (!initialised) {
  1933.       calculator_on (100,150);
  1934.       initialised++;
  1935.     } else calculator_on (0,0);
  1936.     calc_active++;
  1937.   }
  1938. }
  1939.  
  1940. /****************************** INITIALISATION *****************************/
  1941.  
  1942. static BOOL calc_initialise (int start)
  1943. {
  1944.   wimpt_init    (&title [1]);       /* Main Wimp initialisation */
  1945.   res_init      (&title [1]);       /* Resources                */
  1946.   resspr_init   ();                 /* Application sprites      */
  1947.   template_init ();                 /* Templates                */
  1948.   dbox_init     ();                 /* Dialogue boxes           */
  1949.   flex_init     ();
  1950.   wimpt_noerr (font_find ("Portrhouse.Standard",14*16,14*16,0,0,&tfont));
  1951.   initialise_stores   ();
  1952.   initialise_window   ();
  1953.   if (!harddisk) initialise_keyboard ();
  1954.   win_register_event_handler (keyboard [0], calc_event_handler, &calc);
  1955.   win_register_event_handler (keyboard [1], calc_event_handler, &calc);
  1956.   win_register_event_handler (keyboard [2], calc_event_handler, &calc);
  1957.   win_register_event_handler (header      , calc_event_handler, &calc);
  1958.   win_register_event_handler (calc        , calc_event_handler, &calc);
  1959.   win_add_unknown_event_processor (calc_unknown_handler,        &calc); 
  1960.   if ((calc_win_menu = menu_new (&title [1], calc_win_text)) != NULL) {
  1961.     event_attachmenu (header      , calc_win_menu, calc_menuproc, &calc);
  1962.     event_attachmenu (keyboard [0], calc_win_menu, calc_menuproc, &calc);
  1963.     event_attachmenu (keyboard [1], calc_win_menu, calc_menuproc, &calc);
  1964.     event_attachmenu (keyboard [2], calc_win_menu, calc_menuproc, &calc);
  1965.   }
  1966.   if ((calc_bar_menu = menu_new (&title [1], ">Info,Quit")) != NULL) {
  1967.     baricon (title, (int) resspr_area (), calc_iconclick);
  1968.     if (!event_attachmenu (win_ICONBAR, calc_bar_menu, calc_menuproc, 0))
  1969.       return FALSE;
  1970.   } else return FALSE;
  1971.   if (start) calc_iconclick (-2);
  1972.   return TRUE;
  1973. }
  1974.  
  1975. /******************************* MAIN PROGRAM ******************************/
  1976.  
  1977. int main (int argc, char *argv[])
  1978. {
  1979.   backdrop = (argc > 1) ? argv[1][0] - '0' : 0;
  1980.   harddisk = (argc > 2) ? argv[2][0] - '0' : 0;
  1981.   if (calc_initialise (backdrop)) { while (TRUE) event_process (); }
  1982.   return 0;
  1983. }
  1984.  
  1985. /******************************* End of HpCalc *****************************/
  1986. name);2] ยข,spoweee _str*