|
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 }