|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T c
Length: 14562 (0x38e2)
Types: TextFile
Names: »calctool.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/calctool/calctool.c«
/* calctool.c
*
* This program looks and acts like a simple calculator.
*
* Copyright (c) Rich Burridge - January 1987.
* Sun Microsystems, Australia - All rights reserved.
*
* Version 1.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"
#ifdef SUNTOOL
void canvas_proc() ;
Canvas canvas ;
Cursor main_cursor ;
Event event ;
Frame frame ;
Panel panel ;
Panel_item base_item, display_item ;
Pixwin *cpw ;
struct pixfont *sfont, *nfont ;
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"
} ;
DEFINE_ICON_FROM_IMAGE(calctool_icon,icon_image) ;
#else
struct sgttyb old,new ;
int found ; /* Indicates if valid key value entered. */
#endif SUNTOOL
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 }
} ;
/* Length of display in characters for each base. */
int disp_length[4] = {32, 15, 12, 12} ;
double disp_val ; /* Value of the current display. */
double last_input ; /* Previous number input by user. */
double mem_vals[10] ; /* Memory registers. */
double result ; /* Current calculator total value. */
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 column ; /* Column number of key pressed. */
int error ; /* Indicates some kind of display error. */
int n ; /* Index into buttons array structure. */
int new_input ; /* New number input since last op. */
int nohelp ; /* Indicates if a help file was found. */
int pointed ; /* Whether a decimal point has been given. */
int row ; /* Row number of key pressed. */
int toclear ; /* Indicates if display should be cleared. */
/* Routines obeyed by mouse button or character presses. */
do_accuracy(), do_base(), do_calculation(), do_clear() ;
do_close(), do_delete(), do_help(), do_memory(), do_not() ;
do_number(), do_point(), do_quit(), do_shift(), do_sqrt() ;
char c ; /* Current character typed by the user. */
char cur_op ; /* Current arithmetic operation. */
char cur_value ; /* Current button or character pressed. */
char old_cal_value ; /* Previous calculation operator. */
struct button buttons[TOTAL_ITEMS] = { /* Calculator button values. */
{ "<<", do_shift, '<' }, /* Row 1. */
{ "BIN", do_base, 'B' },
{ "OCT", do_base, 'O' },
{ "DEC", do_base, 'D' },
{ "HEX", do_base, 'H' },
{ ">>", do_shift, '>' },
{ "STO", do_memory, 's' }, /* Row 2. */
{ "RCL", do_memory, 'r' },
{ " D ", do_number, 'd' },
{ " E ", do_number, 'e' },
{ " F ", do_number, 'f' },
{ "CLR", do_clear, '\177' },
{ "NOT", do_not, '~' }, /* Row 3. */
{ "SRT", do_sqrt, 'S' },
{ " A ", do_number, 'a' },
{ " B ", do_number, 'b' },
{ " C ", do_number, 'c' },
{ "BSP", do_delete, '\010' },
{ "AND", do_calculation, '&' }, /* Row 4. */
{ "OR", do_calculation, '|' },
{ " 7 ", do_number, '7' },
{ " 8 ", do_number, '8' },
{ " 9 ", do_number, '9' },
{ " X ", do_calculation, 'x' },
{ "XOR", do_calculation, '^' }, /* Row 5. */
{ "XNR", do_calculation, 'n' },
{ " 4 ", do_number, '4' },
{ " 5 ", do_number, '5' },
{ " 6 ", do_number, '6' },
{ " / ", do_calculation, '/' },
{ "ACC", do_accuracy, 'A' }, /* Row 6. */
{ "HLP", do_help, '?' },
{ " 1 ", do_number, '1' },
{ " 2 ", do_number, '2' },
{ " 3 ", do_number, '3' },
{ " - ", do_calculation, '-' },
{ "OFF", do_close, '\033' }, /* Row 7. */
{ "END", do_quit, 'q' },
{ " 0 ", do_number, '0' },
{ " . ", do_point, '.' },
{ " = ", do_calculation, '=' },
{ " + ", do_calculation, '+' },
{ " ", do_calculation, 'X' }, /* Extra useful definitions. */
{ " ", do_calculation, '\015' },
{ " ", do_quit, 'Q' },
{ " ", do_calculation, 'N' },
} ;
char display[MAXLINE] ; /* Current calculator display. */
main(argc,argv)
int argc ;
char *argv[] ;
{
nohelp = 0 ;
if ((hfd = fopen(HELPNAME,"r")) == NULL)
{
FPRINTF(stderr,"Help file %s not found\r\n",HELPNAME) ;
nohelp = 1 ;
}
#ifdef SUNTOOL
sfont = pf_open(SMALLFONT) ; /* Open small point font. */
nfont = pf_open(NORMALFONT) ; /* Open normal sized font. */
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) ;
panel = window_create(frame,PANEL,WIN_HEIGHT,DISPLAY,
0) ;
canvas = window_create(frame,CANVAS,
WIN_BELOW,panel,
WIN_WIDTH,TOTAL_WIDTH,
WIN_HEIGHT,TOTAL_HEIGHT,
WIN_FONT,nfont,
WIN_EVENT_PROC,canvas_proc,
0) ;
window_set(canvas,WIN_CONSUME_KBD_EVENT,WIN_ASCII_EVENTS,0) ;
display_item = panel_create_item(panel,PANEL_TEXT,
PANEL_VALUE_Y,DISPLAY-25,
PANEL_VALUE_FONT,nfont,
0) ;
base_item = panel_create_item(panel,PANEL_MESSAGE,
PANEL_LABEL_X,10,
PANEL_LABEL_Y,DISPLAY-10,
PANEL_LABEL_FONT,sfont,
PANEL_LABEL_STRING,"",
0) ;
cpw = canvas_pixwin(canvas) ;
main_cursor = window_get(canvas,WIN_CURSOR) ;
#endif SUNTOOL
base = DEC ; /* Initial base. */
accuracy = 2 ; /* Initial accuracy. */
do_clear() ; /* Initialise and clear display. */
for (n = 0; n < 10; n++) mem_vals[n] = 0.0 ; /* Clear memory registers. */
#ifdef SUNTOOL
make_canvas() ; /* Draw the calculators buttons. */
window_fit(frame) ;
window_main_loop(frame) ;
exit(0) ;
#else
IOCTL(fileno(stdin),TIOCGETP,&old) ;
IOCTL(fileno(stdin),TIOCGETP,&new) ;
new.sg_flags |= RAW ;
IOCTL(fileno(stdin),TIOCSETP,&new) ;
for (;;)
{
found = 0 ;
while (!found)
{
READ(0,&c,1) ;
for (n = 0; n < TOTAL_ITEMS; n++)
if (c == buttons[n].value)
{
found = 1 ;
break ;
}
}
cur_value = buttons[n].value ;
(*buttons[n].func)() ;
}
#endif SUNTOOL
}
#ifdef SUNTOOL
/*ARGSUSED*/
static void
canvas_proc(win,event,arg)
Canvas win ;
Event *event ;
caddr_t arg ;
{
int column,row ;
if (event_is_button(event) && event_is_up(event))
{
column = event_x(event) / (BUTTON_WIDTH + BUTTON_GAP) ;
row = event_y(event) / (BUTTON_HEIGHT + BUTTON_GAP) ;
n = row*BUTTON_COLS+column ;
}
else if (event_is_ascii(event))
{
for (n = 0; n < TOTAL_ITEMS; n++)
if (event_id(event) == buttons[n].value) break ;
if (n == TOTAL_ITEMS) return ;
}
else return ;
cur_value = buttons[n].value ;
if (error && cur_value != '\177') return ; /* If error, must clear first. */
(*buttons[n].func)() ;
}
#endif SUNTOOL
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. */
{
static int basevals[4] = {2, 8, 10, 16} ;
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 ;
{
char base_str[MAXLINE] ;
switch (base)
{
case BIN : STRCPY(base_str,"BIN") ;
break ;
case OCT : STRCPY(base_str,"OCT") ;
break ;
case DEC : STRCPY(base_str,"") ;
break ;
case HEX : STRCPY(base_str,"HEX") ;
}
#ifdef SUNTOOL
PANEL_SET(base_item,PANEL_LABEL_STRING,base_str,0) ;
#else
FPRINTF(stdout,"%s\r\n",base_str) ;
#endif SUNTOOL
}
display_result(display) /* Output result to calculator display. */
char display[MAXLINE] ;
{
#ifdef SUNTOOL
PANEL_SET(display_item,PANEL_VALUE_X,20+(MAX_DIGITS - strlen(display))*7,
PANEL_VALUE,display,
0) ;
#else
FPRINTF(stdout,"%s\r\n",display) ;
#endif SUNTOOL
}
get_next_value() /* Get next key or mouse button press. */
{
int column,found,n,row ;
found = 0 ;
while (!found)
{
#ifdef SUNTOOL
window_read_event(canvas,&event) ;
if (event_is_button(&event) && event_is_up(&event))
{
column = event_x(&event) / (BUTTON_WIDTH + BUTTON_GAP) ;
row = event_y(&event) / (BUTTON_HEIGHT + BUTTON_GAP) ;
n = row*BUTTON_COLS+column ;
if (n < TOTAL_ITEMS) found = 1 ;
}
else if (event_is_ascii(&event))
{
c = event_id(&event) ;
#else
{
READ(0,&c,1) ;
#endif SUNTOOL
for (n = 0; n < TOTAL_ITEMS; n++)
if (c == buttons[n].value)
{
found = 1 ;
break ;
}
}
}
return(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 ;
}
#ifdef SUNTOOL
make_canvas() /* Draw the calculators buttons. */
{
int x ;
pw_writebackground(cpw,0,0,TOTAL_WIDTH,TOTAL_HEIGHT,PIX_CLR) ;
for (row = 0; row < BUTTON_ROWS; row++)
for (column = 0; column < BUTTON_COLS; column++)
{
pw_write(cpw,column*BUTTON_WIDTH+BUTTON_BORDER+(column*BUTTON_GAP),
row*BUTTON_HEIGHT+BUTTON_BORDER+(row*BUTTON_GAP),
BUTTON_WIDTH,BUTTON_HEIGHT,PIX_SRC,&button_pr,0,0) ;
x = (strlen(buttons[row*BUTTON_COLS+column].str) == 3) ? 8 : 11 ;
pw_text(cpw,column*BUTTON_WIDTH+BUTTON_BORDER+(column*BUTTON_GAP)+x,
row*BUTTON_HEIGHT+BUTTON_BORDER+(row*BUTTON_GAP)+14,
PIX_SRC | PIX_DST,nfont,
buttons[row*BUTTON_COLS+column].str) ;
}
}
#endif SUNTOOL
make_display(display) /* Output calculators display - right justified. */
char display[MAXLINE] ;
{
#ifdef SUNTOOL
PANEL_SET(display_item,PANEL_VALUE_X,20+(MAX_DIGITS - strlen(display))*7,
PANEL_VALUE,display,
0) ;
#endif SUNTOOL
}
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 ;
static char digits[] = "0123456789abcdef" ;
if (isinf(number) || isnan(number))
{
STRCPY(display,"Error") ;
display_result(display) ;
error = 1 ;
return ;
}
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] ;
}
ndig = MIN(ddig + accuracy,--cmax) ;
while (ndig-- > 0)
{
if (ddig-- == 0) *optr++ = '.' ;
val *= powers[1][base] ;
dval = val ;
*optr++ = digits[dval] ;
val -= (int) val ;
}
*optr++ = '\0' ;
display_result(display) ;
toclear = 1 ;
pointed = 0 ;
}
make_text(x,y,line) /* Output a line of text. */
int x,y ;
char line[MAXLINE] ;
{
#ifdef SUNTOOL
pw_text(cpw,x,y,PIX_SRC,nfont,line) ;
#else
FPRINTF(stdout,"%s\r\n",line) ;
#endif SUNTOOL
}