[comp.sources.misc] Calctool v2.1 - a Sun calculator. Part 1 of 2.

richb@sunaus.sun.oz.AU (02/22/88)

This is V2.1 of a desktop calculator for the Sun workstation.
Currently this version works under SunView, but NeWS and X.11 versions
will be coming soon.

This is a complete rehash from the v1.x series, and now includes
many more mathematical and trigonometrical functions. Memory register
manipulation has been extended, the user interface tidied up and color
is now supported.

See the online help or the manual pages for more details.

Thankyou to everybody who has sent me mail suggesting enhancements.

Thanks to Ed Falk at Sun Microsystems (Mountain View) for some of the
basic algorithms used.

Suggestions for furthur improvement would be most welcome plus bugs,
comments and flames.

    Rich.

Rich Burridge,           JANET richb%sunaus.oz@uk.ac.ucl.cs
ACSnet  richb@sunaus.oz  UUCP {uunet,hplabs,mcvax,ukc}!munnari!sunaus.oz!richb
PHONE: +61 2 436 4699    ARPAnet rburridge@Sun.COM
Sun Microsystems, Unit 2, 49-53 Hotham Pde, Artarmon, N.S.W. 2164, AUSTRALIA.

------CUT HERE------CUT HERE------
#! /bin/sh
# this is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh to create the files:
#   calctool.c
#   functions.c
#   sunview.c
# This archive created: Fri Feb 19 18:59:56 EST 1988
#
#
export PATH; PATH=/bin:$PATH
#
if [ -f calctool.c ]
then
echo shar: will not over-write existing file calctool.c
else
echo shar: extracting 'calctool.c',    16468 characters
cat > calctool.c <<'Funky_Stuff'

/*  calctool.c
 *
 *  This program looks and acts like a simple calculator.
 *
 *  Copyright (c) Rich Burridge - February 1988.
 *                Sun Microsystems, Australia - All rights reserved.
 *
 *  Basic algorithms by Ed Falk, Sun Microsystems, Mountain View.
 *
 *  Includes ideas and code from:
 *                Rich Baughman, Consumer Financial Institute, Newton, MA
 *
 *  Version 2.1.
 *
 *  No responsibility is taken for any errors or inaccuracies inherent
 *  either to the comments or the code of this program, but if
 *  reported to me then an attempt will be made to fix them.
 */

#include "patchlevel.h"
#include "color.h"
#include "calctool.h"

double powers[11][4] = {
         {    1.0,          1.0,           1.0,             1.0 },
         {    2.0,          8.0,          10.0,            16.0 },
         {    4.0,         64.0,         100.0,           256.0 },
         {    8.0,        512.0,        1000.0,          4096.0 },
         {   16.0,       4096.0,       10000.0,         65536.0 },
         {   32.0,      32768.0,      100000.0,       1048576.0 },
         {   64.0,     262144.0,     1000000.0,      16777216.0 },
         {  128.0,    2097152.0,    10000000.0,     268435456.0 },
         {  256.0,   16777216.0,   100000000.0,    4294967296.0 },
         {  512.0,  134217728.0,  1000000000.0,   68719476736.0 },
         { 1024.0, 1073741824.0, 10000000000.0, 1099511627776.0 }
} ;

char base_str[4][4] = { "BIN", "OCT", "DEC", "HEX" } ;
char ttype_str[3][5] = { "DEG", "GRAD", "RAD" } ;

char digits[] = "0123456789abcdef" ;
int basevals[4] = {2, 8, 10, 16} ;

/* Length of display in characters for each base. */
int disp_length[4] = {32, 15, 12, 12} ;

/* X offset in pixels for various length button strings. */
int chxoff[4] = { 5, 9, 14, 16 } ;

double disp_val ;             /* Value of the current display. */
double last_input ;           /* Previous number input by user. */
double mem_vals[MAXREGS] ;    /* Memory register values. */
double result ;               /* Current calculator total value. */
double tresults[3] ;          /* Current trigonometric results. */

FILE *hfd ;         /* File descriptor for help information. */

int accuracy ;      /* Number of digits precision (Max 9). */
int base ;          /* Current base: BIN, OCT, DEC or HEX. */
int color ;         /* Color being used for current raster operation. */
int column ;        /* Column number of current key/mouse press. */
int down ;          /* Indicates is a mouse button is down. */
int error ;         /* Indicates some kind of display error. */
int iscolor ;       /* Set if this is a color screen. */
int ishelp ;        /* Set if there is a help file. */
int new_input ;     /* New number input since last op. */
int pending ;       /* Indicates command depending on multiple presses. */
int pending_op ;    /* Arithmetic operation for pending command. */
int pointed ;       /* Whether a decimal point has been given. */
int portion ;       /* Portion of button on current key/mouse press. */
int row ;           /* Row number of current key/mouse press. */
int rstate ;        /* Indicates if memory register frame is displayed. */
int spaces ;        /* Number of spaces in current button string. */
int toclear ;       /* Indicates if display should be cleared. */
int tstate ;        /* Indicates current button set being displayed. */
int ttype ;         /* Trigonometric type (deg, grad or rad). */
int x ;             /* X offset for text for button. */
int y ;             /* Y offset for text for button. */

/* Routines obeyed by mouse button or character presses. */
int close_frame(),    destroy_frame(),  do_atrig(),     do_base() ;
int do_calculation(), do_clear(),       do_constant(),  do_delete() ;
int do_immediate(),   do_keys(),        do_nothing(),   do_number() ;
int do_pending(),     do_point(),       do_portion(),   do_registers() ;
int do_pending(),     do_trig(),        do_trigtype(),  toggle_reg_canvas() ;

char cur_op ;           /* Current arithmetic operation. */
char current ;          /* Current button or character pressed. */
char old_cal_value ;    /* Previous calculation operator. */
char pstr[5] ;          /* Current button text string. */

struct button buttons[TITEMS] = {              /* Calculator button values. */
  { ">   ", '>',    OP_SET,   LGREY,    do_pending },       /* Row 1. */
  { "<   ", '<',    OP_SET,   LGREY,    do_pending },
  { "BIN ", 'B',    OP_CLEAR, YELLOW,   do_base },
  { "MEM ", 'M',    OP_CLEAR, BLUE,     toggle_reg_canvas },
  { "OCT ", 'O',    OP_CLEAR, YELLOW,   do_base },
  { "D   ", 'd',    OP_NOP,   PINK,     do_number },
  { "DEC ", 'D',    OP_CLEAR, YELLOW,   do_base },
  { "E   ", 'e',    OP_NOP,   PINK,     do_number }, 
  { "HEX ", 'H',    OP_CLEAR, YELLOW,   do_base },
  { "F   ", 'f',    OP_NOP,   PINK,     do_number },  
  { "KEYS", 'K',    OP_CLEAR, BLUE,     do_keys },
  { "?   ", '?',    OP_SET,   BLUE,     do_pending },  

