[comp.windows.news] Calctool v2.2 Part 1 of 2.

richb@sunaus.oz (Rich Burridge) (05/04/88)

This is the latest release of calctool, a desktop calculator.
No new features, just an additional graphics interface for NeWS as well as
SunView. It has been sent to Sun-Spots for archiving purposes; it has also
been sent here for people to try this on other NeWS implementations besides
the one from Sun Microsystems.

This is my very first NeWS program and I suspect the NeWS code is pathetic.
I'd very much appreciate any suggestions for improvements with this. I have
two immediate questions for NeWS programmers out there:

(1) The calctool icon should only be 42 pixels wide. What is the
    coding sequence to stop it adopting a 1:1 ratio with the height?
(2) How can I easily construct and set a cursor image from an image file as
    opposed to one of the default cursor types?
 
All bugs and suggestions to me please. This has been tested under SunOS v3.5,
SunOS v4.0(beta)1 using NeWS v1.1.

To compile the SunView version, type "make sunview"; to compile the NeWS
version, type "make news".

    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
#	graphics.c
#	news.c
#	sunview.c
# This archive created: Wed May  4 15:36:15 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',    17040 characters
cat > calctool.c <<'Funky_Stuff'

/*  calctool.c
 *
 *  A calculator program for use with the NeWS and SunView graphics packages.
 *
 *  Copyright (c) Rich Burridge - May 1988.
 *                Sun Microsystems, Australia - All rights reserved.
 *
 *  Basic algorithms by Ed Falk, Sun Microsystems, Mountain View.
 *
 *  Version 2.2.
 *
 *  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 } ;

/* Valid keys when an error condition has occured. */
/*                            MEM  KEYS HELP   clr   QUIT OFF  */
char validkeys[MAXVALID]  = { 'M', 'K', '?', '\177', 'q', 'o' } ;

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. */

enum base_type base ;         /* Current base: BIN, OCT, DEC or HEX. */
enum trig_type ttype ;        /* Trigonometric type (deg, grad or rad). */

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

int accuracy ;      /* Number of digits precision (Max 9). */
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 issel ;         /* Set if valid [Get] selection. */
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 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. */
char *selection ;        /* Current [Get] selection. */

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. */
  if (init_ws_type())        /* Determine window system type. */
    {
      FPRINTF(stderr,"Error initialising window system.\n") ;
      exit(1) ;
    }
  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. */
  load_colors() ;            /* Load the initial calctool colormap. */
  make_items() ;             /* Create panel items and cursors. */

  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. */
  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) ;
  set_item(DISPLAYITEM,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[(int) base] + inum ;
      *optr++ ;
    }
      
  if (*optr == '.')
    for (i = 1; (inum = char_val(*++optr)) >= 0; i++)
      val += inum / powers[i][(int) base] ;
  return(val) ;
}
 
 
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.2.%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. */
enum base_type base ;
{
  char val ;
  int column,i,n,portion,row ;

