home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mega CD-ROM 1
/
megacd_rom_1.zip
/
megacd_rom_1
/
MATH
/
RPN30SRC.ZIP
/
DISPLAY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-30
|
7KB
|
282 lines
/*
* 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);
}
/* /////////////////////////////////////////////////////////////////////// */