  { "&32 ", 'i',    OP_CLEAR, LGREY,    do_immediate },      /* Row 2. */
  { "STO ", 's',    OP_SET,   MAUVE,    do_pending },
  { "&16 ", 'h',    OP_CLEAR, LGREY,    do_immediate },
  { "RCL ", 'r',    OP_SET,   MAUVE,    do_pending }, 
  { "PI  ", 'P',    OP_CLEAR, ORANGE,   do_constant },
  { "A   ", 'a',    OP_NOP,   PINK,     do_number }, 
  { "e   ", 'E',    OP_CLEAR, ORANGE,   do_constant },
  { "B   ", 'b',    OP_NOP,   PINK,     do_number },
  { "%   ", '%',    OP_SET,   LPURPLE,  do_calculation },
  { "C   ", 'c',    OP_NOP,   PINK,     do_number },
  { "clr ", '\177', OP_CLEAR, BLUE,     do_clear },
  { "bsp ", '\010', OP_NOP,   BLUE,     do_delete },

  { "OR  ", '|',    OP_SET,   GREEN,    do_calculation },   /* Row 3. */
  { "AND ", '&',    OP_SET,   GREEN,    do_calculation },
  { "ASIN", '}',    OP_CLEAR, LGREEN,   do_atrig },
  { "SIN ", '{',    OP_CLEAR, LGREEN,   do_trig },
  { "e^x ", '#',    OP_CLEAR, ORANGE,   do_immediate },
  { "7   ", '7',    OP_NOP,   LBLUE,    do_number },
  { "10^x", '$',    OP_CLEAR, ORANGE,   do_immediate },
  { "8   ", '8',    OP_NOP,   LBLUE,    do_number },
  { "y^x ", 'Y',    OP_SET,   ORANGE,   do_calculation },
  { "9   ", '9',    OP_NOP,   LBLUE,    do_number }, 
  { "INT ", 'I',    OP_CLEAR, LGREY,    do_portion },
  { "X   ", 'x',    OP_SET,   LPURPLE,  do_calculation },

  { "XNOR", 'n',    OP_SET,   GREEN,    do_calculation },   /* Row 4. */
  { "XOR ", '^',    OP_SET,   GREEN,    do_calculation },
  { "ACOS", ')',    OP_CLEAR, LGREEN,   do_atrig },
  { "COS ", '(',    OP_CLEAR, LGREEN,   do_trig },
  { "ln  ", 'N',    OP_CLEAR, ORANGE,   do_immediate },
  { "4   ", '4',    OP_NOP,   LBLUE,    do_number },
  { "log ", 'G',    OP_CLEAR, ORANGE,   do_immediate },
  { "5   ", '5',    OP_NOP,   LBLUE,    do_number },
  { "SQRT", 'S',    OP_CLEAR, ORANGE,   do_immediate },
  { "6   ", '6',    OP_NOP,   LBLUE,    do_number },
  { "FRAC", 'F',    OP_CLEAR, LGREY,    do_portion },
  { "/   ", '/',    OP_SET,   LPURPLE,  do_calculation },

  { "NOT ", '~',    OP_CLEAR, GREEN,    do_immediate },     /* Row 5. */
  { "ACC ", 'A',    OP_SET,   BLUE,     do_pending },
  { "ATAN", 'T',    OP_CLEAR, LGREEN,   do_atrig },
  { "TAN ", 't',    OP_CLEAR, LGREEN,   do_trig },
  { "1/x ", 'R',    OP_CLEAR, ORANGE,   do_immediate },
  { "1   ", '1',    OP_NOP,   LBLUE,    do_number },
  { "x!  ", '!',    OP_CLEAR, ORANGE,   do_immediate },
  { "2   ", '2',    OP_NOP,   LBLUE,    do_number },
  { "x^2 ", '@',    OP_CLEAR, ORANGE,   do_immediate },
  { "3   ", '3',    OP_NOP,   LBLUE,    do_number },
  { "CHS ", 'C',    OP_CLEAR, LGREY,    do_immediate },
  { "-   ", '-',    OP_SET,   LPURPLE,  do_calculation },

  { "QUIT", 'q',    OP_CLEAR, BLUE,     destroy_frame },    /* Row 6. */
  { "OFF ", 'o',    OP_CLEAR, BLUE,     close_frame },
  { "    ", ' ',    OP_CLEAR, GREY,     do_nothing },
  { "    ", ' ',    OP_CLEAR, GREY,     do_nothing },
  { "DEG ", '\004', OP_CLEAR, RED,      do_trigtype },
  { "0   ", '0',    OP_NOP,   LBLUE,    do_number },
  { "RAD ", '\022', OP_CLEAR, RED,      do_trigtype },
  { ".   ", '.',    OP_NOP,   LPURPLE,  do_point },
  { "GRAD", '\007', OP_CLEAR, RED,      do_trigtype },
  { "=   ", '=',    OP_CLEAR, LPURPLE,  do_calculation },
  { "ABS ", 'U',    OP_CLEAR, LGREY,    do_portion },
  { "+   ", '+',    OP_SET,   LPURPLE,  do_calculation },

  { "    ", 'X',    OP_NOP,   WHITE,    do_calculation },   /* Extra definitions. */
  { "    ", '*',    OP_NOP,   WHITE,    do_calculation },
  { "    ", '\015', OP_NOP,   WHITE,    do_calculation },
  { "    ", 'Q',    OP_NOP,   WHITE,    destroy_frame },
} ;

char display[MAXLINE] ;     /* Current calculator display. */
char helpname[MAXLINE] ;    /* Filename for help file. */
char progname[MAXLINE] ;    /* Name of this program. */


main(argc,argv)
int argc ;
char *argv[] ;
{
  STRCPY(progname,argv[0]) ; /* Save this programs name. */
  get_options(argc,argv) ;   /* Get command line arguments. */
  open_helpfile(helpname) ;  /* Open helpfile if present. */
  make_icon() ;              /* Set up the calctool window icon. */
  init_fonts() ;             /* Open required fonts. */
  make_frames(argc,argv) ;   /* Create calctool window frames. */
  make_subframes() ;         /* Create panels and canvases. */
  make_items() ;             /* Create panel items and cursors. */
  load_colors() ;            /* Load the initial calctool colormap. */

  pending = 0 ;              /* No initial pending command. */
  rstate = 0 ;               /* No memory register frame display initially. */
  tstate = 0 ;               /* Button values displayed first. */
  base = DEC ;               /* Initial base. */
  ttype = DEG ;              /* Initial trigonometric type. */
  down = 0 ;                 /* No mouse presses initially. */
  accuracy = 2 ;             /* Initial accuracy. */
  do_clear() ;               /* Initialise and clear display. */

  make_registers() ;         /* Calculate memory register frame values. */
  make_canvas(0) ;           /* Draw the calculators buttons. */
  display_base(base) ;       /* Initial arithmetic base. */
  display_ttype(ttype) ;     /* Initial trigonometric type. */
  start_tool() ;             /* Display the calculator. */
  exit(0) ;
}


