home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / calculat / rpn30src.zip / DISPLAY.C < prev    next >
C/C++ Source or Header  |  1990-05-30  |  7KB  |  282 lines

  1. /*
  2.  * DISPLAY
  3.  *
  4.  * Maintain the calculator-display window.
  5.  *
  6.  * 90.05.23 v3.0
  7.  *    Optional savefile-output added.
  8.  *    Tweaks to the register-display formats.
  9.  */
  10.  
  11. #include <conio.h>
  12. #include <math.h>       /** needed for pow() & log10() **/
  13. #include <float.h>
  14. #include <string.h>
  15. #include "rpn.h"
  16. #include "display.h"
  17. #include "debug.h"
  18.  
  19. #define min(a,b)    ((a) < (b) ? (a) : (b))
  20. #define max(a,b)    ((a) > (b) ? (a) : (b))
  21.  
  22. #include <setjmp.h>
  23. #include <signal.h>
  24.  
  25. static jmp_buf jb;
  26.  
  27. #pragma warn -par
  28. static void fpe(int sig, int type, int *reglist)
  29. {
  30.     _clear87();
  31.     longjmp(jb,1);
  32. }
  33. #pragma warn .par
  34.  
  35. /*
  36. | Determine the number of decimal places to show.  If this is negative,
  37. | it means that fixed format won't work.
  38. */
  39. static int format_size(double reg, int marks)
  40. {
  41.     int p;
  42.  
  43.     if (setjmp(jb) != 0)
  44.     return (-pre);
  45.     signal(SIGFPE,fpe);
  46.  
  47.     if (0.0 == reg)
  48.     return pre;
  49.  
  50. #if 0
  51.     p = (int)log10(fabs(reg));    /* minimum distance, decimal pt. to digit */
  52. #endif
  53.     frexp(reg, &p);        /* minimum distance, decimal pt. to digit */
  54.     signal(SIGFPE,SIG_DFL);
  55.  
  56.     if (p >= 0) {        /* whole number */
  57.     p = (STK_WIDTH - marks) - p;
  58.     return min(p, pre);
  59.     }
  60.     p = -p;            /* ...fraction */
  61.     if (p > (STK_WIDTH - marks))
  62.     return (-pre);
  63.  
  64.     return max(p, pre);
  65. }
  66.  
  67. /*
  68.  * In the following format strings, 21 is the stack display width,
  69.  * also #define'd as STK_WIDTH.  TurboC won't accept macros in strings.
  70.  */
  71.  
  72. static char fix_fmt[] =
  73.     "%#21.*le%#21.*le%#21.*le"
  74.     " ─fix─────────────── "
  75.     "%21.*lf\r\n"
  76.     "%#21.*le";
  77.  
  78. static char sci_fmt[] =
  79.     "%#21.*le%#21.*le%#21.*le"
  80.     " ─sci─────────────── "
  81.     "%21.*le\r\n"
  82.     "%#21.*le";
  83.  
  84. static char def_fmt[] =
  85.     "%#21.*lg%#21.*lg%#21.*lg"
  86.     " ─default─────────── "
  87.     "%#21.*lg\r\n"
  88.     "%#21.*lg";
  89.  
  90. static char hex_fmt[] =
  91.     "%#21lx%#21lx%#21lx"
  92.     " ─hex─────────────── "
  93.     "%#21lx\r\n"
  94.     "%#21lx";
  95.  
  96. static char oct_fmt[] =
  97.     "%#21lo%#21lo%#21lo"
  98.     " ─oct─────────────── "
  99.     "%#21lo\r\n"
  100.     "%#21lo";
  101.  
  102. static char ftn_fmt[] =
  103.     "%-13.13s\r\n"
  104.     "──────────── \r\n"
  105.     "%-13.13s";
  106.  
  107. static char *fmtlst[] = { fix_fmt, sci_fmt, def_fmt, hex_fmt, oct_fmt };
  108.  
  109. /* ///////////////////////////////////////////////////////////////////// */
  110. /*
  111. | Build the function-string and stack-string displays, then output
  112. | them along with the Base and trig-mode/ScrollLock indicators.
  113. | If a savefile is active, also print out parts of the strings.
  114. */
  115. static char stk_string[130];    /* plenty of room for the stack window   */
  116. static char ftn_string[45];    /* enough for the `last/this ftn' window */
  117.  
  118. void display(void)
  119. {
  120.     int t, z, y, x, l;        /* control the register display widths   */
  121.     int  f;            /* index to the needed stack format      */
  122.  
  123.     /*
  124.     | Build the last/current functions display.
  125.     */
  126.     sprintf(ftn_string, ftn_fmt, lastfunct, thisfunct);
  127.  
  128.  
  129.     /*
  130.     | Build the stack display.  If the stack can't be shown in the current
  131.     | base, force the base back to 10.  Then choose an appropriate format.
  132.     */
  133.     if ( (base != 10)  &&  (xreg>MAXLONG || yreg>MAXLONG
  134.             || zreg>MAXLONG || treg>MAXLONG || lastx>MAXLONG) )
  135.     {
  136.         base = 10;
  137.         show_base(1); /** 1 means "blink the base" **/
  138.     }
  139.  
  140.     /*
  141.     | The assignments in the following are sure to work.  They are
  142.     | there to provide the "if" possibilities with shared final code.
  143.     */
  144. #pragma warn -pia
  145.     if ( ((16 == base) && (f = 3))
  146.         || ((8 == base) && (f = 4)) )
  147.     {
  148.         sprintf(stk_string, fmtlst[f], (long)treg, (long)zreg,
  149.                 (long)yreg, (long)xreg, (long)lastx);
  150.     }
  151. #pragma warn .pia
  152.     else {
  153.     if ( 0 > (t = format_size(treg,STK_MARKS)) )
  154.         t = pre;
  155.     if ( 0 > (z = format_size(zreg,STK_MARKS)) )
  156.         z = pre;
  157.     if ( 0 > (y = format_size(yreg,STK_MARKS)) )
  158.         y = pre;
  159.     if ( 0 > (l = format_size(lastx,STK_MARKS)) )
  160.         l = pre;
  161.  
  162.     f = notation;
  163.     if (newnum) {
  164.         x = format_size(xreg,4);
  165.         if (x <= 0) {
  166.         x = pre;
  167.         f = 2;
  168.         }
  169.     } else {
  170.         x = num_ct;
  171.         if (x > 17) {
  172.         x = 17;
  173.         f = 2;
  174.         }
  175.     }
  176.         sprintf(stk_string, fmtlst[f],
  177.         t, treg, z, zreg, y, yreg, x, xreg, l, lastx);
  178.     }
  179.  
  180.     /*
  181.     | Output the function and stack displays.
  182.     */
  183.     window(F_LEFT, F_TOP, F_RIGHT, F_BOTTOM);
  184.     textcolor(D_FTN);
  185.     cputs(ftn_string);
  186.  
  187.     window(S_LEFT, S_TOP, S_RIGHT, S_BOTTOM);
  188.     textcolor(D_NUM);
  189.     if (negative && (10 != base))
  190.     *(stk_string + 84) = '-';
  191.     cputs(stk_string);
  192.  
  193.     /*
  194.     | Show the trigonometry mode, or scroll-lock status.
  195.     */
  196.     window(LEFT+32, BOTTOM-1, RIGHT, BOTTOM);
  197.     if (orig_sl != scrolllock) {
  198.     textcolor(D_OOPS);
  199.     cputs("SCRL");
  200.     } else {
  201.     textcolor(D_FTN);
  202.     cputs (trig_mode == RADIANS  ?  "Rad."  :  "Deg.");
  203.     }
  204.  
  205.     window(V_LEFT, S_TOP, V_RIGHT, S_TOP);
  206.     textcolor(D_NUM);
  207.     cputs(savefile  ?  "Save"  :  "    ");
  208.  
  209.     /*
  210.     | v3.0 - If a savefile is in use, dump the current function and
  211.     | Y, X, & LastX registers to the file.
  212.     */
  213.     if (NULL != savefile && write_save) {
  214.     *(stk_string + 64) = (*(ftn_string + 15) = 0);
  215.     *(stk_string + 105) = '\r';
  216.     *(stk_string + 106) = '\n';
  217.     fprintf(savefile, "%sy: %s  x: %s : LastX\r\n",
  218.         ftn_string, stk_string+42, stk_string+84);
  219.     write_save = FALSE;
  220.     }
  221. }
  222.  
  223. /* /////////////////////////////////////////////////////////////////////// */
  224.  
  225. void show_base(int err)
  226. {
  227.     char string[8];
  228.  
  229.     sprintf(string, "%3d", base);
  230.     window(B_LEFT, S_TOP, B_RIGHT, S_TOP);
  231.     textcolor( (err ? BLINK : 0)
  232.           + ((base==10 || base==16 || base==8) ? D_FTN : D_OOPS) );
  233.     cputs(string);
  234. }
  235.  
  236. /* /////////////////////////////////////////////////////////////////////// */
  237. /*
  238. | v3.0: Add savefile output.
  239. | version 2:  All references to cprintf() are replaced by sprintf()/cputs().
  240. | For this one, just jam out the message a piece at a time.
  241. */
  242. void prterr(const char *a, const char *b)
  243. {
  244.     window(LEFT+1, MSG_LINE, RIGHT, MSG_LINE+1);
  245.     textcolor(D_OOPS);
  246.     putch(' ');
  247.     cputs(a);
  248.     putch(' ');
  249.     cputs(b);
  250.     cputs(" error ");
  251.     DBG_FPRINTF((errfile,"prterr: %s\nprterr: %s\n\n", a, b));
  252.     /*
  253.     | v3.0 - If a savefile is in use, write out the error.
  254.     */
  255.     if (NULL != savefile) {
  256.     fprintf(savefile, "ERROR - %s %s\r\n", a, b);
  257.     }
  258. }
  259.  
  260. /* /////////////////////////////////////////////////////////////////////// */
  261.  
  262. /*
  263. | disp_buf saves the portion of the original screen that the
  264. |   calculator display overwrites.
  265. */
  266. static char disp_buf[ 2 * D_WIDTH * D_DEPTH ];
  267.  
  268. void open_display(void)
  269. {
  270.     /** Save original screen **/
  271.     gettext(LEFT, TOP, RIGHT, BOTTOM, (void *)disp_buf);
  272.     puttext(LEFT, TOP, RIGHT, BOTTOM, (void *)frame);
  273.     show_base(0);
  274.     display();
  275. }
  276. /* / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / */
  277.  
  278. void close_display(void) {
  279.     puttext(LEFT, TOP, RIGHT, BOTTOM, disp_buf);
  280. }
  281. /* /////////////////////////////////////////////////////////////////////// */
  282.