[net.sources] Simple little desktop calculator for the Sun under V3.n

richb@yarra.OZ (Rich Burridge) (10/06/86)

This is a simple little desktop calculator for the Sun running under
V3.0 of the Sun O/S and using SunView.

It's my first serious look at SunView so I reckon it can certainly
be improved. Comments, suggestions, improvements and bugs to me.

I still think it's amazing how a little 300 line C program can
generate a binary of about 1/2 megabyte :-)

Regards Rich.

Rich Burridge            ISD:  +61 3 267-6222
Sun Australia            STD:  (03) 267-6222
14 Queens Rd,            ARPA: richb%yarra.oz@seismo.arpa
Melbourne, VIC 3004.     UUCP: seismo!munnari!yarra.oz!richb
AUSTRALIA.               ACS:  richb@yarra.oz

----------CUT HERE--------------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 (not csh) to create:
#	Makefile
#	README
#	calc.archive
#	calctool.c
#	calctool.icon
# This archive created: Mon Oct  6 15:06:45 1986
# By:	Rich Burridge (Sun Computer Australia (Melbourne))
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#
#  Makefile for calctool, a desktop calculator for the Sun.
#
#  Copyright (c) Rich Burridge - SUN Australia - October 1986.
#
#  Version 1.0.
#
#  No responsibility is taken for any errors inherent either in the comments
#  or the code of this program, but if reported to me then an attempt will
#  be made to fix them.
#
BINARIES      = calctool
BINDIR        = .
CCFLAGS       = -c -O
LDFLAGS       =
OBJS          = calctool.o
SRCS          = calctool.c
HDRS          =
LIBS          = -lm -lsuntool -lsunwindow -lpixrect
#
#  The following commands are declared.
#
all:            $(BINARIES)

release:        $(BINARIES)
		strip $(BINARIES)
#
#  General Makefile stuff.
#
backup:
		cp calctool.c calctool.c~
clean:
		rm -f *.o core
lint:
		lint $(SRCS) -lpixrect
#
#  calc specific stuff.
#
calctool:       $(OBJS)
		cc $(LDFLAGS) -o calctool $(OBJS) $(LIBS)

calctool.o:     calctool.c $(HDRS)
		cc $(CCFLAGS) calctool.c
SHAR_EOF
fi
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
cat << \SHAR_EOF > 'README'

  Calctool is a very simple little desktop calculator for the Sun
workstation running under V3.0 (or later) of the Sun O/S.

  It is based on the Sanyo cx250 pocket calculator, of which I have
a copy and of which I'm always losing. This program has been
hastily put together. It is also my first real look at Sunview,
Suns own graphics package.

  Suggestion for improvement would be most welcome plus bugs,
comments and flames to me.

Regards Rich.

Rich Burridge             ISD:   +61 3 267-6222
Sun Australia             STD:   (03) 267-6222
14 Queens Rd,             ARPA: richb%yarra.oz@seismo.arpa
Melbourne, VIC 3004.      UUCP: seismo!munnari!yarra.oz!richb
AUSTRALIA.                ACS:  richb@yarra.oz
SHAR_EOF
fi
if test -f 'calc.archive'
then
	echo shar: "will not over-write existing file 'calc.archive'"
else
cat << \SHAR_EOF > 'calc.archive'

SHAR_EOF
fi
if test -f 'calctool.c'
then
	echo shar: "will not over-write existing file 'calctool.c'"
else
cat << \SHAR_EOF > 'calctool.c'

/*  calctool.c
 *
 *  This program looks and acts just like a simple desktop calculator.
 *  Copyright (c) Rich Burridge - Sun Australia - October 1986.
 *
 *  Version 1.0
 *
 *  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 <stdio.h>
#include <strings.h>
#include <math.h>
#include <suntool/sunview.h>
#include <suntool/panel.h>

#define  SPRINTF        (void) sprintf   /* To make lint happy. */
#define  SSCANF         (void) sscanf
#define  STRCPY         (void) strcpy
#define  STRNCAT        (void) strncat

#define  UNDEFINED       0               /* No current arithmetic operation. */
#define  ADDITION        1
#define  SUBTRACTION     2
#define  MULTIPLICATION  3
#define  DIVISION        4
#define  SQUARE_ROOT     5