char_val(chr)
char chr ;
{
       if (chr >= '0' && chr <= '9') return(chr - '0') ;
  else if (chr >= 'a' && chr <= 'f') return(chr - 'a' + 10) ;
  else return(-1) ;
}


clear_display()
{
  int i ;

  pointed = 0 ;
  toclear = 1 ;
  STRCPY(display,"0.") ;
  for (i = 0; i < accuracy; i++) STRNCAT(display,"0",1) ;
  display_result(display) ;
  disp_val = 0.0 ;
}


double
convert_display()    /* Convert input string into a double. */
{
  int i,inum ;
  double val ;
  char *optr ;

  val = 0.0 ;
  optr = display ;
  while ((inum = char_val(*optr)) >= 0)
    {
      val = val * basevals[base] + inum ;
      *optr++ ;
    }
      
  if (*optr == '.')
    for (i = 1; (inum = char_val(*++optr)) >= 0; i++)
      val += inum / powers[i][base] ;
  return(val) ;
}
 
 
display_base(base)
int base ;
{
  display_base_item(base_str[base]) ;
}


display_ttype(ttype)
int ttype ;
{
  display_ttype_item(ttype_str[ttype]) ;
}


get_label(n)
int n ;
{
  if (tstate)
    switch (buttons[n].value)
        {
          case CTRL('d') : STRCPY(pstr,"^d  ") ;
                           break ;
          case CTRL('g') : STRCPY(pstr,"^g  ") ;
                           break ;
          case '\010'    : STRCPY(pstr,"bsp ") ;
                           break ;
          case CTRL('r') : STRCPY(pstr,"^r  ") ;
                           break ;
          case '\177'    : STRCPY(pstr,"del ") ;
                           break ;
          default        : SPRINTF(pstr,"%c   ",buttons[n].value) ;
        }
  else STRCPY(pstr,buttons[n].str) ;
}


get_options(argc,argv)        /* Extract command line options. */
int argc ;
char *argv[] ;
{
  STRCPY(helpname,HELPNAME) ;    /* Default help filename. */
  argv++ ;
  argc-- ;
  while (argc > 0)
    {
      switch (argv[0][1])
        {
          case 'h' : argv++ ;
                     argc-- ;
                     STRCPY(helpname,*argv) ;      /* Get new help filename. */
                     break ;
          case 'v' : FPRINTF(stderr,"%s version 2.1.%1d\n",progname,PATCHLEVEL) ;
                     break ;
          case '?' : FPRINTF(stderr,"Usage: %s [-h helpfile] [-v] [-?]\n",progname) ;
                     exit(1) ;
        }
      argc-- ;
      argv++ ;
    }
}


grey_buttons(base)     /* Grey out numeric buttons depending upon base. */
int base ;
{
  char val ;
  int i,n ;

  for (i = 0; i < 16; i++)
    {
      val = digits[i] ;
      for (n = 0; n < TITEMS; n++)
        if (val == buttons[n].value) break ;
      if (i < basevals[base])
        {
          if (i < 10) buttons[n].color = LBLUE ;
          else buttons[n].color = PINK ;
        }
      else buttons[n].color = GREY ;
      draw_button(n) ;
    }
}


initialise()
{
  error = 0 ;              /* Currently no display error. */
  cur_op = '?' ;           /* No arithmetic operator defined yet. */
  old_cal_value = '?' ;
  result = 0.0 ;           /* No previous result yet. */
  last_input = 0.0 ;
}


char *
make_number(number)        /* Convert display value to current base. */
double number ;            /* Value to convert. */
{
  char *optr ;
  double val ;
  int cmax ;       /* Maximum number of characters to display. */
  int ndig ;       /* Total number of digits to generate. */
  int ddig ;       /* Number of digits to left of . */
  int dval ;

  if (isinf(number) || isnan(number))
    {
      STRCPY(display,"Error") ;
      error = 1 ;
      return(display) ;
    }

  cmax = disp_length[base] ;
  optr = display ;
  val = fabs(number) ;
  if (number < 0.0) *optr++ = '-' ;
  val += .5 / powers[accuracy][base] ;

  if (val < 1.0)
    {
      ddig = 0 ;
      *optr++ = '0' ;
      cmax-- ;
    }
  else
    {
      for (ddig = 0; val >= 1.0; ddig++)
        val /= powers[1][base] ;
    }

  if ((ndig = ddig + accuracy) > cmax)
    {
      if (ddig > cmax)
        {
          STRCPY(display,"Overflow") ;
          error = 1 ;
          return(display) ;
        }
      else
        {
          STRCPY(display,"Reducing precision") ;
          display_result(display) ;
          sleep(1) ;
          bzero(display,MAXLINE) ;
          accuracy = cmax - ddig ;
          if (accuracy < 0) accuracy = 0 ;
          ndig = ddig + accuracy ;
        }
    }

  while (ndig-- > 0)
    {
      if (ddig-- == 0) *optr++ = '.' ;
      val *= powers[1][base] ;
      dval = val ;
      *optr++ = digits[dval] ;
      val -= (int) val ;
    }
 *optr++ = '\0' ;
  toclear = 1 ;
  pointed = 0 ;
  return(display) ;
}


matherr(x)      /* Calctools' math library error-handling routine. */
struct exception *x ;
{
  SPRINTF(display,"Error in %s",x->name) ;
  display_result(display) ;
  error = 1 ;
  return(1) ;
}


open_helpfile(helpname)     /* Open helpfile if present. */
char *helpname ;
{
  char *getenv(), name[MAXLINE], *paths, *ptr ;
  int i ;

  i = 0 ;
  ishelp = 1 ;
  if ((hfd = fopen(helpname,"r")) == NULL)
    {
      paths = getenv("PATH") ;
      if ((ptr = paths) && helpname[0] != '/')
        for (;;)
          if (*ptr == ':' || *ptr == 0)
            {
              if (*ptr == 0) break ;
              name[i++] = '/' ;
              name[i] = 0 ;
              STRCAT(name,helpname) ;
              if ((hfd = fopen(name,"r")) != NULL) return ;
              *ptr++ ;
              i = 0 ;
            }
          else name[i++] = *ptr++ ;
      FPRINTF(stderr,"%s: Help file: %s not found\r\n",progname,helpname) ;
      ishelp = 0 ;
    }
}


