home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************/
- /* Copyright 1988 by Chuck Musciano and Harris Corporation */
- /* */
- /* Permission to use, copy, modify, and distribute this software */
- /* and its documentation for any purpose and without fee is */
- /* hereby granted, provided that the above copyright notice */
- /* appear in all copies and that both that copyright notice and */
- /* this permission notice appear in supporting documentation, and */
- /* that the name of Chuck Musciano and Harris Corporation not be */
- /* used in advertising or publicity pertaining to distribution */
- /* of the software without specific, written prior permission. */
- /* Chuck Musciano and Harris Corporation make no representations */
- /* about the suitability of this software for any purpose. It is */
- /* provided "as is" without express or implied warranty. */
- /************************************************************************/
-
- /************************************************************************/
- /* */
- /* Module: display.c */
- /* */
- /* Function: Manage calculator display */
- /* */
- /* Public Names: update_display resolve stack top and display */
- /* convert_display convert user entry to stack top */
- /* convert_value convert value to string */
- /* fix_proc handle display widths */
- /* do_digit handle digit input */
- /* clear_entry clear any typed digits */
- /* keyboard handle keyboard entries */
- /* */
- /* Change History: 17 Nov 86 Creation */
- /* */
- /************************************************************************/
-
- #include <stdio.h>
-
- #include <suntool/sunview.h>
- #include <suntool/panel.h>
- #include <suntool/canvas.h>
-
- #include "manifest.h"
- #include "globals.h"
- #include "keys.h"
-
- #define DIGIT_FONT "/usr/lib/fonts/fixedwidthfonts/gallant.r.19"
-
- #define margin(x) (((curr_mode == SCIENTIFIC? 15 : 16) - strlen(x)) * DIGIT_WIDTH)
-
- #define MAX_DIGITS ((curr_mode == SCIENTIFIC)? 14 : 16)
- #define DIGIT_WIDTH d_font->pf_defaultsize.x
- #define DIGIT_HEIGHT d_font->pf_defaultsize.y
- #define STATUS_WIDTH s_font->pf_defaultsize.x
- #define STATUS_HEIGHT s_font->pf_defaultsize.y
-
- PUBLIC double atof();
- PUBLIC char *index();
-
- PUBLIC Canvas display;
- PUBLIC Panel keys;
- PUBLIC struct pixfont *key_font;
-
- PRIVATE Pixwin *pw = NULL;
- PRIVATE struct pixfont *d_font = NULL;
- PRIVATE struct pixfont *s_font = NULL;
- PRIVATE char e_str[5], d_str[18];
- PRIVATE int e_len = 0;
- PRIVATE int d_len = 0;
- PRIVATE int pw_width;
- PRIVATE int pw_height;
- PRIVATE char *digit = "0123456789ABCDEF.E-";
-
- PRIVATE verify(source, valid)
-
- char *source;
- char *valid;
-
- { register char *s;
-
- for ( ; *source; source++) {
- for (s = valid; *s && *s != *source; s++)
- ;
- if (*s == '\0')
- return(FALSE);
- }
- return(TRUE);
- }
-
- PRIVATE convert_stacktop()
-
- { char buf[60], *p;
-
- convert_value(v_stack[v_top], buf);
- if (curr_mode == SCIENTIFIC && (p = index(buf, 'E')) != NULL) {
- strcpy(e_str, p + 1);
- if (*e_str == '+')
- strcpy(e_str, e_str + 1);
- e_len = strlen(e_str);
- if (e_len == 2) {
- e_str[3] = '\0';
- e_str[2] = e_str[1];
- e_str[1] = e_str[0];
- e_str[0] = '0';
- e_len = 3;
- }
- else if (e_len == 3 && *e_str == '-') {
- e_str[4] = '\0';
- e_str[3] = e_str[2];
- e_str[2] = e_str[1];
- e_str[1] = '0';
- e_len = 4;
- }
- *p = '\0';
- }
- else {
- *e_str = '\0';
- e_len = 0;
- }
- strcpy(d_str, buf);
- d_len = strlen(d_str);
- }
-
- PUBLIC update_display()
-
- { char buf[60], *p, *op_str();
- int i, w;
- static char *tm[] = {"Deg ", "Rad ", "Grad"};
-
- if (d_font == NULL)
- if ((d_font = pf_open(DIGIT_FONT)) == NULL) {
- fprintf(stderr, "calctool: could not open font %s\n", DIGIT_FONT);
- exit(1);
- }
- if (s_font == NULL)
- if ((s_font = pf_open(STATUS_FONT)) == NULL) {
- fprintf(stderr, "calctool: could not open font %s\n", DIGIT_FONT);
- exit(1);
- }
- if (pw == NULL) {
- pw = canvas_pixwin(display);
- pw_width = (int) window_get(display, WIN_WIDTH);
- pw_height = (int) window_get(display, WIN_HEIGHT);
- }
- for (i = w = 0; i < o_top && w < 23; w += strlen(op_str(o_stack[i++])))
- pw_text(pw, w * STATUS_WIDTH + 1, 7, PIX_SRC, s_font, op_str(o_stack[i]));
- for ( ; w < 23; w++)
- pw_text(pw, w * STATUS_WIDTH + 1, 7, PIX_SRC, s_font, " ");
- pw_text(pw, 23 * STATUS_WIDTH, 7, PIX_SRC, s_font, (curr_mode == SCIENTIFIC)? tm[trig_mode] : " ");
- if (curr_mode == SCIENTIFIC && ee_mode)
- pw_text(pw, 28 * STATUS_WIDTH, 7, PIX_SRC, s_font, eng_mode? "Eng " : "EE ");
- else
- pw_text(pw, 28 * STATUS_WIDTH, 7, PIX_SRC, s_font, " ");
- if (curr_mode == SCIENTIFIC)
- if (curr_width[0] == -1)
- strcpy(buf, " Float");
- else
- sprintf(buf, "%2d Digits", curr_width[0]);
- else
- sprintf(buf, " %2d Bits", curr_width[index_of(curr_base)]);
- pw_text(pw, 32 * STATUS_WIDTH, 7, PIX_SRC, s_font, buf);
- if (d_len > 0) {
- if (e_len > 0) {
- pw_text(pw, pw_width - 6 * DIGIT_WIDTH, 26, PIX_SRC, d_font, " e");
- pw_text(pw, pw_width - 4 * DIGIT_WIDTH, 26, PIX_SRC, d_font, e_str);
- if (e_len == 3)
- pw_text(pw, pw_width - DIGIT_WIDTH, 26, PIX_SRC, d_font, " ");
- }
- else
- pw_text(pw, pw_width - 6 * DIGIT_WIDTH, 26, PIX_SRC, d_font, " ");
- pw_rop(pw, 0, pw_height - DIGIT_HEIGHT + 1, margin(d_str), DIGIT_HEIGHT, PIX_SRC | PIX_COLOR(0), NULL, 0, 0);
- pw_text(pw, margin(d_str), 26, PIX_SRC, d_font, d_str);
- }
- else {
- convert_value(v_stack[v_top], buf);
- if (strcmp(buf, "NaN") == 0) {
- strcpy(buf, " Error! ");
- pw_text(pw, pw_width - 6 * DIGIT_WIDTH, 26, PIX_SRC, d_font, " ");
- }
- else if (curr_mode == SCIENTIFIC && (p = index(buf, 'E')) != NULL) {
- pw_text(pw, pw_width - 6 * DIGIT_WIDTH, 26, PIX_SRC, d_font, " e");
- *p++ = '\0';
- i = 4;
- if (*p == '+')
- p++;
- if (*p == '-') {
- pw_text(pw, pw_width - i-- * DIGIT_WIDTH, 26, PIX_SRC, d_font, "-");
- p++;
- }
- if (strlen(p) == 2)
- pw_text(pw, pw_width - i-- * DIGIT_WIDTH, 26, PIX_SRC, d_font, "0");
- pw_text(pw, pw_width - i * DIGIT_WIDTH, 26, PIX_SRC, d_font, p);
- if (i - strlen(p) == 1)
- pw_text(pw, pw_width - DIGIT_WIDTH, 26, PIX_SRC, d_font, " ");
- }
- else
- pw_text(pw, pw_width - 6 * DIGIT_WIDTH, 26, PIX_SRC, d_font, " ");
- pw_rop(pw, 0, pw_height - DIGIT_HEIGHT + 1, margin(buf), DIGIT_HEIGHT, PIX_SRC|PIX_COLOR(0), NULL, 0, 0);
- pw_text(pw, margin(buf), 26, PIX_SRC, d_font, buf);
- }
- }
-
- PUBLIC convert_display()
-
- { char buf[60], *p;
- int i;
-
- if (d_len > 0 || e_len > 0)
- if (curr_mode == SCIENTIFIC) {
- strcpy(buf, d_str);
- strcat(buf, "E");
- strcat(buf, e_str);
- v_stack[v_top] = atof(buf);
- }
- else {
- for (i = 0, p = d_str; *p; p++)
- i = i * curr_base + (index(digit, *p) - digit);
- v_stack[v_top] = (double) i;
- }
- edit_ee = FALSE;
- clear_entry();
- }
-
- PUBLIC convert_value(val, s)
-
- double val;
- char *s;
-
- { unsigned int i;
- int start, exp, dp, sign = 1, j, sp;
- char *p, *q, buf[60];
-
- if (curr_mode == SCIENTIFIC) {
- sprintf(s, " %-20.15E", val);
- if (!verify(s, " 0123456789eE+-.")) {
- strcpy(s, "NaN");
- return;
- }
- if (s[30] == '-') {
- sign = -1;
- strcpy(&(s[30]), &(s[31]));
- }
- start = 30;
- sscanf(&(s[start + 18]), "%d", &exp);
- s[start + 17] = '\0';
- strcpy(&(s[start + 1]), &(s[start + 2])); /* lose the decimal point */
- exp++; /* and remember it */
- if (s[start + 13] >= '5') /* round up */
- for (i = start + 12; ; i--) {
- s[i]++;
- if (s[i] == ':') {
- s[i] = '0';
- if (i == start) {
- s[--start] = '1';
- exp++;
- break;
- }
- }
- else
- break;
- }
- s[start + 13] = '\0'; /* retain 13 digits */
- s[start - 1] = s[start];
- s[start--] = '.';
- exp--;
- dp = start + 1;
- if (ee_mode || exp > 12 || exp < ((curr_width[0] == -1)? -12 : -curr_width[0])) {
- if (eng_mode)
- for ( ; exp % 3; dp++, exp--) {
- s[dp] = s[dp + 1];
- s[dp + 1] = '.';
- }
- if (curr_width[0] != -1) {
- i = strlen(s + dp + 1);
- if (i > curr_width[0])
- s[dp + curr_width[0] + 1] = '\0';
- }
- else
- for (i = strlen(s) - 1; s[i] == '0'; s[i--] = '\0')
- ;
- if (s[i = strlen(s) - 1] == '.')
- s[i] = '\0';
- sprintf(s + strlen(s), "E%03d", exp);
- }
- else {
- for ( ; exp > 0; dp++, exp--) {
- s[dp] = s[dp + 1];
- s[dp + 1] = '.';
- }
- for ( ; exp < 0; dp--, exp++) {
- s[dp] = s[dp - 1];
- s[dp - 1] = '.';
- s[dp - 2] = '0';
- start = dp - 2;
- }
- if (curr_width[0] != -1) {
- i = strlen(s + dp + 1);
- if (i > curr_width[0])
- s[dp + curr_width[0] + 1] = '\0';
- else
- for ( ; i < curr_width[0]; i++)
- strcat(s, "0");
- if (strlen(s + start) > 14)
- s[start + 14] = '\0';
- }
- else {
- for (i = strlen(s) - 1; s[i] == '0'; s[i--] = '\0');
- if (strlen(s + dp + 1) > 12)
- s[dp + 13] = '\0';
- if (s[i = strlen(s) - 1] == '.')
- s[i] = '\0';
- }
- }
- if (sign == -1)
- s[--start] = '-';
- strcpy(s, s + start);
- }
- else {
- i = (unsigned int) val;
- i &= ((unsigned) 0xffffffff) >> (32 - curr_width[index_of(curr_base)]);
- for (p = buf; i; i = i >> index_of(curr_base))
- *p++ = digit[i & (curr_base - 1)];
- *p = '\0';
- if (*buf == '\0')
- strcpy(buf, "0");
- for (j = strlen(buf) - 1, p = s; j >= 0; j--, p++)
- *p = buf[j];
- *p = '\0';
- }
- }
-
-
- PUBLIC fix_proc(item, event)
-
- Panel_item item;
- Event *event;
-
- { static Menu s_menu = NULL;
- static Menu b_menu = NULL;
- static Menu h_menu = NULL;
- static Menu t_menu = NULL;
- int i;
-
- if (event_id(event) >= ASCII_FIRST && event_id(event) <= ASCII_LAST) {
- keyboard(event_id(event));
- return;
- }
- if ((event_id(event) == MS_LEFT && !inverted) || (event_id(event) == MS_MIDDLE && inverted))
- if (curr_mode == SCIENTIFIC)
- if (curr_width[0] == 12)
- curr_width[0] = -1;
- else
- curr_width[0]++;
- else
- switch (curr_base) {
- case BINARY : if (curr_width[1] == 16)
- curr_width[1] = 4;
- else
- curr_width[1] *= 2;
- break;
- case OCTAL :
- case HEXADECIMAL : if (curr_width[index_of(curr_base)] == 32)
- curr_width[index_of(curr_base)] = 8;
- else
- curr_width[index_of(curr_base)] *= 2;
- break;
- }
- else if (curr_mode == SCIENTIFIC && ((event_id(event) == MS_LEFT && inverted) || (event_id(event) == MS_MIDDLE && !inverted)))
- if (trig_mode == GRAD)
- trig_mode = DEG;
- else
- trig_mode++;
- else if (event_id(event) == MS_RIGHT) {
- if (inverted) {
- if (t_menu == NULL)
- t_menu = menu_create(MENU_INITIAL_SELECTION, MENU_DEFAULT,
- MENU_ITEM, MENU_STRING, "Degrees", MENU_VALUE, 1, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, "Radians", MENU_VALUE, 2, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, "Grads", MENU_VALUE, 3, MENU_FONT, key_font, 0,
- 0);
- menu_set(t_menu, MENU_DEFAULT, trig_mode + 1, 0);
- if ((i = (int) menu_show(t_menu, keys, event, 0)) != 0)
- trig_mode = i - 1;
- }
- else if (curr_mode == SCIENTIFIC) {
- if (s_menu == NULL)
- s_menu = menu_create(MENU_INITIAL_SELECTION, MENU_DEFAULT,
- MENU_ITEM, MENU_STRING, " Float", MENU_VALUE, 1, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, " 0 Digits", MENU_VALUE, 2, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, " 1 Digit", MENU_VALUE, 3, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, " 2 Digits", MENU_VALUE, 4, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, " 3 Digits", MENU_VALUE, 5, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, " 4 Digits", MENU_VALUE, 6, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, " 5 Digits", MENU_VALUE, 7, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, " 6 Digits", MENU_VALUE, 8, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, " 7 Digits", MENU_VALUE, 9, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, " 8 Digits", MENU_VALUE, 10, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, " 9 Digits", MENU_VALUE, 11, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, "10 Digits", MENU_VALUE, 12, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, "11 Digits", MENU_VALUE, 13, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, "12 Digits", MENU_VALUE, 14, MENU_FONT, key_font, 0,
- 0);
- menu_set(s_menu, MENU_DEFAULT, curr_width[0] + 2, 0);
- if ((i = (int) menu_show(s_menu, keys, event, 0)) != 0)
- curr_width[0] = i - 2;
- }
- else if (curr_base == BINARY) {
- if (b_menu == NULL)
- b_menu = menu_create(MENU_INITIAL_SELECTION, MENU_DEFAULT,
- MENU_ITEM, MENU_STRING, " 4 Bits", MENU_VALUE, 4, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, " 8 Bits", MENU_VALUE, 8, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, "16 Bits", MENU_VALUE, 16, MENU_FONT, key_font, 0,
- 0);
- menu_set(b_menu, MENU_DEFAULT_ITEM, menu_find(b_menu, MENU_VALUE, curr_width[1], 0), 0);
- if ((i = (int) menu_show(b_menu, keys, event, 0)) != 0)
- curr_width[1] = i;
- }
- else {
- if (h_menu == NULL)
- h_menu = menu_create(MENU_INITIAL_SELECTION, MENU_DEFAULT,
- MENU_ITEM, MENU_STRING, " 8 Bits", MENU_VALUE, 8, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, "16 Bits", MENU_VALUE, 16, MENU_FONT, key_font, 0,
- MENU_ITEM, MENU_STRING, "32 Bits", MENU_VALUE, 32, MENU_FONT, key_font, 0,
- 0);
- menu_set(h_menu, MENU_DEFAULT_ITEM, menu_find(h_menu, MENU_VALUE, curr_width[index_of(curr_base)], 0), 0);
- if ((i = (int) menu_show(h_menu, keys, event, 0)) != 0)
- curr_width[index_of(curr_base)] = i;
- }
- }
- convert_display();
- update_display();
- if (inverted)
- invert_proc();
- }
-
- do_digit(op)
-
- int op;
-
- { char temp[60];
-
- if (op <= DIGIT_F) {
- if (edit_ee && e_len > 0) {
- e_str[e_len - 3] = e_str[e_len - 2];
- e_str[e_len - 2] = e_str[e_len - 1];
- e_str[e_len - 1] = digit[op];
- }
- else if (d_len == 1 && d_str[0] == '0')
- d_str[0] = digit[op];
- else if (d_len < MAX_DIGITS) {
- d_str[d_len] = digit[op];
- d_str[++d_len] = '\0';
- }
- }
- else if (op == DIGIT_DOT) {
- if (e_len == 0 && index(d_str, '.') == 0) {
- if (d_len == 0) {
- strcpy(d_str, "0.");
- d_len = 2;
- }
- else {
- d_str[d_len] = '.';
- d_str[++d_len] = '\0';
- }
- }
- }
- else if (op == DIGIT_CHS) {
- if (edit_ee && e_len > 0)
- if (e_len == 4) {
- strcpy(e_str, e_str + 1);
- e_len = 3;
- }
- else {
- e_str[3] = e_str[2];
- e_str[2] = e_str[1];
- e_str[1] = e_str[0];
- e_str[0] = '-';
- e_len = 4;
- }
- else {
- if (d_len == 0)
- convert_stacktop();
- if (curr_mode == SCIENTIFIC) {
- if (d_len > 0 && strcmp(d_str, "0") != 0)
- if (d_str[0] == '-') {
- strcpy(d_str, d_str + 1);
- d_len -= 1;
- }
- else {
- strcpy(temp, d_str);
- d_str[0] = '-';
- strcpy(d_str + 1, temp);
- d_len += 1;
- }
- }
- else {
- convert_display();
- v_stack[v_top] = -v_stack[v_top];
- convert_stacktop();
- }
- }
- }
- else if (op == DIGIT_EE) {
- ee_mode = TRUE;
- edit_ee = !edit_ee;
- if (d_len == 0)
- convert_stacktop();
- if (e_len == 0) {
- e_len = 3;
- strcpy(e_str, "000");
- }
- }
- update_display();
- }
-
- PUBLIC clear_entry()
-
- {
- e_str[e_len = 0] = d_str[d_len = 0] = '\0';
- edit_ee = FALSE;
- }
-
- PUBLIC keyboard(key)
-
- char key;
-
- { double temp;
-
- switch (key) {
- case '0' :
- case '1' :
- case '2' :
- case '3' :
- case '4' :
- case '5' :
- case '6' :
- case '7' :
- case '8' :
- case '9' : if (curr_mode == SCIENTIFIC || (key - '0' + DIGIT_0 < curr_base))
- do_digit(blink(key - '0' + DIGIT_0));
- break;
- case 'A' :
- case 'B' :
- case 'C' :
- case 'D' :
- case 'F' : if (curr_mode == PROGRAMMER && curr_base == HEXADECIMAL)
- do_digit(blink(key - 'A' + DIGIT_A));
- break;
- case 'a' :
- case 'b' :
- case 'c' :
- case 'd' :
- case 'f' : if (curr_mode == PROGRAMMER && curr_base == HEXADECIMAL)
- do_digit(blink(key - 'a' + DIGIT_A));
- break;
- case 'e' :
- case 'E' : if (curr_mode == PROGRAMMER && curr_base == HEXADECIMAL)
- do_digit(blink(DIGIT_E));
- else if (curr_mode == SCIENTIFIC)
- do_digit(blink(DIGIT_EE));
- break;
- case 'g' :
- case 'G' : blink(EXC_OP);
- convert_display();
- do_exchange(0);
- break;
- case 'r' :
- case 'R' : blink(RCL_OP);
- clear_entry();
- do_recall(0);
- break;
- case 's' :
- case 'S' : blink(STO_OP);
- convert_display();
- do_store(0);
- break;
- case '.' : if (curr_mode == SCIENTIFIC)
- do_digit(blink(DIGIT_DOT));
- break;
- case '+' : do_binary(blink(ADD_OP));
- break;
- case '-' : do_binary(blink(SUB_OP));
- break;
- case 'x' :
- case 'X' :
- case '*' : do_binary(blink(MUL_OP));
- break;
- case '/' : do_binary(blink(DIV_OP));
- break;
- case '&' : if (curr_mode == PROGRAMMER)
- do_binary(blink(AND_OP));
- break;
- case '|' : if (curr_mode == PROGRAMMER)
- do_binary(blink(OR_OP));
- break;
- case '^' : if (curr_mode == PROGRAMMER)
- do_binary(blink(XOR_OP));
- break;
- case '\n':
- case '\r':
- case '=' : do_unary(blink(EQUAL_OP));
- break;
- case '(' : do_unary(blink(LPAREN_OP));
- break;
- case ')' : do_unary(blink(RPAREN_OP));
- break;
- }
- }
-
-