#define  BUTTON_BORDER   5               /* No of pixels in border. */
#define  BUTTON_COLS     4               /* No of columns of buttons. */
#define  BUTTON_GAP      5               /* No of pixels between buttons. */
#define  BUTTON_HEIGHT   25              /* Number of pixels for height. */
#define  BUTTON_ROWS     5               /* No of rows of buttons. */
#define  BUTTON_WIDTH    40              /* No of pixels for width. */
#define  DISPLAY         30              /* Calculators numerical display. */
#define  DISP_LENGTH     12              /* Length of display in characters. */
#define  MAXLINE         30              /* Length of character strings. */
#define  NOBUTTONS       BUTTON_ROWS * BUTTON_COLS

char *sprintf() ;
void button_press() ;
Frame frame ;
Panel panel1,panel2 ;
Panel_item display_item ;

short icon_image[] = {
#include "calctool.icon"
} ;
DEFINE_ICON_FROM_IMAGE(calctool_icon,icon_image) ;

double old_display ;                /* Previous calculator display value. */
double last_input ;                 /* Previous number input by user. */

int column,row ;
int error ;                         /* Indicates some kind of display error. */
int operator = UNDEFINED ;          /* Current arithmetic operation. */
int pointed ;                       /* Whether a decimal point has been given. */
int started ;                       /* Indicates if number should be displayed. */
int toclear ;                       /* Indicates if display should be cleared. */

char bpress ;                       /* Current button pressed. */
char oldbpress ;                    /* Previous button pressed. */
char button_vals[NOBUTTONS][4] =    /* Calculator button values. */
       {
         "END", " C ", "SRT", "OFF",
         " 7 ", " 8 ", " 9 ", " X ",
         " 4 ", " 5 ", " 6 ", " / ",
         " 1 ", " 2 ", " 3 ", " - ",
         " 0 ", " . ", " = ", " + "
       } ;
char display[MAXLINE] ;             /* Current calculator display. */


main(argc,argv)
int argc ;
char *argv[] ;

{
  frame = window_create(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, BUTTON_HEIGHT,
                        WIN_COLUMN_WIDTH, BUTTON_WIDTH,
                        WIN_ROWS, BUTTON_ROWS,
                        WIN_COLUMNS, BUTTON_COLS,
                        FRAME_ARGS, argc,argv,
                        0) ;

  panel1 = window_create(frame,PANEL,WIN_HEIGHT,DISPLAY,0) ;
  panel2 = window_create(frame,PANEL,WIN_BELOW,panel1,0) ;
  display_item = panel_create_item(panel1,PANEL_MESSAGE,
                                   PANEL_PAINT, PANEL_NO_CLEAR,
                                   0) ;
  initialise() ;              /* Initialise certain variables. */
  clear_display() ;
  for (row = 0; row < BUTTON_ROWS; row++)
    for (column = 0; column < BUTTON_COLS; column++)
      panel_create_item(panel2,PANEL_BUTTON,
         PANEL_LABEL_X,column*BUTTON_WIDTH+BUTTON_BORDER+(column*BUTTON_GAP),
         PANEL_LABEL_Y,row*BUTTON_HEIGHT+BUTTON_BORDER+(row*BUTTON_GAP),
         PANEL_LABEL_IMAGE,
           panel_button_image(panel2,button_vals[row*BUTTON_COLS+column],0,0),
         PANEL_NOTIFY_PROC,button_press,0) ;

  window_fit(panel2) ;
  window_fit(frame) ;
  window_main_loop(frame) ;
  exit(0) ;
}


clear_display()

{
  started = 0 ;
  pointed = 0 ;
  toclear = 0 ;
  STRCPY(display,"0.") ;
  make_display() ;
}


do_calculation()      /* Perform arithmetic calculation and display result. */