process_item(n)
int n ;
{
  if (n > TITEMS) return ;

  current = buttons[n].value ;
  if (current == 'X') current = 'x' ;         /* Reassign "extra" values. */
  if (current == '*') current = 'x' ;
  if (current == '\015') current = '=' ;
  if (current == 'Q') current = 'q' ;

  if (error && current != '\177') return ;    /* If error, must clear first. */

  if (pending)
    {
      for (n = 0; n < TITEMS; n++)
        if (pending == buttons[n].value) break ;
    }
  switch (buttons[n].opdisp)
    {
      case OP_SET   : display_op_item(buttons[n].str) ;
                      break ;
      case OP_CLEAR : display_op_item("") ;
    }
  (*buttons[n].func)() ;
}


show_display(val)
double val ;
{
  if (!error)
    {
      STRCPY(display,make_number(val)) ;
      display_result(display) ;
    }
}
Funky_Stuff
len=`wc -c < calctool.c`
if [ $len !=    16468 ] ; then
echo error: calctool.c was $len bytes long, should have been    16468
fi
fi # end of overwriting check
if [ -f functions.c ]
then
echo shar: will not over-write existing file functions.c
else
echo shar: extracting 'functions.c',    15064 characters
cat > functions.c <<'Funky_Stuff'

/*  functions.c
 *
 *  This file contains the seperate functions used by calctool,
 *  whenever a calculator button is pressed.
 *
 *  Copyright (c) Rich Burridge - February 1988.
 *                Sun Microsystems, Australia - All rights reserved.
 *
 *  Basic algorithms by Ed Falk, Sun Microsystems, Mountain View.
 *
 *  Includes ideas and code from:
 *                Rich Baughman, Consumer Financial Institute, Newton, MA
 *
 *  Version 2.1.
 *
 *  No responsibility is taken for any errors or inaccuracies inherent
 *  either to the comments or the code of this program, but if
 *  reported to me then an attempt will be made to fix them.
 */

#include "calctool.h"
#include "color.h"

BOOLEAN ibool() ;
double setbool() ;

extern char *make_number() ;
extern double convert_display() ;
extern int signgam ;

extern FILE *hfd ;                /* File descriptor for help information. */
extern struct button buttons[] ;  /* Calculator button values. */

/* Length of display in characters for each base. */
extern int disp_length[] ;

extern double disp_val ;          /* Value of the current display. */
extern double last_input ;        /* Previous number input by user. */
extern double mem_vals[] ;        /* Memory register values. */
extern double result ;            /* Current calculator total value. */
extern double tresults[] ;        /* Current trigonometric results. */

extern int accuracy ;             /* Number of digits precision (Max 9). */
extern int base ;                 /* Current base: BIN, OCT, DEC or HEX. */
extern int color ;                /* Color of current raster operation. */
extern int iscolor ;              /* Set if this is a color screen. */
extern int ishelp ;               /* Set if there is a help file. */
extern int new_input ;            /* New number input since last op. */
extern int pending ;              /* Indicates command depending on multiple presses. */
extern int pending_op ;           /* Arithmetic operation for pending command. */
extern int pointed ;              /* Whether a decimal point has been given. */
extern int toclear ;              /* Indicates if display should be cleared. */
extern int ttype ;                /* Current trigonometric type. */

extern char cur_op ;              /* Current arithmetic operation. */
extern char current ;             /* Current button or character pressed. */
extern char old_cal_value ;       /* Previous calculation operator. */
extern char display[MAXLINE] ;    /* Current calculator display. */


do_atrig()
{
  switch (current)
    {
      case ')' : disp_val = acos(disp_val) ;         /* cos-1. */
                 break ;
      case '}' : disp_val = asin(disp_val) ;         /* sin-1. */
                 break ;
      case 'T' : disp_val = atan(disp_val) ;         /* tan-1. */
    }

  tresults[DEG]  = disp_val *= 180.0 / M_PI ;
  tresults[GRAD] = disp_val *= 200.0 / M_PI ;
  tresults[RAD]  = disp_val ;
  cur_op = current ;
  show_display(tresults[ttype]) ;
}


do_base()    /* Change the current base setting. */
{
  switch (current)
    {
      case 'B' : base = BIN ;
                 break ;
      case 'O' : base = OCT ;
                 break ;
      case 'D' : base = DEC ;
                 break ;
      case 'H' : base = HEX ;
    }
  grey_buttons(base) ;
  display_base(base) ;
  show_display(disp_val) ;
  make_registers() ;
}


do_calculation()      /* Perform arithmetic calculation and display result. */
{
  if (current == '=' && old_cal_value == '=')
    if (new_input) result = last_input ;
    else disp_val = last_input ;

  if (current != '=' && old_cal_value == '=') cur_op = '?' ;
  switch (cur_op)
    {
      case '?'    : result = disp_val ;                 /* Undefined. */
                    break ;
      case '+'    : result += disp_val ;                /* Addition. */
                    break ;
      case '-'    : result -= disp_val ;                /* Subtraction. */
                    break ;
      case 'x'    : result *= disp_val ;                /* Multiplication. */
                    break ;
      case '/'    : result /= disp_val ;                /* Division. */
                    break ;
      case '%'    : result *= disp_val * 0.01 ;         /* % */
                    break ;
      case 'Y'    : result = pow(result,disp_val) ;     /* y^x */
                    break ;
      case '&'    : result = setbool(ibool(result) & ibool(disp_val)) ;  /* AND */
                    break ;
      case '|'    : result = setbool(ibool(result) | ibool(disp_val)) ;  /* OR */
                    break ;
      case '^'    : result = setbool(ibool(result) ^ ibool(disp_val)) ;  /* XOR */
                    break ;
      case 'n'    : result = setbool(~(ibool(result) ^ ibool(disp_val))) ;  /* XNOR */
                    break ;
      case '='    : break ;                             /* Equals. */
    }
  show_display(result) ;
  if (!(current == '=' && old_cal_value == '=')) last_input = disp_val ;

  disp_val = result ;
  if (current != '=') cur_op = current ;
  old_cal_value = current ;
  new_input = 0 ;
}


do_clear()       /* Clear the calculator display and re-initialise. */
{
  clear_display() ;
  initialise() ;
}


do_constant()
{
  switch (current)
    {
      case 'E' : disp_val = M_E ;      /* e. */
                 break ;
      case 'P' : disp_val = M_PI ;     /* PI. */
    }
  show_display(disp_val) ;
}


do_delete()     /* Remove the last numeric character typed. */
{
  if (strlen(display)) display[strlen(display)-1] = '\0' ;
  display_result(display) ;
  disp_val = convert_display() ;    /* Convert input to a number. */
}


