home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8803 / calctool2.1 / 1 next >
Encoding:
Text File  |  1990-07-13  |  47.6 KB  |  1,555 lines

  1. Path: uunet!munnari!basser!richb
  2. From: richb@sunaus.sun.oz.AU
  3. Newsgroups: comp.sources.misc
  4. Subject: Calctool v2.1 - a Sun calculator. Part 1 of 2.
  5. Message-ID: <1192@basser.oz>
  6. Date: 22 Feb 88 11:55:57 GMT
  7. Sender: john@basser.oz
  8. Lines: 1544
  9. Approved: john@basser.cs.su.oz.AU
  10.  
  11. This is V2.1 of a desktop calculator for the Sun workstation.
  12. Currently this version works under SunView, but NeWS and X.11 versions
  13. will be coming soon.
  14.  
  15. This is a complete rehash from the v1.x series, and now includes
  16. many more mathematical and trigonometrical functions. Memory register
  17. manipulation has been extended, the user interface tidied up and color
  18. is now supported.
  19.  
  20. See the online help or the manual pages for more details.
  21.  
  22. Thankyou to everybody who has sent me mail suggesting enhancements.
  23.  
  24. Thanks to Ed Falk at Sun Microsystems (Mountain View) for some of the
  25. basic algorithms used.
  26.  
  27. Suggestions for furthur improvement would be most welcome plus bugs,
  28. comments and flames.
  29.  
  30.     Rich.
  31.  
  32. Rich Burridge,           JANET richb%sunaus.oz@uk.ac.ucl.cs
  33. ACSnet  richb@sunaus.oz  UUCP {uunet,hplabs,mcvax,ukc}!munnari!sunaus.oz!richb
  34. PHONE: +61 2 436 4699    ARPAnet rburridge@Sun.COM
  35. Sun Microsystems, Unit 2, 49-53 Hotham Pde, Artarmon, N.S.W. 2164, AUSTRALIA.
  36.  
  37. ------CUT HERE------CUT HERE------
  38. #! /bin/sh
  39. # this is a shell archive, meaning:
  40. # 1. Remove everything above the #! /bin/sh line
  41. # 2. Save the resulting text in a file.
  42. # 3. Execute the file with /bin/sh to create the files:
  43. #   calctool.c
  44. #   functions.c
  45. #   sunview.c
  46. # This archive created: Fri Feb 19 18:59:56 EST 1988
  47. #
  48. #
  49. export PATH; PATH=/bin:$PATH
  50. #
  51. if [ -f calctool.c ]
  52. then
  53. echo shar: will not over-write existing file calctool.c
  54. else
  55. echo shar: extracting 'calctool.c',    16468 characters
  56. cat > calctool.c <<'Funky_Stuff'
  57.  
  58. /*  calctool.c
  59.  *
  60.  *  This program looks and acts like a simple calculator.
  61.  *
  62.  *  Copyright (c) Rich Burridge - February 1988.
  63.  *                Sun Microsystems, Australia - All rights reserved.
  64.  *
  65.  *  Basic algorithms by Ed Falk, Sun Microsystems, Mountain View.
  66.  *
  67.  *  Includes ideas and code from:
  68.  *                Rich Baughman, Consumer Financial Institute, Newton, MA
  69.  *
  70.  *  Version 2.1.
  71.  *
  72.  *  No responsibility is taken for any errors or inaccuracies inherent
  73.  *  either to the comments or the code of this program, but if
  74.  *  reported to me then an attempt will be made to fix them.
  75.  */
  76.  
  77. #include "patchlevel.h"
  78. #include "color.h"
  79. #include "calctool.h"
  80.  
  81. double powers[11][4] = {
  82.          {    1.0,          1.0,           1.0,             1.0 },
  83.          {    2.0,          8.0,          10.0,            16.0 },
  84.          {    4.0,         64.0,         100.0,           256.0 },
  85.          {    8.0,        512.0,        1000.0,          4096.0 },
  86.          {   16.0,       4096.0,       10000.0,         65536.0 },
  87.          {   32.0,      32768.0,      100000.0,       1048576.0 },
  88.          {   64.0,     262144.0,     1000000.0,      16777216.0 },
  89.          {  128.0,    2097152.0,    10000000.0,     268435456.0 },
  90.          {  256.0,   16777216.0,   100000000.0,    4294967296.0 },
  91.          {  512.0,  134217728.0,  1000000000.0,   68719476736.0 },
  92.          { 1024.0, 1073741824.0, 10000000000.0, 1099511627776.0 }
  93. } ;
  94.  
  95. char base_str[4][4] = { "BIN", "OCT", "DEC", "HEX" } ;
  96. char ttype_str[3][5] = { "DEG", "GRAD", "RAD" } ;
  97.  
  98. char digits[] = "0123456789abcdef" ;
  99. int basevals[4] = {2, 8, 10, 16} ;
  100.  
  101. /* Length of display in characters for each base. */
  102. int disp_length[4] = {32, 15, 12, 12} ;
  103.  
  104. /* X offset in pixels for various length button strings. */
  105. int chxoff[4] = { 5, 9, 14, 16 } ;
  106.  
  107. double disp_val ;             /* Value of the current display. */
  108. double last_input ;           /* Previous number input by user. */
  109. double mem_vals[MAXREGS] ;    /* Memory register values. */
  110. double result ;               /* Current calculator total value. */
  111. double tresults[3] ;          /* Current trigonometric results. */
  112.  
  113. FILE *hfd ;         /* File descriptor for help information. */
  114.  
  115. int accuracy ;      /* Number of digits precision (Max 9). */
  116. int base ;          /* Current base: BIN, OCT, DEC or HEX. */
  117. int color ;         /* Color being used for current raster operation. */
  118. int column ;        /* Column number of current key/mouse press. */
  119. int down ;          /* Indicates is a mouse button is down. */
  120. int error ;         /* Indicates some kind of display error. */
  121. int iscolor ;       /* Set if this is a color screen. */
  122. int ishelp ;        /* Set if there is a help file. */
  123. int new_input ;     /* New number input since last op. */
  124. int pending ;       /* Indicates command depending on multiple presses. */
  125. int pending_op ;    /* Arithmetic operation for pending command. */
  126. int pointed ;       /* Whether a decimal point has been given. */
  127. int portion ;       /* Portion of button on current key/mouse press. */
  128. int row ;           /* Row number of current key/mouse press. */
  129. int rstate ;        /* Indicates if memory register frame is displayed. */
  130. int spaces ;        /* Number of spaces in current button string. */
  131. int toclear ;       /* Indicates if display should be cleared. */
  132. int tstate ;        /* Indicates current button set being displayed. */
  133. int ttype ;         /* Trigonometric type (deg, grad or rad). */
  134. int x ;             /* X offset for text for button. */
  135. int y ;             /* Y offset for text for button. */
  136.  
  137. /* Routines obeyed by mouse button or character presses. */
  138. int close_frame(),    destroy_frame(),  do_atrig(),     do_base() ;
  139. int do_calculation(), do_clear(),       do_constant(),  do_delete() ;
  140. int do_immediate(),   do_keys(),        do_nothing(),   do_number() ;
  141. int do_pending(),     do_point(),       do_portion(),   do_registers() ;
  142. int do_pending(),     do_trig(),        do_trigtype(),  toggle_reg_canvas() ;
  143.  
  144. char cur_op ;           /* Current arithmetic operation. */
  145. char current ;          /* Current button or character pressed. */
  146. char old_cal_value ;    /* Previous calculation operator. */
  147. char pstr[5] ;          /* Current button text string. */
  148.  
  149. struct button buttons[TITEMS] = {              /* Calculator button values. */
  150.   { ">   ", '>',    OP_SET,   LGREY,    do_pending },       /* Row 1. */
  151.   { "<   ", '<',    OP_SET,   LGREY,    do_pending },
  152.   { "BIN ", 'B',    OP_CLEAR, YELLOW,   do_base },
  153.   { "MEM ", 'M',    OP_CLEAR, BLUE,     toggle_reg_canvas },
  154.   { "OCT ", 'O',    OP_CLEAR, YELLOW,   do_base },
  155.   { "D   ", 'd',    OP_NOP,   PINK,     do_number },
  156.   { "DEC ", 'D',    OP_CLEAR, YELLOW,   do_base },
  157.   { "E   ", 'e',    OP_NOP,   PINK,     do_number }, 
  158.   { "HEX ", 'H',    OP_CLEAR, YELLOW,   do_base },
  159.   { "F   ", 'f',    OP_NOP,   PINK,     do_number },  
  160.   { "KEYS", 'K',    OP_CLEAR, BLUE,     do_keys },
  161.   { "?   ", '?',    OP_SET,   BLUE,     do_pending },  
  162.  
  163.   { "&32 ", 'i',    OP_CLEAR, LGREY,    do_immediate },      /* Row 2. */
  164.   { "STO ", 's',    OP_SET,   MAUVE,    do_pending },
  165.   { "&16 ", 'h',    OP_CLEAR, LGREY,    do_immediate },
  166.   { "RCL ", 'r',    OP_SET,   MAUVE,    do_pending }, 
  167.   { "PI  ", 'P',    OP_CLEAR, ORANGE,   do_constant },
  168.   { "A   ", 'a',    OP_NOP,   PINK,     do_number }, 
  169.   { "e   ", 'E',    OP_CLEAR, ORANGE,   do_constant },
  170.   { "B   ", 'b',    OP_NOP,   PINK,     do_number },
  171.   { "%   ", '%',    OP_SET,   LPURPLE,  do_calculation },
  172.   { "C   ", 'c',    OP_NOP,   PINK,     do_number },
  173.   { "clr ", '\177', OP_CLEAR, BLUE,     do_clear },
  174.   { "bsp ", '\010', OP_NOP,   BLUE,     do_delete },
  175.  
  176.   { "OR  ", '|',    OP_SET,   GREEN,    do_calculation },   /* Row 3. */
  177.   { "AND ", '&',    OP_SET,   GREEN,    do_calculation },
  178.   { "ASIN", '}',    OP_CLEAR, LGREEN,   do_atrig },
  179.   { "SIN ", '{',    OP_CLEAR, LGREEN,   do_trig },
  180.   { "e^x ", '#',    OP_CLEAR, ORANGE,   do_immediate },
  181.   { "7   ", '7',    OP_NOP,   LBLUE,    do_number },
  182.   { "10^x", '$',    OP_CLEAR, ORANGE,   do_immediate },
  183.   { "8   ", '8',    OP_NOP,   LBLUE,    do_number },
  184.   { "y^x ", 'Y',    OP_SET,   ORANGE,   do_calculation },
  185.   { "9   ", '9',    OP_NOP,   LBLUE,    do_number }, 
  186.   { "INT ", 'I',    OP_CLEAR, LGREY,    do_portion },
  187.   { "X   ", 'x',    OP_SET,   LPURPLE,  do_calculation },
  188.  
  189.   { "XNOR", 'n',    OP_SET,   GREEN,    do_calculation },   /* Row 4. */
  190.   { "XOR ", '^',    OP_SET,   GREEN,    do_calculation },
  191.   { "ACOS", ')',    OP_CLEAR, LGREEN,   do_atrig },
  192.   { "COS ", '(',    OP_CLEAR, LGREEN,   do_trig },
  193.   { "ln  ", 'N',    OP_CLEAR, ORANGE,   do_immediate },
  194.   { "4   ", '4',    OP_NOP,   LBLUE,    do_number },
  195.   { "log ", 'G',    OP_CLEAR, ORANGE,   do_immediate },
  196.   { "5   ", '5',    OP_NOP,   LBLUE,    do_number },
  197.   { "SQRT", 'S',    OP_CLEAR, ORANGE,   do_immediate },
  198.   { "6   ", '6',    OP_NOP,   LBLUE,    do_number },
  199.   { "FRAC", 'F',    OP_CLEAR, LGREY,    do_portion },
  200.   { "/   ", '/',    OP_SET,   LPURPLE,  do_calculation },
  201.  
  202.   { "NOT ", '~',    OP_CLEAR, GREEN,    do_immediate },     /* Row 5. */
  203.   { "ACC ", 'A',    OP_SET,   BLUE,     do_pending },
  204.   { "ATAN", 'T',    OP_CLEAR, LGREEN,   do_atrig },
  205.   { "TAN ", 't',    OP_CLEAR, LGREEN,   do_trig },
  206.   { "1/x ", 'R',    OP_CLEAR, ORANGE,   do_immediate },
  207.   { "1   ", '1',    OP_NOP,   LBLUE,    do_number },
  208.   { "x!  ", '!',    OP_CLEAR, ORANGE,   do_immediate },
  209.   { "2   ", '2',    OP_NOP,   LBLUE,    do_number },
  210.   { "x^2 ", '@',    OP_CLEAR, ORANGE,   do_immediate },
  211.   { "3   ", '3',    OP_NOP,   LBLUE,    do_number },
  212.   { "CHS ", 'C',    OP_CLEAR, LGREY,    do_immediate },
  213.   { "-   ", '-',    OP_SET,   LPURPLE,  do_calculation },
  214.  
  215.   { "QUIT", 'q',    OP_CLEAR, BLUE,     destroy_frame },    /* Row 6. */
  216.   { "OFF ", 'o',    OP_CLEAR, BLUE,     close_frame },
  217.   { "    ", ' ',    OP_CLEAR, GREY,     do_nothing },
  218.   { "    ", ' ',    OP_CLEAR, GREY,     do_nothing },
  219.   { "DEG ", '\004', OP_CLEAR, RED,      do_trigtype },
  220.   { "0   ", '0',    OP_NOP,   LBLUE,    do_number },
  221.   { "RAD ", '\022', OP_CLEAR, RED,      do_trigtype },
  222.   { ".   ", '.',    OP_NOP,   LPURPLE,  do_point },
  223.   { "GRAD", '\007', OP_CLEAR, RED,      do_trigtype },
  224.   { "=   ", '=',    OP_CLEAR, LPURPLE,  do_calculation },
  225.   { "ABS ", 'U',    OP_CLEAR, LGREY,    do_portion },
  226.   { "+   ", '+',    OP_SET,   LPURPLE,  do_calculation },
  227.  
  228.   { "    ", 'X',    OP_NOP,   WHITE,    do_calculation },   /* Extra definitions. */
  229.   { "    ", '*',    OP_NOP,   WHITE,    do_calculation },
  230.   { "    ", '\015', OP_NOP,   WHITE,    do_calculation },
  231.   { "    ", 'Q',    OP_NOP,   WHITE,    destroy_frame },
  232. } ;
  233.  
  234. char display[MAXLINE] ;     /* Current calculator display. */
  235. char helpname[MAXLINE] ;    /* Filename for help file. */
  236. char progname[MAXLINE] ;    /* Name of this program. */
  237.  
  238.  
  239. main(argc,argv)
  240. int argc ;
  241. char *argv[] ;
  242. {
  243.   STRCPY(progname,argv[0]) ; /* Save this programs name. */
  244.   get_options(argc,argv) ;   /* Get command line arguments. */
  245.   open_helpfile(helpname) ;  /* Open helpfile if present. */
  246.   make_icon() ;              /* Set up the calctool window icon. */
  247.   init_fonts() ;             /* Open required fonts. */
  248.   make_frames(argc,argv) ;   /* Create calctool window frames. */
  249.   make_subframes() ;         /* Create panels and canvases. */
  250.   make_items() ;             /* Create panel items and cursors. */
  251.   load_colors() ;            /* Load the initial calctool colormap. */
  252.  
  253.   pending = 0 ;              /* No initial pending command. */
  254.   rstate = 0 ;               /* No memory register frame display initially. */
  255.   tstate = 0 ;               /* Button values displayed first. */
  256.   base = DEC ;               /* Initial base. */
  257.   ttype = DEG ;              /* Initial trigonometric type. */
  258.   down = 0 ;                 /* No mouse presses initially. */
  259.   accuracy = 2 ;             /* Initial accuracy. */
  260.   do_clear() ;               /* Initialise and clear display. */
  261.  
  262.   make_registers() ;         /* Calculate memory register frame values. */
  263.   make_canvas(0) ;           /* Draw the calculators buttons. */
  264.   display_base(base) ;       /* Initial arithmetic base. */
  265.   display_ttype(ttype) ;     /* Initial trigonometric type. */
  266.   start_tool() ;             /* Display the calculator. */
  267.   exit(0) ;
  268. }
  269.  
  270.  
  271. char_val(chr)
  272. char chr ;
  273. {
  274.        if (chr >= '0' && chr <= '9') return(chr - '0') ;
  275.   else if (chr >= 'a' && chr <= 'f') return(chr - 'a' + 10) ;
  276.   else return(-1) ;
  277. }
  278.  
  279.  
  280. clear_display()
  281. {
  282.   int i ;
  283.  
  284.   pointed = 0 ;
  285.   toclear = 1 ;
  286.   STRCPY(display,"0.") ;
  287.   for (i = 0; i < accuracy; i++) STRNCAT(display,"0",1) ;
  288.   display_result(display) ;
  289.   disp_val = 0.0 ;
  290. }
  291.  
  292.  
  293. double
  294. convert_display()    /* Convert input string into a double. */
  295. {
  296.   int i,inum ;
  297.   double val ;
  298.   char *optr ;
  299.  
  300.   val = 0.0 ;
  301.   optr = display ;
  302.   while ((inum = char_val(*optr)) >= 0)
  303.     {
  304.       val = val * basevals[base] + inum ;
  305.       *optr++ ;
  306.     }
  307.       
  308.   if (*optr == '.')
  309.     for (i = 1; (inum = char_val(*++optr)) >= 0; i++)
  310.       val += inum / powers[i][base] ;
  311.   return(val) ;
  312. }
  313.  
  314.  
  315. display_base(base)
  316. int base ;
  317. {
  318.   display_base_item(base_str[base]) ;
  319. }
  320.  
  321.  
  322. display_ttype(ttype)
  323. int ttype ;
  324. {
  325.   display_ttype_item(ttype_str[ttype]) ;
  326. }
  327.  
  328.  
  329. get_label(n)
  330. int n ;
  331. {
  332.   if (tstate)
  333.     switch (buttons[n].value)
  334.         {
  335.           case CTRL('d') : STRCPY(pstr,"^d  ") ;
  336.                            break ;
  337.           case CTRL('g') : STRCPY(pstr,"^g  ") ;
  338.                            break ;
  339.           case '\010'    : STRCPY(pstr,"bsp ") ;
  340.                            break ;
  341.           case CTRL('r') : STRCPY(pstr,"^r  ") ;
  342.                            break ;
  343.           case '\177'    : STRCPY(pstr,"del ") ;
  344.                            break ;
  345.           default        : SPRINTF(pstr,"%c   ",buttons[n].value) ;
  346.         }
  347.   else STRCPY(pstr,buttons[n].str) ;
  348. }
  349.  
  350.  
  351. get_options(argc,argv)        /* Extract command line options. */
  352. int argc ;
  353. char *argv[] ;
  354. {
  355.   STRCPY(helpname,HELPNAME) ;    /* Default help filename. */
  356.   argv++ ;
  357.   argc-- ;
  358.   while (argc > 0)
  359.     {
  360.       switch (argv[0][1])
  361.         {
  362.           case 'h' : argv++ ;
  363.                      argc-- ;
  364.                      STRCPY(helpname,*argv) ;      /* Get new help filename. */
  365.                      break ;
  366.           case 'v' : FPRINTF(stderr,"%s version 2.1.%1d\n",progname,PATCHLEVEL) ;
  367.                      break ;
  368.           case '?' : FPRINTF(stderr,"Usage: %s [-h helpfile] [-v] [-?]\n",progname) ;
  369.                      exit(1) ;
  370.         }
  371.       argc-- ;
  372.       argv++ ;
  373.     }
  374. }
  375.  
  376.  
  377. grey_buttons(base)     /* Grey out numeric buttons depending upon base. */
  378. int base ;
  379. {
  380.   char val ;
  381.   int i,n ;
  382.  
  383.   for (i = 0; i < 16; i++)
  384.     {
  385.       val = digits[i] ;
  386.       for (n = 0; n < TITEMS; n++)
  387.         if (val == buttons[n].value) break ;
  388.       if (i < basevals[base])
  389.         {
  390.           if (i < 10) buttons[n].color = LBLUE ;
  391.           else buttons[n].color = PINK ;
  392.         }
  393.       else buttons[n].color = GREY ;
  394.       draw_button(n) ;
  395.     }
  396. }
  397.  
  398.  
  399. initialise()
  400. {
  401.   error = 0 ;              /* Currently no display error. */
  402.   cur_op = '?' ;           /* No arithmetic operator defined yet. */
  403.   old_cal_value = '?' ;
  404.   result = 0.0 ;           /* No previous result yet. */
  405.   last_input = 0.0 ;
  406. }
  407.  
  408.  
  409. char *
  410. make_number(number)        /* Convert display value to current base. */
  411. double number ;            /* Value to convert. */
  412. {
  413.   char *optr ;
  414.   double val ;
  415.   int cmax ;       /* Maximum number of characters to display. */
  416.   int ndig ;       /* Total number of digits to generate. */
  417.   int ddig ;       /* Number of digits to left of . */
  418.   int dval ;
  419.  
  420.   if (isinf(number) || isnan(number))
  421.     {
  422.       STRCPY(display,"Error") ;
  423.       error = 1 ;
  424.       return(display) ;
  425.     }
  426.  
  427.   cmax = disp_length[base] ;
  428.   optr = display ;
  429.   val = fabs(number) ;
  430.   if (number < 0.0) *optr++ = '-' ;
  431.   val += .5 / powers[accuracy][base] ;
  432.  
  433.   if (val < 1.0)
  434.     {
  435.       ddig = 0 ;
  436.       *optr++ = '0' ;
  437.       cmax-- ;
  438.     }
  439.   else
  440.     {
  441.       for (ddig = 0; val >= 1.0; ddig++)
  442.         val /= powers[1][base] ;
  443.     }
  444.  
  445.   if ((ndig = ddig + accuracy) > cmax)
  446.     {
  447.       if (ddig > cmax)
  448.         {
  449.           STRCPY(display,"Overflow") ;
  450.           error = 1 ;
  451.           return(display) ;
  452.         }
  453.       else
  454.         {
  455.           STRCPY(display,"Reducing precision") ;
  456.           display_result(display) ;
  457.           sleep(1) ;
  458.           bzero(display,MAXLINE) ;
  459.           accuracy = cmax - ddig ;
  460.           if (accuracy < 0) accuracy = 0 ;
  461.           ndig = ddig + accuracy ;
  462.         }
  463.     }
  464.  
  465.   while (ndig-- > 0)
  466.     {
  467.       if (ddig-- == 0) *optr++ = '.' ;
  468.       val *= powers[1][base] ;
  469.       dval = val ;
  470.       *optr++ = digits[dval] ;
  471.       val -= (int) val ;
  472.     }
  473.  *optr++ = '\0' ;
  474.   toclear = 1 ;
  475.   pointed = 0 ;
  476.   return(display) ;
  477. }
  478.  
  479.  
  480. matherr(x)      /* Calctools' math library error-handling routine. */
  481. struct exception *x ;
  482. {
  483.   SPRINTF(display,"Error in %s",x->name) ;
  484.   display_result(display) ;
  485.   error = 1 ;
  486.   return(1) ;
  487. }
  488.  
  489.  
  490. open_helpfile(helpname)     /* Open helpfile if present. */
  491. char *helpname ;
  492. {
  493.   char *getenv(), name[MAXLINE], *paths, *ptr ;
  494.   int i ;
  495.  
  496.   i = 0 ;
  497.   ishelp = 1 ;
  498.   if ((hfd = fopen(helpname,"r")) == NULL)
  499.     {
  500.       paths = getenv("PATH") ;
  501.       if ((ptr = paths) && helpname[0] != '/')
  502.         for (;;)
  503.           if (*ptr == ':' || *ptr == 0)
  504.             {
  505.               if (*ptr == 0) break ;
  506.               name[i++] = '/' ;
  507.               name[i] = 0 ;
  508.               STRCAT(name,helpname) ;
  509.               if ((hfd = fopen(name,"r")) != NULL) return ;
  510.               *ptr++ ;
  511.               i = 0 ;
  512.             }
  513.           else name[i++] = *ptr++ ;
  514.       FPRINTF(stderr,"%s: Help file: %s not found\r\n",progname,helpname) ;
  515.       ishelp = 0 ;
  516.     }
  517. }
  518.  
  519.  
  520. process_item(n)
  521. int n ;
  522. {
  523.   if (n > TITEMS) return ;
  524.  
  525.   current = buttons[n].value ;
  526.   if (current == 'X') current = 'x' ;         /* Reassign "extra" values. */
  527.   if (current == '*') current = 'x' ;
  528.   if (current == '\015') current = '=' ;
  529.   if (current == 'Q') current = 'q' ;
  530.  
  531.   if (error && current != '\177') return ;    /* If error, must clear first. */
  532.  
  533.   if (pending)
  534.     {
  535.       for (n = 0; n < TITEMS; n++)
  536.         if (pending == buttons[n].value) break ;
  537.     }
  538.   switch (buttons[n].opdisp)
  539.     {
  540.       case OP_SET   : display_op_item(buttons[n].str) ;
  541.                       break ;
  542.       case OP_CLEAR : display_op_item("") ;
  543.     }
  544.   (*buttons[n].func)() ;
  545. }
  546.  
  547.  
  548. show_display(val)
  549. double val ;
  550. {
  551.   if (!error)
  552.     {
  553.       STRCPY(display,make_number(val)) ;
  554.       display_result(display) ;
  555.     }
  556. }
  557. Funky_Stuff
  558. len=`wc -c < calctool.c`
  559. if [ $len !=    16468 ] ; then
  560. echo error: calctool.c was $len bytes long, should have been    16468
  561. fi
  562. fi # end of overwriting check
  563. if [ -f functions.c ]
  564. then
  565. echo shar: will not over-write existing file functions.c
  566. else
  567. echo shar: extracting 'functions.c',    15064 characters
  568. cat > functions.c <<'Funky_Stuff'
  569.  
  570. /*  functions.c
  571.  *
  572.  *  This file contains the seperate functions used by calctool,
  573.  *  whenever a calculator button is pressed.
  574.  *
  575.  *  Copyright (c) Rich Burridge - February 1988.
  576.  *                Sun Microsystems, Australia - All rights reserved.
  577.  *
  578.  *  Basic algorithms by Ed Falk, Sun Microsystems, Mountain View.
  579.  *
  580.  *  Includes ideas and code from:
  581.  *                Rich Baughman, Consumer Financial Institute, Newton, MA
  582.  *
  583.  *  Version 2.1.
  584.  *
  585.  *  No responsibility is taken for any errors or inaccuracies inherent
  586.  *  either to the comments or the code of this program, but if
  587.  *  reported to me then an attempt will be made to fix them.
  588.  */
  589.  
  590. #include "calctool.h"
  591. #include "color.h"
  592.  
  593. BOOLEAN ibool() ;
  594. double setbool() ;
  595.  
  596. extern char *make_number() ;
  597. extern double convert_display() ;
  598. extern int signgam ;
  599.  
  600. extern FILE *hfd ;                /* File descriptor for help information. */
  601. extern struct button buttons[] ;  /* Calculator button values. */
  602.  
  603. /* Length of display in characters for each base. */
  604. extern int disp_length[] ;
  605.  
  606. extern double disp_val ;          /* Value of the current display. */
  607. extern double last_input ;        /* Previous number input by user. */
  608. extern double mem_vals[] ;        /* Memory register values. */
  609. extern double result ;            /* Current calculator total value. */
  610. extern double tresults[] ;        /* Current trigonometric results. */
  611.  
  612. extern int accuracy ;             /* Number of digits precision (Max 9). */
  613. extern int base ;                 /* Current base: BIN, OCT, DEC or HEX. */
  614. extern int color ;                /* Color of current raster operation. */
  615. extern int iscolor ;              /* Set if this is a color screen. */
  616. extern int ishelp ;               /* Set if there is a help file. */
  617. extern int new_input ;            /* New number input since last op. */
  618. extern int pending ;              /* Indicates command depending on multiple presses. */
  619. extern int pending_op ;           /* Arithmetic operation for pending command. */
  620. extern int pointed ;              /* Whether a decimal point has been given. */
  621. extern int toclear ;              /* Indicates if display should be cleared. */
  622. extern int ttype ;                /* Current trigonometric type. */
  623.  
  624. extern char cur_op ;              /* Current arithmetic operation. */
  625. extern char current ;             /* Current button or character pressed. */
  626. extern char old_cal_value ;       /* Previous calculation operator. */
  627. extern char display[MAXLINE] ;    /* Current calculator display. */
  628.  
  629.  
  630. do_atrig()
  631. {
  632.   switch (current)
  633.     {
  634.       case ')' : disp_val = acos(disp_val) ;         /* cos-1. */
  635.                  break ;
  636.       case '}' : disp_val = asin(disp_val) ;         /* sin-1. */
  637.                  break ;
  638.       case 'T' : disp_val = atan(disp_val) ;         /* tan-1. */
  639.     }
  640.  
  641.   tresults[DEG]  = disp_val *= 180.0 / M_PI ;
  642.   tresults[GRAD] = disp_val *= 200.0 / M_PI ;
  643.   tresults[RAD]  = disp_val ;
  644.   cur_op = current ;
  645.   show_display(tresults[ttype]) ;
  646. }
  647.  
  648.  
  649. do_base()    /* Change the current base setting. */
  650. {
  651.   switch (current)
  652.     {
  653.       case 'B' : base = BIN ;
  654.                  break ;
  655.       case 'O' : base = OCT ;
  656.                  break ;
  657.       case 'D' : base = DEC ;
  658.                  break ;
  659.       case 'H' : base = HEX ;
  660.     }
  661.   grey_buttons(base) ;
  662.   display_base(base) ;
  663.   show_display(disp_val) ;
  664.   make_registers() ;
  665. }
  666.  
  667.  
  668. do_calculation()      /* Perform arithmetic calculation and display result. */
  669. {
  670.   if (current == '=' && old_cal_value == '=')
  671.     if (new_input) result = last_input ;
  672.     else disp_val = last_input ;
  673.  
  674.   if (current != '=' && old_cal_value == '=') cur_op = '?' ;
  675.   switch (cur_op)
  676.     {
  677.       case '?'    : result = disp_val ;                 /* Undefined. */
  678.                     break ;
  679.       case '+'    : result += disp_val ;                /* Addition. */
  680.                     break ;
  681.       case '-'    : result -= disp_val ;                /* Subtraction. */
  682.                     break ;
  683.       case 'x'    : result *= disp_val ;                /* Multiplication. */
  684.                     break ;
  685.       case '/'    : result /= disp_val ;                /* Division. */
  686.                     break ;
  687.       case '%'    : result *= disp_val * 0.01 ;         /* % */
  688.                     break ;
  689.       case 'Y'    : result = pow(result,disp_val) ;     /* y^x */
  690.                     break ;
  691.       case '&'    : result = setbool(ibool(result) & ibool(disp_val)) ;  /* AND */
  692.                     break ;
  693.       case '|'    : result = setbool(ibool(result) | ibool(disp_val)) ;  /* OR */
  694.                     break ;
  695.       case '^'    : result = setbool(ibool(result) ^ ibool(disp_val)) ;  /* XOR */
  696.                     break ;
  697.       case 'n'    : result = setbool(~(ibool(result) ^ ibool(disp_val))) ;  /* XNOR */
  698.                     break ;
  699.       case '='    : break ;                             /* Equals. */
  700.     }
  701.   show_display(result) ;
  702.   if (!(current == '=' && old_cal_value == '=')) last_input = disp_val ;
  703.  
  704.   disp_val = result ;
  705.   if (current != '=') cur_op = current ;
  706.   old_cal_value = current ;
  707.   new_input = 0 ;
  708. }
  709.  
  710.  
  711. do_clear()       /* Clear the calculator display and re-initialise. */
  712. {
  713.   clear_display() ;
  714.   initialise() ;
  715. }
  716.  
  717.  
  718. do_constant()
  719. {
  720.   switch (current)
  721.     {
  722.       case 'E' : disp_val = M_E ;      /* e. */
  723.                  break ;
  724.       case 'P' : disp_val = M_PI ;     /* PI. */
  725.     }
  726.   show_display(disp_val) ;
  727. }
  728.  
  729.  
  730. do_delete()     /* Remove the last numeric character typed. */
  731. {
  732.   if (strlen(display)) display[strlen(display)-1] = '\0' ;
  733.   display_result(display) ;
  734.   disp_val = convert_display() ;    /* Convert input to a number. */
  735. }
  736.  
  737.  
  738. do_factorial(val)     /* Calculate the factorial of val. */
  739. double val ;
  740. {
  741.   double a ;
  742.   int i ;
  743.  
  744.   if (val == (int) val)
  745.     {
  746.       i = val ;
  747.       a = 1.0 ;
  748.       while ((i > 0) && (a != HUGE)) a *= (float) i-- ;
  749.     }
  750.   else
  751.     {
  752.       a = gamma(val+1) ;
  753.       a = exp(a) ;
  754.       if (signgam) a = -a ;
  755.     }
  756.   return (a) ;
  757. }
  758.  
  759.  
  760. do_immediate()
  761. {
  762.   switch (current)
  763.     {
  764.       case '#' : disp_val = exp(disp_val) ;                     /* e^x */
  765.                  break ;
  766.       case '$' : disp_val = exp(M_LN10*disp_val) ;              /* 10^x */
  767.                  break ;
  768.       case 'N' : disp_val = log(disp_val) ;                     /* ln */
  769.                  break ;
  770.       case 'G' : disp_val = log10(disp_val) ;                   /* log */
  771.                  break ;
  772.       case 'S' : disp_val = sqrt(disp_val) ;                    /* SQRT */
  773.                  break ;
  774.       case 'R' : disp_val = 1.0 / disp_val ;                    /* 1/x */
  775.                  break ;
  776.       case '@' : disp_val *= disp_val ;                         /* x^2 */
  777.                  break ;
  778.       case 'C' : disp_val = -disp_val ;                         /* CHS */
  779.                  break ;
  780.       case 'i' : disp_val = setbool(ibool(disp_val)) ;          /* &32 */
  781.                  break ;
  782.       case 'h' : disp_val = setbool(ibool(disp_val) & 0xffff) ; /* &16 */
  783.                  break ;
  784.       case '!' : disp_val = do_factorial(disp_val) ;            /* x! */
  785.                  break ;
  786.       case '~' : disp_val = setbool(~ibool(disp_val)) ;         /* NOT */
  787.     }
  788.   show_display(disp_val) ;
  789. }
  790.  
  791.  
  792. do_keys()
  793. {
  794.   make_canvas(1) ;
  795. }
  796.  
  797.  
  798. do_nothing()    /* Dummy routine for the two blank keys. */
  799. {
  800. }
  801.  
  802.  
  803. do_number()
  804. {
  805.   int n ;
  806.   static int maxvals[4] = {1, 7, 9, 15} ;
  807.  
  808.   n = current - '0' ;
  809.   if (base == HEX && current >= 'a' && current <= 'f')
  810.     n = current - 'a' + 10 ;
  811.   if (n > maxvals[base]) return ;
  812.  
  813.   if (toclear)
  814.     {
  815.       SPRINTF(display,"%c",current) ;
  816.       toclear = 0 ;
  817.     }
  818.   else if (strlen(display) < disp_length[base])
  819.     STRNCAT(display,¤t,1) ;
  820.   display_result(display) ;
  821.   disp_val = convert_display() ;    /* Convert input to a number. */
  822.   new_input = 1 ;
  823. }
  824.  
  825.  
  826. do_pending()
  827. {
  828.   char help_str[MAXLINE],nextline[MAXLINE],*p ;
  829.   int n,shift,y ;
  830.   BOOLEAN temp ;
  831.  
  832.   switch (pending)
  833.     {
  834.       case 'A' : if (current >= '0' && current <= '9')         /* ACC. */
  835.                    {
  836.                      accuracy = char_val(current) ;
  837.                      make_registers() ;
  838.                    }
  839.                  break ;
  840.       case '?' : if (pending_op == '?')                        /* HELP. */
  841.                    {
  842.                      if (ishelp) ishelp++ ;
  843.                      pending_op = '=' ;
  844.                      make_canvas(0) ;
  845.                      set_cursor(MAINCURSOR) ;
  846.                    }
  847.                  else
  848.                    {
  849.                      clear_canvas(WHITE) ;
  850.                      if (!ishelp) make_text(20,20,"No help file found.") ;
  851.                      else
  852.                        { 
  853.                          for (n = 0; n < TITEMS; n++)
  854.                            if (current == buttons[n].value) break ;
  855.                          color = (iscolor) ? buttons[n].color : WHITE ;
  856.                          clear_canvas(color) ;
  857.                          SPRINTF(help_str,"_%s_\n",buttons[n].str) ;
  858.                          rewind(hfd) ;
  859.                          y = 15 ;
  860.                          p = fgets(nextline,BUFSIZ,hfd) ;
  861.                          if (EQUAL(p,"_calctool.help_\n"))
  862.                            {
  863.                              while (p = fgets(nextline,BUFSIZ,hfd))
  864.                                if (*p == '_' && EQUAL(p,help_str)) break ;
  865.                              if (!p) make_text(5,y,"No help for this item.") ;
  866.                              for (;;)
  867.                                {
  868.                                  FGETS(nextline,BUFSIZ,hfd) ;
  869.                                  if (nextline[0] == '_') break ;
  870.                                  nextline[strlen(nextline)-1] = '\0' ;
  871.                                  make_text(5,y,nextline) ;
  872.                                  y += 15 ;
  873.                                }
  874.                            }
  875.                          else make_text(5,y,"Invalid help file given.") ;
  876.                        }    
  877.                      make_text(5,y+25,"Hit any button or valid key.") ;
  878.                      pending_op = '?' ;
  879.                      return ;
  880.                    }
  881.                  break ;
  882.       case 's' :                                               /* STO. */
  883.       case 'r' : if (current >= '0' && current <= '9')         /* RCL. */
  884.                    {
  885.                      switch (pending)
  886.                        {
  887.                          case 'r' : disp_val = mem_vals[char_val(current)] ;
  888.                                     break ;
  889.                          case 's' : switch (pending_op)
  890.                                       {
  891.                                         case '+' : mem_vals[char_val(current)] += disp_val ;
  892.                                                    break ;
  893.                                         case '-' : mem_vals[char_val(current)] -= disp_val ;
  894.                                                    break ;
  895.                                         case 'x' : mem_vals[char_val(current)] *= disp_val ;
  896.                                                    break ;
  897.                                         case '/' : mem_vals[char_val(current)] /= disp_val ;
  898.                                                    break ;
  899.                                         case '=' : mem_vals[char_val(current)] = disp_val ;
  900.                                       }
  901.                                     make_registers() ;
  902.                        }
  903.                      break ;
  904.                    }
  905.                  else if (current == '+' || current == '-' ||
  906.                           current == 'x' || current == '/')
  907.                    {
  908.                      pending_op = current ;
  909.                      return ;
  910.                    }
  911.                  break ;
  912.       case '<' :
  913.       case '>' : if (current >= '0' && current <= '9')
  914.                    {
  915.                      for (n = 0; n < TITEMS; n++)
  916.                        if (current == buttons[n].value) break ;
  917.                      shift = char_val(buttons[n].value) ;
  918.                      temp = ibool(convert_display()) ;
  919.                      switch (pending)
  920.                        {
  921.                          case '<' : temp = temp << shift ;
  922.                                     break ;
  923.                          case '>' : temp = temp >> shift ;
  924.                        }
  925.                      STRCPY(display,make_number(setbool(temp))) ;
  926.                      disp_val = last_input = convert_display() ;
  927.                    }
  928.                  break ;
  929.       default  : if (!pending)
  930.                    {
  931.                      pending = current ;
  932.                      pending_op = '=' ;
  933.                      if (pending == '?') set_cursor(HELPCURSOR) ;
  934.                      if (pending == '?' && (ishelp == 1)) do_pending() ;
  935.                      return ;
  936.                    }
  937.     }    
  938.   show_display(disp_val) ;
  939.   display_op_item("") ;
  940.   pending = 0 ;
  941. }
  942.  
  943.  
  944. do_point()       /* Handle numeric point. */
  945. {
  946.   if (!pointed)
  947.     {
  948.       if (toclear)
  949.         {
  950.           STRCPY(display,".") ;
  951.           toclear = 0 ;
  952.         }
  953.       else if (strlen(display) < disp_length[base])
  954.         STRNCAT(display,".",1) ;
  955.       pointed = 1 ;
  956.     }
  957.   display_result(display) ;
  958.   disp_val = convert_display() ;    /* Convert input to a number. */
  959. }
  960.  
  961.  
  962. do_portion()
  963. {
  964.   switch (current)
  965.     {
  966.       case 'U' : disp_val = fabs(disp_val) ;       /* ABS. */
  967.                  break ;
  968.       case 'F' : disp_val -= (int) disp_val ;      /* FRAC. */
  969.                  break ;
  970.       case 'I' : disp_val = (int) disp_val ;       /* INT. */
  971.     }
  972.   show_display(disp_val) ;
  973. }
  974.  
  975.  
  976. do_trig()
  977. {
  978.   int i ;
  979.   double temp ;
  980.  
  981.   tresults[DEG]  = disp_val *= M_PI / 180.0 ;
  982.   tresults[GRAD] = disp_val *= M_PI / 200.0 ;
  983.   tresults[RAD]  = disp_val ;
  984.  
  985.   for (i = 0; i < 3; i++)
  986.     switch (current)
  987.       {
  988.         case '(' : tresults[i] = cos(tresults[i]) ;   /* cos. */
  989.                    break ;
  990.         case '{' : tresults[i] = sin(tresults[i]) ;   /* sin. */
  991.                    break ;
  992.         case 't' : temp = cos(tresults[i]) ;          /* tan. */
  993.                    tresults[i] = sin(tresults[i]) / temp ;
  994.       }
  995.   cur_op = current ;
  996.   show_display(tresults[ttype]) ;
  997. }
  998.  
  999.  
  1000. do_trigtype()   /* Change the current trigonometric type. */
  1001. {
  1002.   switch (current)
  1003.     {
  1004.       case CTRL('d') : ttype = DEG ;
  1005.                        break ;
  1006.       case CTRL('g') : ttype = GRAD ;
  1007.                        break ;
  1008.       case CTRL('r') : ttype = RAD ;
  1009.     }
  1010.   if (cur_op == ')' || cur_op == '}' || cur_op == 'T' ||
  1011.       cur_op == '(' || cur_op == '{' || cur_op == 't') show_display(tresults[ttype]) ;
  1012.   display_ttype(ttype) ;
  1013. }
  1014.  
  1015.  
  1016. BOOLEAN
  1017. ibool(x)
  1018. double x ;
  1019. {
  1020.   BOOLEAN p ;
  1021.  
  1022.   if (x > 68719476736.00) return(0) ;
  1023.   else if (x < -68719476736.00) return(0) ;
  1024.        else
  1025.          {
  1026.            while(x < 0.0) x += 4294967296.00 ;
  1027.            while(x > 4294967296.00) x -= 4294967296.00 ;
  1028.            p = x ;
  1029.            return (p) ;
  1030.          }
  1031. }
  1032.  
  1033.  
  1034. double
  1035. setbool(p)
  1036. BOOLEAN p ;
  1037. {
  1038.   BOOLEAN q ;
  1039.   double val ;
  1040.  
  1041.   q = p & 0x80000000 ;
  1042.   p &= 0x7fffffff ;
  1043.   val = p ;
  1044.   if (q) val += 2147483648.0 ;
  1045.   return(val) ;
  1046. }
  1047. Funky_Stuff
  1048. len=`wc -c < functions.c`
  1049. if [ $len !=    15064 ] ; then
  1050. echo error: functions.c was $len bytes long, should have been    15064
  1051. fi
  1052. fi # end of overwriting check
  1053. if [ -f sunview.c ]
  1054. then
  1055. echo shar: will not over-write existing file sunview.c
  1056. else
  1057. echo shar: extracting 'sunview.c',    14588 characters
  1058. cat > sunview.c <<'Funky_Stuff'
  1059.  
  1060. /*  sunview.c
  1061.  *
  1062.  *  These are the SunView independent graphics routines used by the calctool
  1063.  *  calculator program.
  1064.  *
  1065.  *  Copyright (c) Rich Burridge - February 1988.
  1066.  *                Sun Microsystems, Australia - All rights reserved.
  1067.  *
  1068.  *  Basic algorithms by Ed Falk, Sun Microsystems, Mountain View.
  1069.  *
  1070.  *  Includes ideas and code from:
  1071.  *                Rich Baughman, Consumer Finance Institute, Newton, MA.
  1072.  *
  1073.  *  Version 2.1.
  1074.  *
  1075.  *  No responsibility is taken for any errors or inaccuracies inherent
  1076.  *  either to the comments or the code of this program, but if
  1077.  *  reported to me then an attempt will be made to fix them.
  1078.  */
  1079.  
  1080. #include "calctool.h"
  1081. #include "color.h"
  1082. #include <suntool/sunview.h>
  1083. #include <suntool/canvas.h>
  1084. #include <suntool/panel.h>
  1085.  
  1086. #define  ICON_SET           (void) icon_set
  1087. #define  PANEL_SET          (void) panel_set
  1088. #define  PW_SETCMSNAME      (void) pw_setcmsname
  1089. #define  PW_PUTCOLORMAP     (void) pw_putcolormap
  1090. #define  WINDOW_DESTROY     (void) window_destroy
  1091. #define  WINDOW_DONE        (void) window_done
  1092. #define  WINDOW_READ_EVENT  (void) window_read_event
  1093. #define  WINDOW_SET         (void) window_set
  1094.  
  1095. void canvas_proc() ;
  1096. int draw_background() ;
  1097. Panel_setting panel_proc() ;
  1098.  
  1099. Canvas canvas, rcanvas ;
  1100. Cursor main_cursor ;
  1101. Frame frame, rframe ;
  1102. Icon calctool_icon ;
  1103. Panel panel ;
  1104. Panel_item base_item, display_item, op_item, ttype_item ;
  1105. Pixfont *sfont, *nfont, *bfont, *font ;
  1106. Pixwin *cpw, *rcpw ;
  1107.  
  1108. short help_cursor_array[16] = {
  1109. #include "help.cursor"
  1110. } ;
  1111. mpr_static(help_cursor_pr,16,16,1,help_cursor_array) ;
  1112. struct cursor help_cursor =
  1113.          { 0, 0, PIX_SRC | PIX_DST, &help_cursor_pr } ;
  1114.  
  1115. short button_image[] = {
  1116. #include "button.icon"
  1117. } ;
  1118. mpr_static(button_pr,64,64,1,button_image) ;
  1119.  
  1120. short icon_image[] = {
  1121. #include "calctool.icon"
  1122. } ;
  1123. mpr_static(icon_pixrect,64,64,1,icon_image) ;
  1124.  
  1125. extern char *make_number() ;
  1126. extern char pstr[] ;              /* Current button text string. */
  1127. extern double mem_vals[] ;        /* Memory register values. */
  1128. extern int chxoff[] ;             /* X offset for various length button strings. */
  1129. extern int color ;                /* Color being used for current raster operation. */
  1130. extern int column ;               /* Column number of current key/mouse press. */
  1131. extern int down ;                 /* Indicates if mouse button is down. */
  1132. extern int iscolor ;              /* Set if this is a color screen. */
  1133. extern int pending ;              /* Set for command with on multiple presses. */
  1134. extern int pending_op ;           /* Arithmetic operation for pending command. */
  1135. extern int portion ;              /* Portion of button on current key/mouse press. */
  1136. extern int row ;                  /* Row number of current key/mouse press. */
  1137. extern int rstate ;               /* Is memory register frame displayed? */
  1138. extern int spaces ;               /* Number of spaces in current button string. */
  1139. extern int tstate ;               /* Current button set being displayed. */
  1140. extern int x ;                    /* X offset for text for button. */ 
  1141. extern int y ;                    /* Y offset for text for button. */ 
  1142. extern struct button buttons[] ;  /* Calculator button values. */
  1143.  
  1144.  
  1145. /*ARGSUSED*/
  1146. static void
  1147. canvas_proc(win,event,arg)
  1148. Canvas  win ;
  1149. Event *event ;
  1150. caddr_t arg ;
  1151.  
  1152. {
  1153.   int i,n ;
  1154.  
  1155.   x = event_x(event) ;
  1156.   y = event_y(event) ;
  1157.   if (event_is_button(event))
  1158.     {
  1159.       if (event_is_down(event) && !down)
  1160.         {
  1161.           column = x / (BWIDTH + BGAP) ;
  1162.           row = y / (BHEIGHT + BGAP) ;
  1163.           portion = (y - BBORDER - (row * (BHEIGHT + BGAP))) / (BHEIGHT / 2) ;
  1164.           n = row*BCOLS*2 + column*2 + portion ;
  1165.           if (pending_op != '?')
  1166.             {
  1167.               if (!iscolor & portion)
  1168.                 pw_writebackground(cpw,column*(BWIDTH+BGAP)+BBORDER+7,
  1169.                                     row*(BHEIGHT+BGAP)+BBORDER+28,
  1170.                                     30,17,PIX_NOT(PIX_DST)) ;
  1171.               else
  1172.                 {
  1173.                   draw_background(column*(BWIDTH+BGAP)+BBORDER+5,
  1174.                                   row*(BHEIGHT+BGAP)+BBORDER+5+(portion*22),
  1175.                                   34,21,BLACK) ;
  1176.                   n = row*BCOLS*2 + column*2 + portion ;
  1177.                   get_label(n) ;
  1178.                   for (spaces = 0, i = 0; i < strlen(pstr); i++)
  1179.                     if (pstr[i] == ' ') spaces++ ;
  1180.                   if (buttons[n].color != GREY)
  1181.                     {
  1182.                       x = chxoff[spaces] ;
  1183.                       y = (n & 1) ? 40: 18 ;
  1184.                       if (spaces == 3)  y += 4 ;
  1185.                       font = (spaces == 3) ? bfont : nfont ;
  1186.                       color = (iscolor) ? buttons[n].color : WHITE ;
  1187.                       pw_ttext(cpw,column*(BWIDTH+BGAP)+BBORDER+x,
  1188.                                   row*(BHEIGHT+BGAP)+BBORDER+y,
  1189.                                   PIX_SRC | PIX_COLOR(color),font,pstr) ;
  1190.                     }
  1191.                 } 
  1192.             }
  1193.           down = event_id(event) ;
  1194.           return ;
  1195.         }
  1196.       else if (event_is_up(event) && (event_id(event) == down))
  1197.         {
  1198.           n = row*BCOLS*2 + column*2 + portion ;
  1199.           if (pending_op != '?') draw_button(n) ;
  1200.           down = 0 ;
  1201.         }
  1202.     }
  1203.   else if (event_is_ascii(event))
  1204.     {
  1205.       for (n = 0; n < TITEMS; n++)
  1206.         if (event_id(event) == buttons[n].value) break ;
  1207.       if (n == TITEMS) return ;
  1208.     }
  1209.   else if (event_id(event) == KBD_DONE && down)
  1210.     {
  1211.       n = row*BCOLS*2 + column*2 + portion ;
  1212.       if (pending_op != '?') draw_button(n) ;
  1213.       down = 0 ;
  1214.       return ;
  1215.     }
  1216.   else return ;
  1217.      
  1218.   process_item(n) ;
  1219. }        
  1220.          
  1221.  
  1222. clear_canvas(color)
  1223. int color ;
  1224. {
  1225.   int height,width ;
  1226.  
  1227.   height = (int) window_get(canvas, WIN_HEIGHT) ;
  1228.   width = (int) window_get(canvas, WIN_WIDTH) ;
  1229.   pw_writebackground(cpw,0,0,width,height,PIX_SRC | PIX_COLOR(color)) ;
  1230. }
  1231.  
  1232.  
  1233. close_frame()
  1234. {
  1235.   if ((int) window_get(rframe, WIN_SHOW) == TRUE)
  1236.     toggle_reg_canvas() ;
  1237.   WINDOW_SET(frame,FRAME_CLOSED,TRUE,0) ;
  1238. }
  1239.  
  1240.  
  1241. destroy_frame()
  1242. {
  1243.   WINDOW_DONE(frame) ;
  1244. }
  1245.  
  1246.  
  1247. display_base_item(str)
  1248. char *str ;
  1249. {
  1250.   PANEL_SET(base_item,PANEL_LABEL_STRING,str,0) ;
  1251. }
  1252.  
  1253.  
  1254. display_op_item(str)
  1255. char *str ;
  1256. {
  1257.   PANEL_SET(op_item,PANEL_LABEL_STRING,str,0) ;
  1258. }
  1259.  
  1260.  
  1261. display_result(display)       /* Output result to calculator display. */
  1262. char display[MAXLINE] ;
  1263. {
  1264.   PANEL_SET(display_item,PANEL_VALUE_X,5+(MAX_DIGITS - strlen(display))*9,
  1265.                          PANEL_VALUE,display,
  1266.                          0) ;
  1267. }
  1268.  
  1269.  
  1270. display_ttype_item(str)
  1271. char *str ;
  1272. {
  1273.   PANEL_SET(ttype_item,PANEL_LABEL_STRING,str,0) ;
  1274. }
  1275.  
  1276.  
  1277. draw_button(n)
  1278. int n ;
  1279. {
  1280.   int i ;
  1281.  
  1282.   row = n / (BCOLS*2) ;
  1283.   column = (n - (row*BCOLS*2)) / 2 ;
  1284.   get_label(n) ;
  1285.   for (spaces = 0, i = 0; i < strlen(pstr); i++)
  1286.     if (pstr[i] == ' ') spaces++ ;
  1287.  
  1288.   color = (iscolor) ? buttons[n].color : WHITE ;
  1289.   if (!(n & 1))
  1290.     pw_write(cpw,column*(BWIDTH+BGAP)+BBORDER+2,
  1291.                  row*(BHEIGHT+BGAP)+BBORDER+2,
  1292.                  40,24,PIX_SRC | PIX_COLOR(color),(Pixrect *) NULL,0,0) ;
  1293.   else
  1294.     { 
  1295.       color = (iscolor) ? buttons[n-1].color : WHITE ;
  1296.       pw_write(cpw,column*(BWIDTH+BGAP)+BBORDER+2,
  1297.                    row*(BHEIGHT+BGAP)+BBORDER+26,
  1298.                    40,24,PIX_SRC | PIX_COLOR(color),(Pixrect *) NULL,0,0) ;
  1299.       pw_write(cpw,column*(BWIDTH+BGAP)+BBORDER+5,
  1300.                    row*(BHEIGHT+BGAP)+BBORDER+26,
  1301.                    34,21,PIX_SRC,&button_pr,5,26) ;
  1302.       if (iscolor)
  1303.         pw_write(cpw,column*(BWIDTH+BGAP)+BBORDER+7,
  1304.                      row*(BHEIGHT+BGAP)+BBORDER+28,
  1305.                      30,17,PIX_SRC | PIX_COLOR(buttons[n].color),(Pixrect *) NULL,0,0) ;
  1306.     }
  1307.   if (buttons[n].color != GREY)
  1308.     {
  1309.       x = chxoff[spaces] ;
  1310.       y = (n & 1) ? 40: 18 ;
  1311.       if (spaces == 3)  y += 4 ;
  1312.       font = (spaces == 3) ? bfont : nfont ;
  1313.       color = (!iscolor & (n & 1)) ? WHITE : BLACK ;
  1314.       pw_ttext(cpw,column*(BWIDTH+BGAP)+BBORDER+x,
  1315.                    row*(BHEIGHT+BGAP)+BBORDER+y,
  1316.                    PIX_SRC | PIX_COLOR(color),font,pstr) ;
  1317.     }
  1318. }
  1319.  
  1320.  
  1321. draw_background(x,y,width,height,color)
  1322. int x,y,width,height,color ;
  1323. {
  1324.   pw_writebackground(cpw,x,y,width,height,PIX_SRC | PIX_COLOR(color)) ;
  1325. }
  1326.  
  1327.  
  1328. draw_calc()
  1329. {
  1330.   make_canvas(0) ;
  1331. }
  1332.  
  1333.  
  1334. init_fonts()
  1335. {
  1336.   sfont = pf_open(SMALLFONT) ;
  1337.   nfont = pf_open(NORMALFONT) ;
  1338.   bfont = pf_open(BIGFONT) ;
  1339. }
  1340.  
  1341.  
  1342. load_colors()      /* Create and load calctool color map. */
  1343. {
  1344.   char colorname[CMS_NAMESIZE] ;
  1345.   u_char red[CALC_COLORSIZE], green[CALC_COLORSIZE], blue[CALC_COLORSIZE] ;
  1346.  
  1347.   iscolor = (cpw->pw_pixrect->pr_depth == 8) ? 1 : 0 ;
  1348.   SPRINTF(colorname,"%s%D",CALC_COLOR,getpid()) ;
  1349.   PW_SETCMSNAME(cpw,colorname) ;
  1350.  
  1351.   calc_colorsetup(red,green,blue) ;
  1352.   PW_PUTCOLORMAP(cpw,0,CALC_COLORSIZE,red,green,blue) ;
  1353. }
  1354.  
  1355.  
  1356. make_canvas(toggle)           /* Draw the calculators buttons. */
  1357. int toggle ;    /* Indicates if mouse or keyboard images should be shown. */
  1358. {
  1359.   int n ;
  1360.  
  1361.   if (toggle) tstate = !tstate ;
  1362.   color = (iscolor) ? GREY : WHITE ;
  1363.   clear_canvas(color) ;
  1364.   for (row = 0; row < BROWS; row++)
  1365.     for (column = 0; column < BCOLS; column++)
  1366.       for (portion = 0; portion < 2; portion++)
  1367.         {
  1368.           n = row*BCOLS*2 + column*2 + portion ;
  1369.           if (!(n & 1))
  1370.             pw_write(cpw,column*(BWIDTH+BGAP)+BBORDER,
  1371.                          row*(BHEIGHT+BGAP)+BBORDER,
  1372.                          BWIDTH,BHEIGHT,PIX_SRC,&button_pr,0,0) ;
  1373.           draw_button(n) ;
  1374.         }
  1375.   if (rstate) WINDOW_SET(rframe, WIN_SHOW, TRUE, 0) ;
  1376. }
  1377.  
  1378.  
  1379. make_frames(argc,argv)
  1380. int argc ;
  1381. char *argv[] ;
  1382. {
  1383.   frame = window_create((Window) 0, FRAME,
  1384.                         FRAME_ICON, calctool_icon,
  1385.                         FRAME_SHOW_LABEL, FALSE,
  1386.                         FRAME_SUBWINDOWS_ADJUSTABLE, FALSE,
  1387.                         FRAME_NO_CONFIRM, TRUE,
  1388.                         WIN_TOP_MARGIN, DISPLAY,
  1389.                         WIN_ROW_HEIGHT, BHEIGHT,
  1390.                         WIN_COLUMN_WIDTH, BWIDTH,
  1391.                         WIN_ROWS, BROWS,
  1392.                         WIN_COLUMNS, BCOLS,
  1393.                         FRAME_ARGS, argc,argv,
  1394.                         0) ;
  1395.   rframe = window_create(frame, FRAME,
  1396.                          FRAME_SHOW_LABEL, FALSE,
  1397.                          FRAME_NO_CONFIRM, TRUE,
  1398.                          WIN_X, TWIDTH+15,
  1399.                          WIN_Y, DISPLAY+5,
  1400.                          WIN_SHOW, FALSE,
  1401.                          WIN_WIDTH,TWIDTH+60,
  1402.                          WIN_HEIGHT,THEIGHT+10,
  1403.                          WIN_FONT,nfont,
  1404.                          0) ;
  1405.  
  1406. }
  1407.  
  1408.  
  1409. make_icon()
  1410. {
  1411.   calctool_icon = icon_create(ICON_WIDTH,42, ICON_IMAGE, &icon_pixrect, 0) ;
  1412. }
  1413.  
  1414.  
  1415. make_items()
  1416. {
  1417.   display_item = panel_create_item(panel,PANEL_TEXT,
  1418.                                    PANEL_VALUE_Y,DISPLAY-27,
  1419.                                    PANEL_NOTIFY_LEVEL, PANEL_ALL,
  1420.                                    PANEL_ACCEPT_KEYSTROKE, 1,
  1421.                                    PANEL_NOTIFY_PROC, panel_proc,
  1422.                                    PANEL_VALUE_FONT,nfont,
  1423.                                    0) ;
  1424.   base_item = panel_create_item(panel,PANEL_MESSAGE,
  1425.                                 PANEL_LABEL_X,BBORDER,
  1426.                                 PANEL_LABEL_Y,DISPLAY-10,
  1427.                                 PANEL_LABEL_FONT,sfont,
  1428.                                 PANEL_LABEL_STRING,"",
  1429.                                 0) ;
  1430.   ttype_item = panel_create_item(panel,PANEL_MESSAGE,
  1431.                                 PANEL_LABEL_X,BBORDER+(BWIDTH+BGAP),
  1432.                                 PANEL_LABEL_Y,DISPLAY-10,
  1433.                                 PANEL_LABEL_FONT,sfont,
  1434.                                 PANEL_LABEL_STRING,"",
  1435.                                 0) ;
  1436.   op_item = panel_create_item(panel,PANEL_MESSAGE,
  1437.                                 PANEL_LABEL_X,BBORDER+2*(BWIDTH+BGAP),
  1438.                                 PANEL_LABEL_Y,DISPLAY-10,
  1439.                                 PANEL_LABEL_FONT,sfont,
  1440.                                 PANEL_LABEL_STRING,"",
  1441.                                 0) ;
  1442.   cpw = canvas_pixwin(canvas) ;
  1443.   rcpw = canvas_pixwin(rcanvas) ;
  1444.   main_cursor = window_get(canvas,WIN_CURSOR) ;
  1445. }
  1446.  
  1447.  
  1448. make_registers()           /* Calculate memory register frame values. */
  1449.  
  1450. {
  1451.   char line[MAXLINE] ;     /* Current memory register line. */
  1452.   int n ;
  1453.   int height,width ;       /* Dimensions of this frame. */
  1454.  
  1455.   height = (int) window_get(rframe,WIN_HEIGHT) ;
  1456.   width = (int) window_get(rframe,WIN_WIDTH) ;
  1457.   pw_writebackground(rcpw,0,0,width,height,PIX_CLR) ;
  1458.   pw_text(rcpw,15,20,PIX_SRC,nfont,"Memory Registers") ;
  1459.   for (n = 0; n < MAXREGS; n++)
  1460.     {
  1461.       SPRINTF(line,"%1d   ",n) ;
  1462.       STRCAT(line,make_number(mem_vals[n])) ;
  1463.       pw_text(rcpw,15,40+15*n,PIX_SRC,nfont,line) ;
  1464.     }
  1465. }
  1466.  
  1467.  
  1468. make_subframes()
  1469. {
  1470.   panel = window_create(frame, PANEL,
  1471.                         PANEL_BLINK_CARET, 0,
  1472.                         WIN_CONSUME_KBD_EVENTS, WIN_ASCII_EVENTS, 0,
  1473.                         WIN_HEIGHT, DISPLAY,
  1474.                         0) ;
  1475.   rcanvas = window_create(rframe,CANVAS,0) ;
  1476.  
  1477.   canvas = window_create(frame,CANVAS,
  1478.                          CANVAS_RETAINED, FALSE,
  1479.                          CANVAS_REPAINT_PROC, draw_calc,
  1480.                          WIN_BELOW,panel,
  1481.                          WIN_WIDTH,TWIDTH,
  1482.                          WIN_HEIGHT,THEIGHT,
  1483.                          WIN_FONT,nfont,
  1484.                          WIN_EVENT_PROC,canvas_proc,
  1485.                          0) ;
  1486.   WINDOW_SET(canvas,WIN_CONSUME_KBD_EVENT,WIN_ASCII_EVENTS,0) ;
  1487.   WINDOW_SET(canvas,WIN_IGNORE_KBD_EVENTS,WIN_LEFT_KEYS,WIN_TOP_KEYS,WIN_RIGHT_KEYS,0) ;
  1488. }
  1489.  
  1490.  
  1491. make_text(x,y,line)        /* Output a line of text. */
  1492. int x,y ;
  1493. char line[MAXLINE] ;
  1494.  
  1495. {
  1496.   pw_ttext(cpw,x,y,PIX_SRC | PIX_COLOR(BLACK),nfont,line) ;
  1497. }
  1498.  
  1499.  
  1500. /*ARGSUSED*/
  1501. Panel_setting
  1502. panel_proc(item,event)
  1503. Panel_item item ;
  1504. Event *event ;
  1505.                       
  1506. {
  1507.   int chr,n ;
  1508.  
  1509.   chr = event_id(event) ;
  1510.   for (n = 0; n < TITEMS; n++)
  1511.     {
  1512.       if (chr == buttons[n].value)
  1513.         {
  1514.           PANEL_SET(item,PANEL_NOTIFY_LEVEL,PANEL_NONE,0) ;
  1515.           process_item(n) ;
  1516.           PANEL_SET(item,PANEL_NOTIFY_LEVEL,PANEL_ALL,0) ;
  1517.           return ;
  1518.         }
  1519.     }
  1520. }
  1521.  
  1522.  
  1523. set_cursor(type)
  1524. int type ;
  1525. {
  1526.   switch (type)
  1527.     {
  1528.       case HELPCURSOR : WINDOW_SET(canvas,WIN_CURSOR,&help_cursor,0) ;
  1529.                         break ;
  1530.       case MAINCURSOR : WINDOW_SET(canvas,WIN_CURSOR,main_cursor,0) ;
  1531.     }
  1532. }
  1533.  
  1534.  
  1535. start_tool()
  1536. {
  1537.   window_fit(frame) ;
  1538.   window_main_loop(frame) ;
  1539. }
  1540.  
  1541.  
  1542. toggle_reg_canvas()
  1543.  
  1544. {
  1545.   rstate = !rstate ;
  1546.   if (rstate) WINDOW_SET(rframe, WIN_SHOW, TRUE, 0) ;
  1547.   else WINDOW_SET(rframe, WIN_SHOW, FALSE, 0) ;
  1548. }
  1549. Funky_Stuff
  1550. len=`wc -c < sunview.c`
  1551. if [ $len !=    14588 ] ; then
  1552. echo error: sunview.c was $len bytes long, should have been    14588
  1553. fi
  1554. fi # end of overwriting check
  1555.