home *** CD-ROM | disk | FTP | other *** search
- /*
- * DISPLAY
- *
- * Maintain the calculator-display window.
- *
- * 90.05.23 v3.0
- * Optional savefile-output added.
- * Tweaks to the register-display formats.
- */
-
- #include <conio.h>
- #include <math.h> /** needed for pow() & log10() **/
- #include <float.h>
- #include <string.h>
- #include "rpn.h"
- #include "display.h"
- #include "debug.h"
-
- #define min(a,b) ((a) < (b) ? (a) : (b))
- #define max(a,b) ((a) > (b) ? (a) : (b))
-
- #include <setjmp.h>
- #include <signal.h>
-
- static jmp_buf jb;
-
- #pragma warn -par
- static void fpe(int sig, int type, int *reglist)
- {
- _clear87();
- longjmp(jb,1);
- }
- #pragma warn .par
-
- /*
- | Determine the number of decimal places to show. If this is negative,
- | it means that fixed format won't work.
- */
- static int format_size(double reg, int marks)
- {
- int p;
-
- if (setjmp(jb) != 0)
- return (-pre);
- signal(SIGFPE,fpe);
-
- if (0.0 == reg)
- return pre;
-
- #if 0
- p = (int)log10(fabs(reg)); /* minimum distance, decimal pt. to digit */
- #endif
- frexp(reg, &p); /* minimum distance, decimal pt. to digit */
- signal(SIGFPE,SIG_DFL);
-
- if (p >= 0) { /* whole number */
- p = (STK_WIDTH - marks) - p;
- return min(p, pre);
- }
- p = -p; /* ...fraction */
- if (p > (STK_WIDTH - marks))
- return (-pre);
-
- return max(p, pre);
- }
-
- /*
- * In the following format strings, 21 is the stack display width,
- * also #define'd as STK_WIDTH. TurboC won't accept macros in strings.
- */
-
- static char fix_fmt[] =
- "%#21.*le%#21.*le%#21.*le"
- " ─fix─────────────── "
- "%21.*lf\r\n"
- "%#21.*le";
-
- static char sci_fmt[] =
- "%#21.*le%#21.*le%#21.*le"
- " ─sci─────────────── "
- "%21.*le\r\n"
- "%#21.*le";
-
- static char def_fmt[] =
- "%#21.*lg%#21.*lg%#21.*lg"
- " ─default─────────── "
- "%#21.*lg\r\n"
- "%#21.*lg";
-
- static char hex_fmt[] =
- "%#21lx%#21lx%#21lx"
- " ─hex─────────────── "
- "%#21lx\r\n"
- "%#21lx";
-
- static char oct_fmt[] =
- "%#21lo%#21lo%#21lo"
- " ─oct─────────────── "
- "%#21lo\r\n"
- "%#21lo";
-
- static char ftn_fmt[] =
- "%-13.13s\r\n"
- "──────────── \r\n"
- "%-13.13s";
-
- static char *fmtlst[] = { fix_fmt, sci_fmt, def_fmt, hex_fmt, oct_fmt };
-
- /* ///////////////////////////////////////////////////////////////////// */
- /*
- | Build the function-string and stack-string displays, then output
- | them along with the Base and trig-mode/ScrollLock indicators.
- | If a savefile is active, also print out parts of the strings.
- */
- static char stk_string[130]; /* plenty of room for the stack window */
- static char ftn_string[45]; /* enough for the `last/this ftn' window */
-
- void display(void)
- {
- int t, z, y, x, l; /* control the register display widths */
- int f; /* index to the needed stack format */
-
- /*
- | Build the last/current functions display.
- */
- sprintf(ftn_string, ftn_fmt, lastfunct, thisfunct);
-
-
- /*
- | Build the stack display. If the stack can't be shown in the current
- | base, force the base back to 10. Then choose an appropriate format.
- */
- if ( (base != 10) && (xreg>MAXLONG || yreg>MAXLONG
- || zreg>MAXLONG || treg>MAXLONG || lastx>MAXLONG) )
- {
- base = 10;
- show_base(1); /** 1 means "blink the base" **/
- }
-
- /*
- | The assignments in the following are sure to work. They are
- | there to provide the "if" possibilities with shared final code.
- */
- #pragma warn -pia
- if ( ((16 == base) && (f = 3))
- || ((8 == base) && (f = 4)) )
- {
- sprintf(stk_string, fmtlst[f], (long)treg, (long)zreg,
- (long)yreg, (long)xreg, (long)lastx);
- }
- #pragma warn .pia
- else {
- if ( 0 > (t = format_size(treg,STK_MARKS)) )
- t = pre;
- if ( 0 > (z = format_size(zreg,STK_MARKS)) )
- z = pre;
- if ( 0 > (y = format_size(yreg,STK_MARKS)) )
- y = pre;
- if ( 0 > (l = format_size(lastx,STK_MARKS)) )
- l = pre;
-
- f = notation;
- if (newnum) {
- x = format_size(xreg,4);
- if (x <= 0) {
- x = pre;
- f = 2;
- }
- } else {
- x = num_ct;
- if (x > 17) {
- x = 17;
- f = 2;
- }
- }
- sprintf(stk_string, fmtlst[f],
- t, treg, z, zreg, y, yreg, x, xreg, l, lastx);
- }
-
- /*
- | Output the function and stack displays.
- */
- window(F_LEFT, F_TOP, F_RIGHT, F_BOTTOM);
- textcolor(D_FTN);
- cputs(ftn_string);
-
- window(S_LEFT, S_TOP, S_RIGHT, S_BOTTOM);
- textcolor(D_NUM);
- if (negative && (10 != base))
- *(stk_string + 84) = '-';
- cputs(stk_string);
-
- /*
- | Show the trigonometry mode, or scroll-lock status.
- */
- window(LEFT+32, BOTTOM-1, RIGHT, BOTTOM);
- if (orig_sl != scrolllock) {
- textcolor(D_OOPS);
- cputs("SCRL");
- } else {
- textcolor(D_FTN);
- cputs (trig_mode == RADIANS ? "Rad." : "Deg.");
- }
-
- window(V_LEFT, S_TOP, V_RIGHT, S_TOP);
- textcolor(D_NUM);
- cputs(savefile ? "Save" : " ");
-
- /*
- | v3.0 - If a savefile is in use, dump the current function and
- | Y, X, & LastX registers to the file.
- */
- if (NULL != savefile && write_save) {
- *(stk_string + 64) = (*(ftn_string + 15) = 0);
- *(stk_string + 105) = '\r';
- *(stk_string + 106) = '\n';
- fprintf(savefile, "%sy: %s x: %s : LastX\r\n",
- ftn_string, stk_string+42, stk_string+84);
- write_save = FALSE;
- }
- }
-
- /* /////////////////////////////////////////////////////////////////////// */
-
- void show_base(int err)
- {
- char string[8];
-
- sprintf(string, "%3d", base);
- window(B_LEFT, S_TOP, B_RIGHT, S_TOP);
- textcolor( (err ? BLINK : 0)
- + ((base==10 || base==16 || base==8) ? D_FTN : D_OOPS) );
- cputs(string);
- }
-
- /* /////////////////////////////////////////////////////////////////////// */
- /*
- | v3.0: Add savefile output.
- | version 2: All references to cprintf() are replaced by sprintf()/cputs().
- | For this one, just jam out the message a piece at a time.
- */
- void prterr(const char *a, const char *b)
- {
- window(LEFT+1, MSG_LINE, RIGHT, MSG_LINE+1);
- textcolor(D_OOPS);
- putch(' ');
- cputs(a);
- putch(' ');
- cputs(b);
- cputs(" error ");
- DBG_FPRINTF((errfile,"prterr: %s\nprterr: %s\n\n", a, b));
- /*
- | v3.0 - If a savefile is in use, write out the error.
- */
- if (NULL != savefile) {
- fprintf(savefile, "ERROR - %s %s\r\n", a, b);
- }
- }
-
- /* /////////////////////////////////////////////////////////////////////// */
-
- /*
- | disp_buf saves the portion of the original screen that the
- | calculator display overwrites.
- */
- static char disp_buf[ 2 * D_WIDTH * D_DEPTH ];
-
- void open_display(void)
- {
- /** Save original screen **/
- gettext(LEFT, TOP, RIGHT, BOTTOM, (void *)disp_buf);
- puttext(LEFT, TOP, RIGHT, BOTTOM, (void *)frame);
- show_base(0);
- display();
- }
- /* / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / */
-
- void close_display(void) {
- puttext(LEFT, TOP, RIGHT, BOTTOM, disp_buf);
- }
- /* /////////////////////////////////////////////////////////////////////// */
-