do_factorial(val)     /* Calculate the factorial of val. */
double val ;
{
  double a ;
  int i ;

  if (val == (int) val)
    {
      i = val ;
      a = 1.0 ;
      while ((i > 0) && (a != HUGE)) a *= (float) i-- ;
    }
  else
    {
      a = gamma(val+1) ;
      a = exp(a) ;
      if (signgam) a = -a ;
    }
  return (a) ;
}


do_immediate()
{
  switch (current)
    {
      case '#' : disp_val = exp(disp_val) ;                     /* e^x */
                 break ;
      case '$' : disp_val = exp(M_LN10*disp_val) ;              /* 10^x */
                 break ;
      case 'N' : disp_val = log(disp_val) ;                     /* ln */
                 break ;
      case 'G' : disp_val = log10(disp_val) ;                   /* log */
                 break ;
      case 'S' : disp_val = sqrt(disp_val) ;                    /* SQRT */
                 break ;
      case 'R' : disp_val = 1.0 / disp_val ;                    /* 1/x */
                 break ;
      case '@' : disp_val *= disp_val ;                         /* x^2 */
                 break ;
      case 'C' : disp_val = -disp_val ;                         /* CHS */
                 break ;
      case 'i' : disp_val = setbool(ibool(disp_val)) ;          /* &32 */
                 break ;
      case 'h' : disp_val = setbool(ibool(disp_val) & 0xffff) ; /* &16 */
                 break ;
      case '!' : disp_val = do_factorial(disp_val) ;            /* x! */
                 break ;
      case '~' : disp_val = setbool(~ibool(disp_val)) ;         /* NOT */
    }
  show_display(disp_val) ;
}


do_keys()
{
  make_canvas(1) ;
}


do_nothing()    /* Dummy routine for the two blank keys. */
{
}


do_number()
{
  int n ;
  static int maxvals[4] = {1, 7, 9, 15} ;

  n = current - '0' ;
  if (base == HEX && current >= 'a' && current <= 'f')
    n = current - 'a' + 10 ;
  if (n > maxvals[base]) return ;

  if (toclear)
    {
      SPRINTF(display,"%c",current) ;
      toclear = 0 ;
    }
  else if (strlen(display) < disp_length[base])
    STRNCAT(display,&current,1) ;
  display_result(display) ;
  disp_val = convert_display() ;    /* Convert input to a number. */
  new_input = 1 ;
}


do_pending()
{
  char help_str[MAXLINE],nextline[MAXLINE],*p ;
  int n,shift,y ;
  BOOLEAN temp ;

  switch (pending)
    {
      case 'A' : if (current >= '0' && current <= '9')         /* ACC. */
                   {
                     accuracy = char_val(current) ;
                     make_registers() ;
                   }
                 break ;
      case '?' : if (pending_op == '?')                        /* HELP. */
                   {
                     if (ishelp) ishelp++ ;
                     pending_op = '=' ;
                     make_canvas(0) ;
                     set_cursor(MAINCURSOR) ;
                   }
                 else
                   {
                     clear_canvas(WHITE) ;
                     if (!ishelp) make_text(20,20,"No help file found.") ;
                     else
                       { 
                         for (n = 0; n < TITEMS; n++)
                           if (current == buttons[n].value) break ;
                         color = (iscolor) ? buttons[n].color : WHITE ;
                         clear_canvas(color) ;
                         SPRINTF(help_str,"_%s_\n",buttons[n].str) ;
                         rewind(hfd) ;
                         y = 15 ;
                         p = fgets(nextline,BUFSIZ,hfd) ;
                         if (EQUAL(p,"_calctool.help_\n"))
                           {
                             while (p = fgets(nextline,BUFSIZ,hfd))
                               if (*p == '_' && EQUAL(p,help_str)) break ;
                             if (!p) make_text(5,y,"No help for this item.") ;
                             for (;;)
                               {
                                 FGETS(nextline,BUFSIZ,hfd) ;
                                 if (nextline[0] == '_') break ;
                                 nextline[strlen(nextline)-1] = '\0' ;
                                 make_text(5,y,nextline) ;
                                 y += 15 ;
                               }
                           }
                         else make_text(5,y,"Invalid help file given.") ;
                       }    
                     make_text(5,y+25,"Hit any button or valid key.") ;
                     pending_op = '?' ;
                     return ;
                   }
                 break ;
      case 's' :                                               /* STO. */
      case 'r' : if (current >= '0' && current <= '9')         /* RCL. */
                   {
                     switch (pending)
                       {
                         case 'r' : disp_val = mem_vals[char_val(current)] ;
                                    break ;
                         case 's' : switch (pending_op)
                                      {
                                        case '+' : mem_vals[char_val(current)] += disp_val ;
                                                   break ;
                                        case '-' : mem_vals[char_val(current)] -= disp_val ;
                                                   break ;
                                        case 'x' : mem_vals[char_val(current)] *= disp_val ;
                                                   break ;
                                        case '/' : mem_vals[char_val(current)] /= disp_val ;
                                                   break ;
                                        case '=' : mem_vals[char_val(current)] = disp_val ;
                                      }
                                    make_registers() ;
                       }
                     break ;
                   }
                 else if (current == '+' || current == '-' ||
                          current == 'x' || current == '/')
                   {
                     pending_op = current ;
                     return ;
                   }
                 break ;
      case '<' :
      case '>' : if (current >= '0' && current <= '9')
                   {
                     for (n = 0; n < TITEMS; n++)
                       if (current == buttons[n].value) break ;
                     shift = char_val(buttons[n].value) ;
                     temp = ibool(convert_display()) ;
                     switch (pending)
                       {
                         case '<' : temp = temp << shift ;
                                    break ;
                         case '>' : temp = temp >> shift ;
                       }
                     STRCPY(display,make_number(setbool(temp))) ;
                     disp_val = last_input = convert_display() ;
                   }
                 break ;
      default  : if (!pending)
                   {
                     pending = current ;
                     pending_op = '=' ;
                     if (pending == '?') set_cursor(HELPCURSOR) ;
                     if (pending == '?' && (ishelp == 1)) do_pending() ;
                     return ;
                   }
    }    
  show_display(disp_val) ;
  display_op_item("") ;
  pending = 0 ;
}


do_point()       /* Handle numeric point. */
{
  if (!pointed)
    {
      if (toclear)
        {
          STRCPY(display,".") ;
          toclear = 0 ;
        }
      else if (strlen(display) < disp_length[base])
        STRNCAT(display,".",1) ;
      pointed = 1 ;
    }
  display_result(display) ;
  disp_val = convert_display() ;    /* Convert input to a number. */
}