{
  if (bpress == 'R')
    {
      SSCANF(display,"%lf",&last_input) ;
      operator = SQUARE_ROOT ;
    }
  else if (bpress != '=')
    {
      if (oldbpress == '+' || oldbpress == '-' || oldbpress == 'X' ||
          oldbpress == '/' || oldbpress == '=')
        {
          operator = bpress ;
          return ;
        }
      SSCANF(display,"%lf",&last_input) ;
    }
  else if (oldbpress != '=' && oldbpress != 'R') SSCANF(display,"%lf",&last_input) ;

  switch (operator)
    {
      case UNDEFINED      : break ;
      case ADDITION       : SPRINTF(display,"%.10f",old_display + last_input) ;
                            break ;
      case SUBTRACTION    : SPRINTF(display,"%.10f",old_display - last_input) ;
                            break ;
      case MULTIPLICATION : SPRINTF(display,"%.10f",old_display * last_input) ;
                            break ;
      case DIVISION       : SPRINTF(display,"%.10f",old_display / last_input) ;
                            break ;
      case SQUARE_ROOT    : SPRINTF(display,"%.10f",sqrt(last_input)) ;
    }
  make_result() ;
  toclear = 1 ;
  SSCANF(display,"%lf",&old_display) ;
}


initialise()

{
  error = 0 ;                 /* Currently no display error. */
  oldbpress = '\0' ;          /* No previous button pressed. */
  operator = UNDEFINED ;      /* No arithmetic operator defined yet. */
  old_display = 0.0 ;         /* No previous value defined yet. */
}


make_display()      /* Build up the calculators display - right justified. */

{
  char output[MAXLINE] ;

  SPRINTF(output,"%20s",display) ;
  panel_set(display_item,PANEL_LABEL_STRING,output,0) ;
}


make_result()       /* Display result of calculation. */

{
  char output[MAXLINE] ;
  int pnt ;

  pnt = strlen(display)-1 ;
  while (display[pnt] != '.' && display[pnt] == '0') display[pnt--] = '\0' ;

  for (pnt = 0; pnt < strlen(display); pnt++)
    if (display[pnt] == '.') break ;

  if (pnt > DISP_LENGTH)
    {
      display[DISP_LENGTH-2] = '\0' ;
      SPRINTF(output,"E%18s.",display) ;
      error = 1 ;
    }
  else if (!strcmp(display,"Infinity"))
    {
      SPRINTF(output,"E%19s","0.") ;
      error = 1 ;
    }
  else if (display[0] == '-') SPRINTF(output,"-%19s",&display[1]) ;
  else SPRINTF(output,"%20s",display) ;
  panel_set(display_item,PANEL_LABEL_STRING,output,0) ;
}


/*ARGSUSED*/
static void button_press(item,event)
Panel_item item ;
Event *event ;

{
  int column,row ;

  column = (event_x(event) - BUTTON_BORDER) / (BUTTON_WIDTH + BUTTON_GAP) ;
  row = (event_y(event) - BUTTON_BORDER) / (BUTTON_HEIGHT + BUTTON_GAP) ;
  bpress = button_vals[row*BUTTON_COLS+column][1] ;

  if (error && bpress != 'C') return ;   /* Only C can clear an error condition. */

  switch (bpress)
    {
      case 'N' : window_destroy(frame) ;              /* Terminate program. */
                 break ;
      case 'F' : window_set(frame,FRAME_CLOSED,TRUE,0) ;  /* Turn window iconic. */
      case 'C' : clear_display() ;
                 operator = UNDEFINED ;
                 old_display = 0.0 ;
                 error = 0 ;
                 break ;
      case 'R' : do_calculation() ;                       /* Square root. */
                 operator = SQUARE_ROOT ;
                 break ;
      case '1' :
      case '2' :
      case '3' :
      case '4' :
      case '5' :
      case '6' :
      case '7' :
      case '8' :
      case '9' : started = 1 ;
      case '0' : if (toclear)
                   {
                     clear_display() ;
                     if (bpress != '0') started = 1 ;
                   }
                 if (strlen(display) < DISP_LENGTH)
                   {
                     if (pointed)
                       {
                         STRNCAT(display,&bpress,1) ;
                         make_display() ;
                       }
                     else if (started)
                       {
                         if (!strcmp(display,"0.")) display[0] = '\0' ;
                         display[strlen(display)-1] = '\0' ;
                         STRNCAT(display,&bpress,1) ;
                         STRNCAT(display,".",1) ;
                         make_display() ;
                       }
                   }
                 break ;

      case '+' : do_calculation() ;
                 operator = ADDITION ;
                 break ;
      case '-' : do_calculation() ;
                 operator = SUBTRACTION ;
                 break ;
      case 'X' : do_calculation() ;
                 operator = MULTIPLICATION ;
                 break ;
      case '/' : do_calculation() ;
                 operator = DIVISION ;
                 break ;

      case '.' : if (strlen(display) < DISP_LENGTH)
                   if (!pointed) pointed = 1 ;
                 break ;

      case '=' : do_calculation() ;
                 break ;
    }
  oldbpress = bpress ;
}
SHAR_EOF
fi
if test -f 'calctool.icon'
then
	echo shar: "will not over-write existing file 'calctool.icon'"
