/* @(#)graphics.c 1.14 90/02/02 * * These are the independent graphics routines used by calctool. * * Copyright (c) Rich Burridge. * Sun Microsystems, Australia - All rights reserved. * * Permission is given to distribute these sources, as long as the * copyright messages are not removed, and no monies are exchanged. * * 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 #include #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 ; if (buttons[n].color == GREY) return ; get_label(n) ; for (spaces = 0, i = 0; i < strlen(pstr); i++) if (pstr[i] == ' ') spaces++ ; 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 ; drawtext(column*(BWIDTH+BGAP)+BBORDER+x, DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+y, KEYCANVAS, butfont, color, pstr) ; } do_repaint() /* Redraw the calctool canvas[es]. */ { make_canvas(0) ; } drawbox(x, y, width, height) int x, y, width, height ; { drawline(x, y, x+width, y) ; drawline(x, y, x, y+height) ; drawline(x, y+height, x+width, y+height) ; drawline(x+width, y, x+width, y+height) ; } 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, DISPLAY+row*(BHEIGHT+BGAP)+BBORDER, BWIDTH, BHEIGHT) ; fillbox(column*(BWIDTH+BGAP)+BBORDER+1, DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+1, 42, 50, 1, color) ; } else { drawbox(column*(BWIDTH+BGAP)+BBORDER+5, DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+26, 34, 21) ; color = (iscolor) ? buttons[n].color : BLACK ; fillbox(column*(BWIDTH+BGAP)+BBORDER+6, DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+27, 32, 19, 1, color) ; } but_text(row, column, portion, state) ; } fillbox(x, y, width, height, boundry, color) int x, y, width, height, boundry, color ; { if (boundry) { color_area(x, y, width, height, WHITE) ; color_area(x+1, y+1, width-2, height-2, color) ; } else color_area(x, y, width, height, color) ; } get_menu_value() /* Get menu value if valid right mouse press. */ { int i, n, val ; n = row*BCOLS*2 + column*2 + portion ; for (i = 0; i < MAXMENUS; i++) if (buttons[n].value == validmenu[i]) { val = do_menu((enum menu_type) i) ; if (val) handle_menu_selection(i, val) ; break ; } } grey_buttons(base) /* Grey out numeric buttons depending upon base. */ enum base_type base ; { char val ; int column, i, n, portion, row ; if (gtype == TTY) return ; 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) ; } } handle_down_event(type) int type ; { x = curx ; y = cury ; if (!down) { if (pending_op == '?') { down = type ; return ; } for (row = 0; row < BROWS; row++) for (column = 0; column < BCOLS; column++) if ((x > (column*(BWIDTH+BGAP)+BBORDER)) && (x < (column*(BWIDTH+BGAP)+BBORDER+BWIDTH)) && ((y - DISPLAY) > (row*(BHEIGHT+BGAP)+BBORDER)) && ((y - DISPLAY) < (row*(BHEIGHT+BGAP)+BBORDER+BHEIGHT))) { portion = (y - DISPLAY - BBORDER - (row*(BHEIGHT+BGAP))) / (BHEIGHT/2) ; inv_but(row, column, portion, INVERTED) ; down = type ; return ; } } } handle_menu_selection(menu, item) /* Process right button menu selection. */ int menu, item ; { pending = validmenu[menu] ; current = num_names[item-1][0] ; do_pending() ; down = 0 ; inv_but(row, column, portion, NORMAL) ; } 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, DISPLAY+row*(BHEIGHT+BGAP)+BBORDER+5+(portion*22), 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) ; if (iscolor) color_area(0, 0, TWIDTH, DISPLAY, WHITE) ; drawline(0, DISPLAY, TWIDTH, DISPLAY) ; for (row = 0; row < BROWS; row++) for (column = 0; column < BCOLS; column++) for (portion = 0; portion < 2; portion++) draw_button(row, column, portion, NORMAL) ; set_item(BASEITEM,base_str[(int) base]) ; set_item(DISPLAYITEM, display) ; set_item(NUMITEM, dtype_str[(int) dtype]) ; set_item(OPITEM, items[(int) OPITEM].text) ; set_item(TTYPEITEM,ttype_str[(int) ttype]) ; set_item(HYPITEM, (hyperbolic) ? "HYP " : " ") ; set_item(INVITEM, (inverse) ? "INV " : " ") ; make_registers() ; } make_menus() /* Create the popup menus used by the graphics versions. */ { /* There are nine popup menus. These are associated with the following keys: * * ACC - range of possible accuracies (0 - 9). * * CON - constant values plus associated comments, if present. * * EXCH - list of register numbers (0 - 9). * * FUN - function definitions plus associated comments, if present. * * HELP - contains all the keys in the calculator. * * < - range of possible left shift values (0 - 9). * * > - range of possible right shift values (0 - 9). * * RCL - list of register numbers (0 - 9). * * STO - list of register numbers (0 - 9). */ create_menu(M_ACC) ; /* Accuracies. */ create_menu(M_CON) ; /* Constant definitions. */ create_menu(M_EXCH) ; /* Register exchange. */ create_menu(M_FUN) ; /* Function definitions. */ create_menu(M_LSHIFT) ; /* Left shift. */ create_menu(M_RSHIFT) ; /* Right shift. */ create_menu(M_RCL) ; /* Register recall. */ create_menu(M_STO) ; /* Register store. */ } make_registers() /* Calculate memory register frame values. */ { char line[MAXLINE] ; /* Current memory register line. */ int n ; if (!rstate) return ; clear_canvas(REGCANVAS, WHITE) ; drawtext(15, 20, REGCANVAS, NFONT, BLACK, "Memory Registers") ; for (n = 0; n < MAXREGS; n++) { SPRINTF(line, "%1d %s", n, make_number(mem_vals[n])) ; drawtext(15, 40+15*n, REGCANVAS, NFONT, BLACK, line) ; } } process_event(type) /* Process this event. */ int type ; { int i, n ; n = row*BCOLS*2 + column*2 + portion ; switch (type) { case CFRAME_REPAINT : make_canvas(0) ; set_item(BASEITEM, base_str[(int) base]) ; set_item(TTYPEITEM, ttype_str[(int) ttype]) ; break ; case EXIT_WINDOW : if (pending_op != '?') if (n >= 0 && n <= (NOBUTTONS*2)) { draw_button(row, column, portion, NORMAL) ; if (!portion) draw_button(row, column, 1, NORMAL) ; } down = 0 ; break ; case KEYBOARD : nextc = cur_ch ; for (n = 0; n < TITEMS; n++) if (nextc == buttons[n].value) break ; if (n == TITEMS) return ; row = n / (BCOLS * 2) ; column = (n - (row * BCOLS * 2)) / 2 ; portion = n & 1 ; process_item(n) ; break ; case LEFT_DOWN : case MIDDLE_DOWN : case RIGHT_DOWN : handle_down_event(type) ; if (type == RIGHT_DOWN) get_menu_value() ; break ; case LEFT_UP : case MIDDLE_UP : case RIGHT_UP : x = curx ; y = cury ; if ((type == LEFT_UP && down == LEFT_DOWN) || (type == MIDDLE_UP && down == MIDDLE_DOWN) || (type == RIGHT_UP && down == RIGHT_DOWN)) { if (pending_op != '?' && n <= (NOBUTTONS*2)) inv_but(row, column, portion, NORMAL) ; down = 0 ; if (n >= 0 && n <= (NOBUTTONS*2)) process_item(n) ; } break ; case RFRAME_REPAINT : make_registers() ; break ; case TAKE_FROM_SHELF : handle_selection() ; 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 ; } break ; case PUT_ON_SHELF : get_display() ; break ; case DIED : exit(0) ; } } set_item(itemno, str) enum item_type itemno ; char *str ; { enum font_type font ; char *old_text ; int x, y ; old_text = items[(int) itemno].text ; if (itemno == DISPLAYITEM) x = 5+(MAX_DIGITS - strlen(old_text))*nfont_width ; else x = items[(int) itemno].x ; y = items[(int) itemno].y ; font = items[(int) itemno].font ; old_text = items[(int) itemno].text ; drawtext(x, y, KEYCANVAS, font, WHITE, old_text) ; if (itemno == DISPLAYITEM) x = 5+(MAX_DIGITS - strlen(str))*nfont_width ; drawtext(x, y, KEYCANVAS, font, BLACK, str) ; STRCPY(items[(int) itemno].text, str) ; }