do_portion()
{
  switch (current)
    {
      case 'U' : disp_val = fabs(disp_val) ;       /* ABS. */
                 break ;
      case 'F' : disp_val -= (int) disp_val ;      /* FRAC. */
                 break ;
      case 'I' : disp_val = (int) disp_val ;       /* INT. */
    }
  show_display(disp_val) ;
}


do_trig()
{
  int i ;
  double temp ;

  tresults[DEG]  = disp_val *= M_PI / 180.0 ;
  tresults[GRAD] = disp_val *= M_PI / 200.0 ;
  tresults[RAD]  = disp_val ;

  for (i = 0; i < 3; i++)
    switch (current)
      {
        case '(' : tresults[i] = cos(tresults[i]) ;   /* cos. */
                   break ;
        case '{' : tresults[i] = sin(tresults[i]) ;   /* sin. */
                   break ;
        case 't' : temp = cos(tresults[i]) ;          /* tan. */
                   tresults[i] = sin(tresults[i]) / temp ;
      }
  cur_op = current ;
  show_display(tresults[ttype]) ;
}


do_trigtype()   /* Change the current trigonometric type. */
{
  switch (current)
    {
      case CTRL('d') : ttype = DEG ;
                       break ;
      case CTRL('g') : ttype = GRAD ;
                       break ;
      case CTRL('r') : ttype = RAD ;
    }
  if (cur_op == ')' || cur_op == '}' || cur_op == 'T' ||
      cur_op == '(' || cur_op == '{' || cur_op == 't') show_display(tresults[ttype]) ;
  display_ttype(ttype) ;
}


BOOLEAN
ibool(x)
double x ;
{
  BOOLEAN p ;
 
  if (x > 68719476736.00) return(0) ;
  else if (x < -68719476736.00) return(0) ;
       else
         {
           while(x < 0.0) x += 4294967296.00 ;
           while(x > 4294967296.00) x -= 4294967296.00 ;
           p = x ;
           return (p) ;
         }
}


double
setbool(p)
BOOLEAN p ;
{
  BOOLEAN q ;
  double val ;

  q = p & 0x80000000 ;
  p &= 0x7fffffff ;
  val = p ;
  if (q) val += 2147483648.0 ;
  return(val) ;
}
Funky_Stuff
len=`wc -c < functions.c`
if [ $len !=    15064 ] ; then
echo error: functions.c was $len bytes long, should have been    15064
fi
fi # end of overwriting check
if [ -f sunview.c ]
then
echo shar: will not over-write existing file sunview.c
else
echo shar: extracting 'sunview.c',    14588 characters
cat > sunview.c <<'Funky_Stuff'

/*  sunview.c
 *
 *  These are the SunView independent graphics routines used by the calctool
 *  calculator program.
 *
 *  Copyright (c) Rich Burridge - February 1988.
 *                Sun Microsystems, Australia - All rights reserved.
 *
 *  Basic algorithms by Ed Falk, Sun Microsystems, Mountain View.
 *
 *  Includes ideas and code from:
 *                Rich Baughman, Consumer Finance Institute, Newton, MA.
 *
 *  Version 2.1.
 *
 *  No responsibility is taken for any errors or inaccuracies inherent
 *  either to the comments or the code of this program, but if
 *  reported to me then an attempt will be made to fix them.
 */

#include "calctool.h"
#include "color.h"
#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include <suntool/panel.h>

#define  ICON_SET           (void) icon_set
#define  PANEL_SET          (void) panel_set
#define  PW_SETCMSNAME      (void) pw_setcmsname
#define  PW_PUTCOLORMAP     (void) pw_putcolormap
#define  WINDOW_DESTROY     (void) window_destroy
#define  WINDOW_DONE        (void) window_done
#define  WINDOW_READ_EVENT  (void) window_read_event
#define  WINDOW_SET         (void) window_set

void canvas_proc() ;
int draw_background() ;
Panel_setting panel_proc() ;

Canvas canvas, rcanvas ;
Cursor main_cursor ;
Frame frame, rframe ;
Icon calctool_icon ;
Panel panel ;
Panel_item base_item, display_item, op_item, ttype_item ;
Pixfont *sfont, *nfont, *bfont, *font ;
Pixwin *cpw, *rcpw ;

short help_cursor_array[16] = {
#include "help.cursor"
} ;
mpr_static(help_cursor_pr,16,16,1,help_cursor_array) ;
struct cursor help_cursor =
         { 0, 0, PIX_SRC | PIX_DST, &help_cursor_pr } ;

short button_image[] = {
#include "button.icon"
} ;
mpr_static(button_pr,64,64,1,button_image) ;

short icon_image[] = {
#include "calctool.icon"
} ;
mpr_static(icon_pixrect,64,64,1,icon_image) ;

extern char *make_number() ;
extern char pstr[] ;              /* Current button text string. */
extern double mem_vals[] ;        /* Memory register values. */
extern int chxoff[] ;             /* X offset for various length button strings. */
extern int color ;                /* Color being used for current raster operation. */
extern int column ;               /* Column number of current key/mouse press. */
extern int down ;                 /* Indicates if mouse button is down. */
extern int iscolor ;              /* Set if this is a color screen. */
extern int pending ;              /* Set for command with on multiple presses. */
extern int pending_op ;           /* Arithmetic operation for pending command. */
extern int portion ;              /* Portion of button on current key/mouse press. */
extern int row ;                  /* Row number of current key/mouse press. */
extern int rstate ;               /* Is memory register frame displayed? */
extern int spaces ;               /* Number of spaces in current button string. */
extern int tstate ;               /* Current button set being displayed. */
extern int x ;                    /* X offset for text for button. */ 
extern int y ;                    /* Y offset for text for button. */ 
extern struct button buttons[] ;  /* Calculator button values. */


/*ARGSUSED*/
static void
canvas_proc(win,event,arg)
Canvas  win ;
Event *event ;
caddr_t arg ;
 