  for (i = 0; i < 16; i++)
    {
      val = digits[i] ;
      for (n = 0; n < TITEMS; n++)
        if (val == buttons[n].value) break ;
      if (i < basevals[(int) base])
        {
          if (i < 10) buttons[n].color = LBLUE ;
          else buttons[n].color = PINK ;
        }
      else buttons[n].color = GREY ;
      row = n / (BCOLS*2) ;
      column = (n - (row*BCOLS*2)) / 2 ;
      portion = n & 1 ;
      draw_button(row,column,portion,NORMAL) ;
    }
}


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 ;
      set_item(OPITEM,"CLR") ;
      return(display) ;
    }

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

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

  if ((ndig = ddig + accuracy) > cmax)
    {
      if (ddig > cmax)
        {
          STRCPY(display,"Overflow") ;
          error = 1 ;
          set_item(OPITEM,"CLR") ;
          return(display) ;
        }
      else
        {
          STRCPY(display,"Reducing precision") ;
          set_item(DISPLAYITEM,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][(int) 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) ;
  set_item(DISPLAYITEM,display) ;
  error = 1 ;
  set_item(OPITEM,"CLR") ;
  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 ;
{
  int i,isvalid ;

  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)
    {
      isvalid = 0 ;                    /* Must press a valid key first. */
      for (i = 0; i < MAXVALID; i++)
        if (current == validkeys[i]) isvalid = 1 ;
      if (pending == '?') isvalid = 1 ;
      if (!isvalid) return ;
      error = 0 ;
    }

  if (pending)
    {
      for (n = 0; n < TITEMS; n++)
        if (pending == buttons[n].value) break ;
    }
  switch (buttons[n].opdisp)
    {
      case (int) OP_SET   : set_item(OPITEM,buttons[n].str) ;
                            break ;
      case (int) OP_CLEAR : if (error) set_item(OPITEM,"CLR") ;
                            else set_item(OPITEM,"") ;
    }
  (*buttons[n].func)() ;
}


show_display(val)
double val ;
{
  if (!error)
    {
      STRCPY(display,make_number(val)) ;
      set_item(DISPLAYITEM,display) ;
    }
}
Funky_Stuff
len=`wc -c < calctool.c`
if [ $len !=    17040 ] ; then
echo error: calctool.c was $len bytes long, should have been    17040
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',    14074 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 - May 1988.
 *                Sun Microsystems, Australia - All rights reserved.
 *
 *  Basic algorithms by Ed Falk, Sun Microsystems, Mountain View.
 *
 *  Version 2.2.
 *
 *  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 "extern.h"

BOOLEAN ibool() ;
double setbool() ;


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[(int) DEG]  = disp_val * 180.0 / M_PI ;
  tresults[(int) GRAD] = disp_val * 200.0 / M_PI ;
  tresults[(int) RAD]  = disp_val ;
  cur_op = current ;
  show_display(tresults[(int) ttype]) ;
  disp_val = tresults[(int) 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) ;
  set_item(BASEITEM,base_str[(int) 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 ')'    :                                     /* cos-1. */
      case '}'    :                                     /* sin-1. */
      case 'T'    :                                     /* tan-1. */
      case '('    :                                     /* cos. */
      case '{'    :                                     /* sin. */
      case 't'    :                                     /* tan. */
      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() ;
  if (error) set_item(DISPLAYITEM,"") ;
  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' ;
  set_item(DISPLAYITEM,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[(int) base]) return ;

  if (toclear)
    {
      SPRINTF(display,"%c",current) ;
      toclear = 0 ;
    }
  else if (strlen(display) < disp_length[(int) base])
    STRNCAT(display,&current,1) ;
  set_item(DISPLAYITEM,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(KEYCANVAS,WHITE) ;
                     y = 20 ;
                     if (!ishelp) text(20,y,KEYCANVAS,NFONT,BLACK,"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(KEYCANVAS,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) text(5,y,KEYCANVAS,NFONT,BLACK,"No help for this item.") ;
                             for (;;)
                               {
                                 FGETS(nextline,BUFSIZ,hfd) ;
                                 if (nextline[0] == '_') break ;
                                 nextline[strlen(nextline)-1] = '\0' ;
                                 text(5,y,KEYCANVAS,NFONT,BLACK,nextline) ;
                                 y += 15 ;
                               }
                           }
                         else text(5,y,KEYCANVAS,NFONT,BLACK,"Invalid help file given.") ;
                       }    
                     text(5,y+25,KEYCANVAS,NFONT,BLACK,"Click LEFT or press any 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) ;
  if (error) set_item(OPITEM,"CLR") ;
  else set_item(OPITEM,"") ;
  pending = 0 ;
}


do_point()       /* Handle numeric point. */
{
  if (!pointed)
    {
      if (toclear)
        {
          STRCPY(display,".") ;
          toclear = 0 ;
        }
      else if (strlen(display) < disp_length[(int) base])
        STRNCAT(display,".",1) ;
      pointed = 1 ;
    }
  set_item(DISPLAYITEM,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()
{
  double temp ;

       if (ttype == DEG)  temp = disp_val * M_PI / 180.0 ;
  else if (ttype == GRAD) temp = disp_val * M_PI / 200.0 ;
  else                    temp = disp_val ;

  switch (current)
    {
      case '(' : tresults[(int) RAD] = cos(temp) ;   /* cos. */
                 break ;
      case '{' : tresults[(int) RAD] = sin(temp) ;   /* sin. */
                 break ;
      case 't' : tresults[(int) RAD] = tan(temp) ;   /* tan. */
    }
  tresults[(int) DEG]  = tresults[(int) RAD] ;
  tresults[(int) GRAD] = tresults[(int) RAD] ;

  cur_op = current ;
  show_display(tresults[(int) ttype]) ;
  disp_val = tresults[(int) 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')
    {
      disp_val = tresults[(int) ttype] ;
      show_display(tresults[(int) ttype]) ;
    }
  set_item(TTYPEITEM,ttype_str[(int) 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 !=    14074 ] ; then
echo error: functions.c was $len bytes long, should have been    14074
fi
fi # end of overwriting check
if [ -f graphics.c ]
then
echo shar: will not over-write existing file graphics.c
else
echo shar: extracting 'graphics.c',     3745 characters
cat > graphics.c <<'Funky_Stuff'

/*  graphics.c
 *
 *  These are the independent graphics routines used by calctool.
 *
 *  Copyright (c) Rich Burridge - May 1988.
 *                Sun Microsystems, Australia - All rights reserved.
 *
 *  Version 2.2.
 *
 *  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 "extern.h"


but_text(row,column,portion,state)
int row,column,portion ;
enum but_state state ;
{
  enum font_type butfont ;
  int i,n ;

  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 ;
      butfont = (spaces == 3) ? BFONT : NFONT ;
      if (state == NORMAL)
        color = (!iscolor & portion) ? WHITE : BLACK ;
      if (state == INVERTED)
        color = (portion) ? BLACK : WHITE ;
      text(column*(BWIDTH+BGAP)+BBORDER+x,
           row*(BHEIGHT+BGAP)+BBORDER+y,KEYCANVAS,butfont,color,pstr) ;
    }
}


draw_button(row,column,portion,state)
int row,column,portion ;
enum but_state state ;
{
  int n ;

  n = row*BCOLS*2 + column*2 + portion ;
  if (!portion)
    {
      color = (iscolor) ? buttons[n].color : WHITE ;
      drawbox(column*(BWIDTH+BGAP)+BBORDER,
              row*(BHEIGHT+BGAP)+BBORDER,BWIDTH,BHEIGHT) ;
      fillbox(column*(BWIDTH+BGAP)+BBORDER+1,
              row*(BHEIGHT+BGAP)+BBORDER+1,KEYCANVAS,42,50,1,color) ;
    }
  else
    { 
      drawbox(column*(BWIDTH+BGAP)+BBORDER+5,
              row*(BHEIGHT+BGAP)+BBORDER+26,34,21) ;
      color = (iscolor) ? buttons[n].color : BLACK ;
      fillbox(column*(BWIDTH+BGAP)+BBORDER+6,
              row*(BHEIGHT+BGAP)+BBORDER+27,KEYCANVAS,32,19,1,color) ;
    }
  but_text(row,column,portion,state) ;
}


handle_down_event(type)
int type ;
{
  int n ;
 
  getxy(&x,&y) ;
  if (!down)
    {
      column = (x - BBORDER) / (BWIDTH + BGAP) ;
      row = (y - BGAP) / (BHEIGHT + BGAP) ;
      portion = (y - BBORDER - (row * (BHEIGHT + BGAP))) / (BHEIGHT / 2) ;
      n = row*BCOLS*2 + column*2 + portion ;
      if (pending_op != '?' && n <= (NOBUTTONS*2))
        inv_but(row,column,portion,INVERTED) ;
      down = type ;
    }
}


inv_but(row,column,portion,state)
int row,column,portion ;
enum but_state state ;
{
  int n ;
 
  n = row*BCOLS*2 + column*2 + portion ;
  if (pending_op != '?')
    {
      if (state == NORMAL)
        if (iscolor) color = buttons[n].color ;
        else color = (portion) ? BLACK : WHITE ;
      if (state == INVERTED)
        color = (portion) ? WHITE : BLACK ;
      fillbox(column*(BWIDTH+BGAP)+BBORDER+6,
              row*(BHEIGHT+BGAP)+BBORDER+5+(portion*22),
              KEYCANVAS,32,19,portion,color) ;
      but_text(row,column,portion,state) ;
    }
}


make_canvas(toggle)
int toggle ;
{
  if (toggle) tstate = !tstate ;
  color = (iscolor) ? GREY : WHITE ;
  clear_canvas(KEYCANVAS,color) ;
  for (row = 0; row < BROWS; row++)
    for (column = 0; column < BCOLS; column++)
      for (portion = 0; portion < 2; portion++)
        draw_button(row,column,portion,NORMAL) ;

  if (rstate) draw_regs() ;
}


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

{
  char line[MAXLINE] ;     /* Current memory register line. */
  int n ;

  clear_canvas(REGCANVAS,WHITE) ;
  text(15,20,REGCANVAS,NFONT,BLACK,"Memory Registers") ;
  for (n = 0; n < MAXREGS; n++)
    {
      SPRINTF(line,"%1d   ",n) ;
      STRCAT(line,make_number(mem_vals[n])) ;
      text(15,40+15*n,REGCANVAS,NFONT,BLACK,line) ;
    }
}
Funky_Stuff
len=`wc -c < graphics.c`
if [ $len !=     3745 ] ; then
echo error: graphics.c was $len bytes long, should have been     3745
fi
fi # end of overwriting check
if [ -f news.c ]
then
echo shar: will not over-write existing file news.c
else
echo shar: extracting 'news.c',     7511 characters
cat > news.c <<'Funky_Stuff'

/*  news.c
 *
 *  These are the NeWS dependent graphics routines used by calctool.
 *
 *  Copyright (c) Rich Burridge - May 1988.
 *                Sun Microsystems, Australia - All rights reserved.
 *
 *  Version 2.2.
 *
 *  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 "extern.h"
#include <sys/types.h>

/* Various event used by the NeWS interface. */
#define  CFRAME_REPAINT_EVENT  100    /* Main frame needs repainting. */
#define  RFRAME_REPAINT_EVENT  101    /* Register frame needs repainting. */
#define  LEFT_DOWN_EVENT       102    /* Left mouse button was depressed. */
#define  LEFT_UP_EVENT         103    /* Left mouse button was debounced. */
#define  MIDDLE_DOWN_EVENT     104    /* Middle mouse button was depressed. */
#define  MIDDLE_UP_EVENT       105    /* Middle mouse button was debounced. */
#define  KEYBOARD_EVENT        106    /* Keyboard character was pressed. */

char old_str[4][MAXLINE] ;    /* Previous contents of calculator text items. */

extern FILE *PostScript ;
extern FILE *PostScriptInput ;


clear_canvas(canvas,color)
enum can_type canvas ;
int color ;
{
  char c ;

       if (canvas == KEYCANVAS) c = 'K' ;
  else if (canvas == REGCANVAS) c = 'R' ;
  FPRINTF(PostScript,"%d %cC PSClearCanvas\n",color,c) ;
}


close_frame()
{
  FPRINTF(PostScript,"PSCloseFrame\n") ;
}


destroy_frame()
{
  exit(0) ;
}


drawbox(x,y,width,height)
int x,y,width,height ;
{
  FPRINTF(PostScript,"%d %d %d %d PSDrawBox\n",x,y,width,height) ;
}


draw_regs()
{
  FPRINTF(PostScript,"PSDrawRegs\n") ;
}


fillbox(x,y,canvas,width,height,boundry,color)
enum can_type canvas ;
int x,y,width,height,boundry,color ;
{
  char c ;

       if (canvas == KEYCANVAS) c = 'K' ;
  else if (canvas == REGCANVAS) c = 'R' ;
  FPRINTF(PostScript,"%d %d %cC %cCHeight %d %d %d %d PSFillBox\n",
          x,y,c,c,width,height,boundry,color) ;
}


getxy(x,y)
int *x,*y ;
{
  pscanf(PostScriptInput,"%d%d",x,y) ;
}


handle_key_event()
{
  int i,n ;

  pscanf(PostScriptInput,"%d%d%d",&n,&x,&y) ;
  for (i = 0; i < TITEMS; i++)
    if (n == buttons[i].value) return(i) ;
  return(-1) ;
}


handle_up_event(type)
int type ;
{
  int n ;

  pscanf(PostScriptInput,"%d%d",&x,&y) ;
  if ((type == LEFT_UP_EVENT   && down == LEFT_DOWN_EVENT) ||
      (type == MIDDLE_UP_EVENT && down == MIDDLE_DOWN_EVENT))
    {
      n = row*BCOLS*2 + column*2 + portion ;
      if (pending_op != '?' && n <= (NOBUTTONS*2))
        inv_but(row,column,portion,NORMAL) ;
      down = 0 ;
      return(n) ;
    }
  return(-1) ;
}


init_fonts()
{
  FPRINTF(PostScript,"PSInitFonts\n") ;
}


init_ws_type()
{
  if (ps_open_PostScript() < 0) return -1 ;
  if (send_ps_file("news.ps") == -1)
    {
      FCLOSE(PostScript) ;
      return(-1) ;
    }
  FFLUSH(PostScript) ;
  if (ferror(PostScript))
    {
      FCLOSE(PostScript) ;
      return(-1) ;
    }
  FPRINTF(PostScript,"PSIsColor\n") ;
  pscanf(PostScriptInput,"%d",&iscolor) ;
  FPRINTF(PostScript,"PSInitialise\n") ;
  return(0) ;
}


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

  calc_colorsetup(red,green,blue) ;
  FPRINTF(PostScript,"%d PSMakeColorTable\n",CALC_COLORSIZE) ;
  for (i = 0; i < CALC_COLORSIZE; i++)
    FPRINTF(PostScript,"%d %d %d %d PSLoadColor\n",
                       red[i],green[i],blue[i],i) ;
}


/*ARGSUSED*/
make_frames(argc,argv)
int argc ;
char *argv[] ;
{
  FPRINTF(PostScript,"%d %d %d %d PSMakeFrames\n",
                     180,10,TWIDTH,DISPLAY+THEIGHT+15) ;
}


make_icon()
{
  FPRINTF(PostScript,"PSMakeIcons\n") ;
}


make_items()
{
  int i ;

  for (i = (int) BASEITEM; i < (int) TTYPEITEM; i++)
    STRCPY(old_str[i],"") ;
  set_item(BASEITEM,"") ;        /* base. */
  set_item(DISPLAYITEM,"") ;     /* display. */
  set_item(OPITEM,"") ;          /* op. */
  set_item(TTYPEITEM,"") ;       /* ttype. */
}


make_subframes()
{
  FPRINTF(PostScript,"%d PSMakeSubframes\n",DISPLAY) ;
}


send_ps_file(fname)
char *fname ;
{
  FILE *stream ;
  int c ;
 
  if ((stream = fopen(fname,"r")) == NULL) return -1 ;
  while ((c = getc(stream)) != EOF) putc(c,PostScript) ;
  FCLOSE(stream) ;
  return 0 ;
}


set_cursor(type)
int type ;
{
  FPRINTF(PostScript,"%d PSSetCursor\n",type) ;
}


set_item(itemno,str)
enum item_type itemno ;
char *str ;
{
  enum font_type fontno ;
  int x,y ;

  if (itemno == DISPLAYITEM)
    {
      fontno = NFONT ;
      y = DISPLAY-20 ;
    }
  else
    {
      fontno = SFONT ;
      y = DISPLAY-10 ;
    }

       if (itemno == BASEITEM) x = BBORDER ;
  else if (itemno == DISPLAYITEM)
    x = 5+(MAX_DIGITS - strlen(old_str[(int) DISPLAYITEM]))*9 ;
  else if (itemno == OPITEM) x = BBORDER+2*(BWIDTH+BGAP) ;
  else if (itemno == TTYPEITEM) x = BBORDER+(BWIDTH+BGAP) ;
  text(x,y,PANELCANVAS,fontno,WHITE,old_str[(int) itemno]) ;

  if (itemno == DISPLAYITEM)
    x = 5+(MAX_DIGITS - strlen(str))*9 ;
  text(x,y,PANELCANVAS,fontno,BLACK,str) ;
  STRCPY(old_str[(int) itemno],str) ;
}


start_tool()
{
  int n,type ;

  while (1)
    {
      FFLUSH(PostScript) ;
      if (pscanf(PostScriptInput,"%d",&type) == EOF) destroy_frame() ;
      switch (type)
        {
          case CFRAME_REPAINT_EVENT : make_canvas(0) ;
                                      set_item(BASEITEM,base_str[(int) base]) ;
                                      set_item(TTYPEITEM,ttype_str[(int) ttype]) ;
                                      break ;
          case RFRAME_REPAINT_EVENT : make_registers() ;
                                      break ;
          case LEFT_DOWN_EVENT      :
          case MIDDLE_DOWN_EVENT    : handle_down_event(type) ;
                                      break ;
          case LEFT_UP_EVENT        :
          case MIDDLE_UP_EVENT      : n = handle_up_event(type) ;
                                      if (n >= 0 && n <= (NOBUTTONS*2))
                                        process_item(n) ;
                                      break ;
          case KEYBOARD_EVENT       : n = handle_key_event() ;
                                      if (n >= 0 && n <= TITEMS)
                                        process_item(n) ;
                                      break ;
          default                   : ;
        }
    }
}


text(x,y,canvas,fontno,color,str)
enum can_type canvas ;
enum font_type fontno ;
int x,y,color ;
char *str ;
{
  int i ;
  char font,fonttype[6],line[MAXLINE] ;

       if (fontno == SFONT) STRCPY(fonttype,"SFont") ;
  else if (fontno == NFONT) STRCPY(fonttype,"NFont") ;
  else if (fontno == BFONT) STRCPY(fonttype,"BFont") ;
       if (canvas == KEYCANVAS) font = 'K' ;
  else if (canvas == REGCANVAS) font = 'R' ;
  else if (canvas == PANELCANVAS) font = 'P' ;
  line[0] = '\0' ;
  for (i = 0; i < strlen(str); i++)
    switch (str[i])
      {
        case '\\' : STRCAT(line,"\\\\") ;
                    break ;
        case '('  : STRCAT(line,"\\(") ;
                    break ;
        case ')'  : STRCAT(line,"\\)") ;
                    break ;
        default   : STRNCAT(line,&str[i],1) ;
      }
  FPRINTF(PostScript,"%cC %cCHeight %s ",font,font,fonttype) ;
  FPRINTF(PostScript,"%d %d %d (%s) PSMakeText\n",x,y,color,line) ;
}


toggle_reg_canvas()

{
  rstate = !rstate ;
  FPRINTF(PostScript,"%d PSToggleRegCanvas\n",rstate) ;
}
Funky_Stuff
len=`wc -c < news.c`
if [ $len !=     7511 ] ; then
echo error: news.c was $len bytes long, should have been     7511
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',    11369 characters
cat > sunview.c <<'Funky_Stuff'

/*  sunview.c
 *
 *  These are the SunView dependent graphics routines used by calctool.
 *
 *  Copyright (c) Rich Burridge - May 1988.
 *                Sun Microsystems, Australia - All rights reserved.
 *
 *  Version 2.2.
 *
 *  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 "extern.h"
#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include <suntool/panel.h>
#include <suntool/selection_svc.h>
#include <suntool/selection_attributes.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  SELN_QUERY         (void) seln_query
#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() ;
Panel_setting panel_proc() ;
Seln_result get_proc() ;

Canvas kcanvas, rcanvas ;
Cursor main_cursor ;
Event *cevent ;
Frame frame, rframe ;
Icon calctool_icon ;
Panel panel ;
Panel_item item, base_item, display_item, op_item, ttype_item ;
Pixfont *font, *sfont, *nfont, *bfont ;
Pixwin *pw, *cpw, *rcpw ;
Seln_holder holder ;
Seln_rank rank = SELN_PRIMARY ;

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 icon_image[] = {
#include "calctool.icon"
} ;
mpr_static(icon_pixrect,64,64,1,icon_image) ;


/*ARGSUSED*/
static void
canvas_proc(win,event,arg)
Canvas  win ;
Event *event ;
caddr_t arg ;
 
{
  char context = 0 ;
  int i,n,type ;
 
  x = event_x(event) ;
  y = event_y(event) ;
  cevent = event ;
  type = event_id(event) ;
  n = row*BCOLS*2 + column*2 + portion ;
  if (event_is_button(event))
    {
      if (event_is_down(event)) handle_down_event(type) ;
      else if (event_is_up(event) && (event_id(event) == down))
        {
          if (pending_op != '?' && n <= (NOBUTTONS*2))
            inv_but(row,column,portion,NORMAL) ;
          down = 0 ;
          if (n >= 0 && n <= (NOBUTTONS*2)) process_item(n) ;
        }
    }
  else if (event_is_ascii(event))
    {
      for (n = 0; n < TITEMS; n++)
        if (event_id(event) == buttons[n].value) break ;
      if (n == TITEMS) return ;
      if (n >= 0 && n <= TITEMS) process_item(n) ;
    }
  else if (event_id(event) == KBD_DONE && down)
    {
      if (pending_op != '?') draw_button(row,column,portion,NORMAL) ;
      down = 0 ;
    }
  else if ((event_id(event) == KEY_LEFT(8)) && event_is_up(event))
    {
      holder = seln_inquire(rank) ;
      if (holder.state == SELN_NONE) return ;
      SELN_QUERY(&holder,get_proc,&context,SELN_REQ_CONTENTS_ASCII,0,0) ;
      if (issel)
        for (i = 0 ; i < strlen(selection); i++)
          for (n = 0; n < TITEMS; n++)
            if (selection[i] == buttons[n].value)
              {
                process_item(n) ;
                break ;
              }
    }
  else window_default_event_proc(win,event,arg) ;
}        
         

clear_canvas(window,color)
enum can_type window ;
int color ;
{
  int height,width ;
  Canvas ctype ;

       if (window == KEYCANVAS) ctype = kcanvas ;
  else if (window == REGCANVAS) ctype = rcanvas ;
  height = (int) window_get(ctype, WIN_HEIGHT) ;
  width = (int) window_get(ctype, WIN_WIDTH) ;
  fillbox(0,0,window,width,height,0,color) ;
}


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


destroy_frame()
{
  WINDOW_DONE(frame) ;
}


drawbox(x,y,width,height)
int x,y,width,height ;
{
  pw_vector(cpw,x,y,x+width,y,PIX_SET,0) ;
  pw_vector(cpw,x,y,x,y+height,PIX_SET,0) ;
  pw_vector(cpw,x,y+height,x+width,y+height,PIX_SET,0) ;
  pw_vector(cpw,x+width,y,x+width,y+height,PIX_SET,0) ;
}


draw_calc()
{
  make_canvas(0) ;
}


draw_regs()
{
  WINDOW_SET(rframe, WIN_SHOW, TRUE, 0) ;
}


fillbox(x,y,window,width,height,boundry,color)
enum can_type window ;
int x,y,width,height,boundry,color ;
{
       if (window == KEYCANVAS) pw = cpw ;
  else if (window == REGCANVAS) pw = rcpw ;
  if (boundry)
    { 
      pw_writebackground(pw,x,y,width,height,PIX_CLR) ;
      pw_writebackground(pw,x+1,y+1,width-2,height-2,
                         PIX_SRC | PIX_COLOR(color)) ;
    }
  else pw_writebackground(pw,x,y,width,height,PIX_SRC | PIX_COLOR(color)) ;
}


Seln_result
get_proc(buffer)
Seln_request *buffer ;
{
  issel = 0 ;
  if (*buffer->requester.context == 0)
    {
      if (buffer == (Seln_request *) NULL ||
          *((Seln_attribute *) buffer->data) != SELN_REQ_CONTENTS_ASCII)
        return ;
      selection = buffer->data + sizeof(Seln_attribute) ;
      *buffer->requester.context = 1 ;
    }
  else selection = buffer->data ;
  issel = 1 ;
}


getxy(x,y)
int *x,*y ;
{
  *x = event_x(cevent) ;
  *y = event_y(cevent) ;
}


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


init_ws_type()
{
  return 0 ;
}


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_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, 0,
                         WIN_SHOW, FALSE,
                         WIN_WIDTH, TWIDTH,
                         WIN_HEIGHT, 200,
                         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) ;
  main_cursor = window_get(kcanvas,WIN_CURSOR) ;
}


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) ;
  kcanvas = 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(kcanvas,WIN_CONSUME_KBD_EVENT,WIN_ASCII_EVENTS,0) ;
  WINDOW_SET(kcanvas,WIN_CONSUME_KBD_EVENTS,WIN_LEFT_KEYS,
                     WIN_TOP_KEYS,WIN_RIGHT_KEYS,0,0) ;
  WINDOW_SET(kcanvas,WIN_CONSUME_KBD_EVENT,WIN_UP_EVENTS,0) ;
  WINDOW_SET(kcanvas,WIN_IGNORE_PICK_EVENT,LOC_MOVE,0) ;

  cpw = canvas_pixwin(kcanvas) ;
  rcpw = canvas_pixwin(rcanvas) ;
}


/*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(kcanvas,WIN_CURSOR,&help_cursor,0) ;
                        break ;
      case MAINCURSOR : WINDOW_SET(kcanvas,WIN_CURSOR,main_cursor,0) ;
    }
}


set_item(itemno,str)
enum item_type itemno ;
char *str ;
{
  if (itemno == DISPLAYITEM)
    {
      PANEL_SET(display_item,PANEL_VALUE_X,5+(MAX_DIGITS - strlen(display))*9,
                PANEL_VALUE,display,0) ;
      return ;
    }
  else if (itemno == BASEITEM) item = base_item ;
  else if (itemno == OPITEM) item = op_item ;
  else if (itemno == TTYPEITEM) item = ttype_item ;
  PANEL_SET(item,PANEL_LABEL_STRING,str,0) ;
}
 
 
start_tool()
{
  make_registers() ;         /* Calculate memory register frame values. */
  make_canvas(0) ;           /* Draw the calculators buttons. */
  set_item(BASEITEM,base_str[(int) base]) ;    /* Initial arithmetic base. */
  set_item(TTYPEITEM,ttype_str[(int) ttype]) ; /* Initial trigonometric type. */
  window_fit(frame) ;
  window_main_loop(frame) ;
}


text(x,y,window,fontno,color,str)
enum font_type fontno ;
enum can_type window ;
int x,y,color ;
char *str ;
{
       if (fontno == SFONT) font = sfont ;
  else if (fontno == NFONT) font = nfont ;
  else if (fontno == BFONT) font = bfont ;
       if (window == KEYCANVAS) pw = cpw ;
  else if (window == REGCANVAS) pw = rcpw ;
  pw_ttext(pw,x,y,PIX_SRC | PIX_COLOR(color),font,str) ;
}


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 !=    11369 ] ; then
echo error: sunview.c was $len bytes long, should have been    11369
fi
fi # end of overwriting check