else
cat << \SHAR_EOF > 'calctool.icon'
/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
 */
	0x9555,0x5555,0x5548,0x8888,0xAAAA,0xAAAA,0xAA88,0x8888,
	0x5555,0x5555,0x5562,0x2222,0xFFFF,0xFFFF,0xFEA2,0x2222,
	0x8000,0x0000,0x0348,0x8888,0xBFFF,0xFFFF,0xFA88,0x8888,
	0xA000,0x0000,0x0B62,0x2222,0xA000,0x0000,0x0AA2,0x2222,
	0xA600,0x2082,0x0B48,0x8888,0xA900,0x6186,0x0A88,0x8888,
	0xA200,0x2282,0x0B62,0x2222,0xA100,0x23C2,0x0AA2,0x2222,
	0xA908,0x2082,0x0B48,0x8888,0xA608,0x7087,0x0A88,0x8888,
	0xA000,0x0000,0x0B62,0x2222,0xA000,0x0000,0x0AA2,0x2222,
	0xBFFF,0xFFFF,0xFB48,0x8888,0x8000,0x0000,0x0288,0x8888,
	0x8000,0x0000,0x0362,0x2222,0xBFDF,0xEFF7,0xFAA2,0x2222,
	0xA050,0x2814,0x0B48,0x8888,0xAF53,0x2994,0x0A88,0x8888,
	0xA154,0xAA55,0x1362,0x2222,0xA253,0x2A54,0xAAA2,0x2222,
	0xA254,0xA9D4,0x4B48,0x8888,0xA454,0xA854,0xAA88,0x8888,
	0xA453,0x2995,0x1B62,0x2222,0xA050,0x2814,0x0AA2,0x2222,
	0xBFDF,0xEFF7,0xFB48,0x8888,0x8000,0x0000,0x0288,0x8888,
	0xBFDF,0xEFF7,0xFB62,0x2222,0xA050,0x2814,0x0AA2,0x2222,
	0xA257,0xA994,0x2B48,0x8888,0xA654,0x2A14,0x4A88,0x8888,
	0xAA57,0x2B94,0x4B62,0x2222,0xAF50,0xAA54,0x8AA2,0x2222,
	0xA254,0xAA54,0x8B48,0x8888,0xA253,0x2995,0x0A88,0x8888,
	0xA050,0x2814,0x0B62,0x2222,0xBFDF,0xEFF7,0xFAA2,0x2222,
	0x8000,0x0000,0x0348,0x8888,0xBFDF,0xEFF7,0xFA88,0x8888,
	0xA050,0x2814,0x0B62,0x2222,0xA253,0x2994,0x0AA2,0x2222,
	0xA654,0xAA54,0x0B48,0x8888,0xA250,0xA895,0xEA88,0x8888,
	0xA253,0x2854,0x0B62,0x2222,0xA254,0x2A54,0x0AA2,0x2222,
	0xA757,0xA994,0x0B48,0x8888,0xA050,0x2814,0x0A88,0x8888,
	0xBFDF,0xEFF7,0xFB62,0x2222,0x8000,0x0000,0x02A2,0x2222,
	0xBFDF,0xEFF7,0xFB48,0x8888,0xA050,0x2814,0x0A88,0x8888,
	0xA650,0x2814,0x0B62,0x2222,0xA950,0x2814,0x4AA2,0x2222,
	0xAB50,0x2BD4,0x4B48,0x8888,0xAD50,0x2815,0xFA88,0x8888,
	0xA951,0x2BD4,0x4B62,0x2222,0xA651,0x2814,0x4AA2,0x2222,
	0xA050,0x2814,0x0B48,0x8888,0xBFDF,0xEFF7,0xFA88,0x8888,
	0x8000,0x0000,0x0322,0x2222,0xFFFF,0xFFFF,0xFE22,0x2222
SHAR_EOF
fi
exit 0
#	End of shell archive
D