{
  int i,n ;
 
  x = event_x(event) ;
  y = event_y(event) ;
  if (event_is_button(event))
    {
      if (event_is_down(event) && !down)
        {
          column = x / (BWIDTH + BGAP) ;
          row = y / (BHEIGHT + BGAP) ;
          portion = (y - BBORDER - (row * (BHEIGHT + BGAP))) / (BHEIGHT / 2) ;
          n = row*BCOLS*2 + column*2 + portion ;
          if (pending_op != '?')
            {
              if (!iscolor & portion)
                pw_writebackground(cpw,column*(BWIDTH+BGAP)+BBORDER+7,
                                    row*(BHEIGHT+BGAP)+BBORDER+28,
                                    30,17,PIX_NOT(PIX_DST)) ;
              else
                {
                  draw_background(column*(BWIDTH+BGAP)+BBORDER+5,
                                  row*(BHEIGHT+BGAP)+BBORDER+5+(portion*22),
                                  34,21,BLACK) ;
                  n = row*BCOLS*2 + column*2 + portion ;
                  get_label(n) ;
                  for (spaces = 0, i = 0; i < strlen(pstr); i++)
                    if (pstr[i] == ' ') spaces++ ;
                  if (buttons[n].color != GREY)
                    {
                      x = chxoff[spaces] ;
                      y = (n & 1) ? 40: 18 ;
                      if (spaces == 3)  y += 4 ;
                      font = (spaces == 3) ? bfont : nfont ;
                      color = (iscolor) ? buttons[n].color : WHITE ;
                      pw_ttext(cpw,column*(BWIDTH+BGAP)+BBORDER+x,
                                  row*(BHEIGHT+BGAP)+BBORDER+y,
                                  PIX_SRC | PIX_COLOR(color),font,pstr) ;
                    }
                } 
            }
          down = event_id(event) ;
          return ;
        }
      else if (event_is_up(event) && (event_id(event) == down))
        {
          n = row*BCOLS*2 + column*2 + portion ;
          if (pending_op != '?') draw_button(n) ;
          down = 0 ;
        }
    }
  else if (event_is_ascii(event))
    {
      for (n = 0; n < TITEMS; n++)
        if (event_id(event) == buttons[n].value) break ;
      if (n == TITEMS) return ;
    }
  else if (event_id(event) == KBD_DONE && down)
    {
      n = row*BCOLS*2 + column*2 + portion ;
      if (pending_op != '?') draw_button(n) ;
      down = 0 ;
      return ;
    }
  else return ;
     
  process_item(n) ;
}        
         

clear_canvas(color)
int color ;
{
  int height,width ;

  height = (int) window_get(canvas, WIN_HEIGHT) ;
  width = (int) window_get(canvas, WIN_WIDTH) ;
  pw_writebackground(cpw,0,0,width,height,PIX_SRC | PIX_COLOR(color)) ;
}


close_frame()
{
  if ((int) window_get(rframe, WIN_SHOW) == TRUE)
    toggle_reg_canvas() ;
  WINDOW_SET(frame,FRAME_CLOSED,TRUE,0) ;
}


destroy_frame()
{
  WINDOW_DONE(frame) ;
}


display_base_item(str)
char *str ;
{
  PANEL_SET(base_item,PANEL_LABEL_STRING,str,0) ;
}
 
 
display_op_item(str)
char *str ;
{
  PANEL_SET(op_item,PANEL_LABEL_STRING,str,0) ;
}


display_result(display)       /* Output result to calculator display. */
char display[MAXLINE] ;
{
  PANEL_SET(display_item,PANEL_VALUE_X,5+(MAX_DIGITS - strlen(display))*9,
                         PANEL_VALUE,display,
                         0) ;
}
 

display_ttype_item(str)
char *str ;
{
  PANEL_SET(ttype_item,PANEL_LABEL_STRING,str,0) ;
}


draw_button(n)
int n ;
{
  int i ;

  row = n / (BCOLS*2) ;
  column = (n - (row*BCOLS*2)) / 2 ;
  get_label(n) ;
  for (spaces = 0, i = 0; i < strlen(pstr); i++)
    if (pstr[i] == ' ') spaces++ ;

  color = (iscolor) ? buttons[n].color : WHITE ;
  if (!(n & 1))
    pw_write(cpw,column*(BWIDTH+BGAP)+BBORDER+2,
                 row*(BHEIGHT+BGAP)+BBORDER+2,
                 40,24,PIX_SRC | PIX_COLOR(color),(Pixrect *) NULL,0,0) ;
  else
    { 
      color = (iscolor) ? buttons[n-1].color : WHITE ;
      pw_write(cpw,column*(BWIDTH+BGAP)+BBORDER+2,
                   row*(BHEIGHT+BGAP)+BBORDER+26,
                   40,24,PIX_SRC | PIX_COLOR(color),(Pixrect *) NULL,0,0) ;
      pw_write(cpw,column*(BWIDTH+BGAP)+BBORDER+5,
                   row*(BHEIGHT+BGAP)+BBORDER+26,
                   34,21,PIX_SRC,&button_pr,5,26) ;
      if (iscolor)
        pw_write(cpw,column*(BWIDTH+BGAP)+BBORDER+7,
                     row*(BHEIGHT+BGAP)+BBORDER+28,
                     30,17,PIX_SRC | PIX_COLOR(buttons[n].color),(Pixrect *) NULL,0,0) ;
    }
  if (buttons[n].color != GREY)
    {
      x = chxoff[spaces] ;
      y = (n & 1) ? 40: 18 ;
      if (spaces == 3)  y += 4 ;
      font = (spaces == 3) ? bfont : nfont ;
      color = (!iscolor & (n & 1)) ? WHITE : BLACK ;
      pw_ttext(cpw,column*(BWIDTH+BGAP)+BBORDER+x,
                   row*(BHEIGHT+BGAP)+BBORDER+y,
                   PIX_SRC | PIX_COLOR(color),font,pstr) ;
    }
}


draw_background(x,y,width,height,color)
int x,y,width,height,color ;
{
  pw_writebackground(cpw,x,y,width,height,PIX_SRC | PIX_COLOR(color)) ;
}


draw_calc()
{
  make_canvas(0) ;
}


init_fonts()
{
  sfont = pf_open(SMALLFONT) ;
  nfont = pf_open(NORMALFONT) ;
  bfont = pf_open(BIGFONT) ;
}


load_colors()      /* Create and load calctool color map. */
{
  char colorname[CMS_NAMESIZE] ;
  u_char red[CALC_COLORSIZE], green[CALC_COLORSIZE], blue[CALC_COLORSIZE] ;

  iscolor = (cpw->pw_pixrect->pr_depth == 8) ? 1 : 0 ;
  SPRINTF(colorname,"%s%D",CALC_COLOR,getpid()) ;
  PW_SETCMSNAME(cpw,colorname) ;

  calc_colorsetup(red,green,blue) ;
  PW_PUTCOLORMAP(cpw,0,CALC_COLORSIZE,red,green,blue) ;
}


make_canvas(toggle)           /* Draw the calculators buttons. */
int toggle ;    /* Indicates if mouse or keyboard images should be shown. */
{
  int n ;

  if (toggle) tstate = !tstate ;
  color = (iscolor) ? GREY : WHITE ;
  clear_canvas(color) ;
  for (row = 0; row < BROWS; row++)
    for (column = 0; column < BCOLS; column++)
      for (portion = 0; portion < 2; portion++)
        {
          n = row*BCOLS*2 + column*2 + portion ;
          if (!(n & 1))
            pw_write(cpw,column*(BWIDTH+BGAP)+BBORDER,
                         row*(BHEIGHT+BGAP)+BBORDER,
                         BWIDTH,BHEIGHT,PIX_SRC,&button_pr,0,0) ;
          draw_button(n) ;
        }
  if (rstate) WINDOW_SET(rframe, WIN_SHOW, TRUE, 0) ;
}


make_frames(argc,argv)
int argc ;
char *argv[] ;
{
  frame = window_create((Window) 0, FRAME,
                        FRAME_ICON, calctool_icon,
                        FRAME_SHOW_LABEL, FALSE,
                        FRAME_SUBWINDOWS_ADJUSTABLE, FALSE,
                        FRAME_NO_CONFIRM, TRUE,
                        WIN_TOP_MARGIN, DISPLAY,
                        WIN_ROW_HEIGHT, BHEIGHT,
                        WIN_COLUMN_WIDTH, BWIDTH,
                        WIN_ROWS, BROWS,
                        WIN_COLUMNS, BCOLS,
                        FRAME_ARGS, argc,argv,
                        0) ;
  rframe = window_create(frame, FRAME,
                         FRAME_SHOW_LABEL, FALSE,
                         FRAME_NO_CONFIRM, TRUE,
                         WIN_X, TWIDTH+15,
                         WIN_Y, DISPLAY+5,
                         WIN_SHOW, FALSE,
                         WIN_WIDTH,TWIDTH+60,
                         WIN_HEIGHT,THEIGHT+10,
                         WIN_FONT,nfont,
                         0) ;
 
}


make_icon()
{
  calctool_icon = icon_create(ICON_WIDTH,42, ICON_IMAGE, &icon_pixrect, 0) ;
}


make_items()
{
  display_item = panel_create_item(panel,PANEL_TEXT,
                                   PANEL_VALUE_Y,DISPLAY-27,
                                   PANEL_NOTIFY_LEVEL, PANEL_ALL,
                                   PANEL_ACCEPT_KEYSTROKE, 1,
                                   PANEL_NOTIFY_PROC, panel_proc,
                                   PANEL_VALUE_FONT,nfont,
                                   0) ;
  base_item = panel_create_item(panel,PANEL_MESSAGE,
                                PANEL_LABEL_X,BBORDER,
                                PANEL_LABEL_Y,DISPLAY-10,
                                PANEL_LABEL_FONT,sfont,
                                PANEL_LABEL_STRING,"",
                                0) ;
  ttype_item = panel_create_item(panel,PANEL_MESSAGE,
                                PANEL_LABEL_X,BBORDER+(BWIDTH+BGAP),
                                PANEL_LABEL_Y,DISPLAY-10,
                                PANEL_LABEL_FONT,sfont,
                                PANEL_LABEL_STRING,"",
                                0) ;
  op_item = panel_create_item(panel,PANEL_MESSAGE,
                                PANEL_LABEL_X,BBORDER+2*(BWIDTH+BGAP),
                                PANEL_LABEL_Y,DISPLAY-10,
                                PANEL_LABEL_FONT,sfont,
                                PANEL_LABEL_STRING,"",
                                0) ;
  cpw = canvas_pixwin(canvas) ;
  rcpw = canvas_pixwin(rcanvas) ;
  main_cursor = window_get(canvas,WIN_CURSOR) ;
}


make_registers()           /* Calculate memory register frame values. */

{
  char line[MAXLINE] ;     /* Current memory register line. */
  int n ;
  int height,width ;       /* Dimensions of this frame. */

  height = (int) window_get(rframe,WIN_HEIGHT) ;
  width = (int) window_get(rframe,WIN_WIDTH) ;
  pw_writebackground(rcpw,0,0,width,height,PIX_CLR) ;
  pw_text(rcpw,15,20,PIX_SRC,nfont,"Memory Registers") ;
  for (n = 0; n < MAXREGS; n++)
    {
      SPRINTF(line,"%1d   ",n) ;
      STRCAT(line,make_number(mem_vals[n])) ;
      pw_text(rcpw,15,40+15*n,PIX_SRC,nfont,line) ;
    }
}


make_subframes()
{
  panel = window_create(frame, PANEL,
                        PANEL_BLINK_CARET, 0,
                        WIN_CONSUME_KBD_EVENTS, WIN_ASCII_EVENTS, 0,
                        WIN_HEIGHT, DISPLAY,
                        0) ;
  rcanvas = window_create(rframe,CANVAS,0) ;

  canvas = window_create(frame,CANVAS,
                         CANVAS_RETAINED, FALSE,
                         CANVAS_REPAINT_PROC, draw_calc,
                         WIN_BELOW,panel,
                         WIN_WIDTH,TWIDTH,
                         WIN_HEIGHT,THEIGHT,
                         WIN_FONT,nfont,
                         WIN_EVENT_PROC,canvas_proc,
                         0) ;
  WINDOW_SET(canvas,WIN_CONSUME_KBD_EVENT,WIN_ASCII_EVENTS,0) ;
  WINDOW_SET(canvas,WIN_IGNORE_KBD_EVENTS,WIN_LEFT_KEYS,WIN_TOP_KEYS,WIN_RIGHT_KEYS,0) ;
}


make_text(x,y,line)        /* Output a line of text. */
int x,y ;
char line[MAXLINE] ;

{
  pw_ttext(cpw,x,y,PIX_SRC | PIX_COLOR(BLACK),nfont,line) ;
}


/*ARGSUSED*/
Panel_setting
panel_proc(item,event)
Panel_item item ;
Event *event ;
                      
{
  int chr,n ;
 
  chr = event_id(event) ;
  for (n = 0; n < TITEMS; n++)
    {
      if (chr == buttons[n].value)
        {
          PANEL_SET(item,PANEL_NOTIFY_LEVEL,PANEL_NONE,0) ;
          process_item(n) ;
          PANEL_SET(item,PANEL_NOTIFY_LEVEL,PANEL_ALL,0) ;
          return ;
        }
    }
}
 
 
set_cursor(type)
int type ;
{
  switch (type)
    {
      case HELPCURSOR : WINDOW_SET(canvas,WIN_CURSOR,&help_cursor,0) ;
                        break ;
      case MAINCURSOR : WINDOW_SET(canvas,WIN_CURSOR,main_cursor,0) ;
    }
}


start_tool()
{
  window_fit(frame) ;
  window_main_loop(frame) ;
}


toggle_reg_canvas()

{
  rstate = !rstate ;
  if (rstate) WINDOW_SET(rframe, WIN_SHOW, TRUE, 0) ;
  else WINDOW_SET(rframe, WIN_SHOW, FALSE, 0) ;
}
Funky_Stuff
len=`wc -c < sunview.c`
if [ $len !=    14588 ] ; then
echo error: sunview.c was $len bytes long, should have been    14588
fi
fi # end of overwriting check