home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
msdos
/
desqview
/
calcdv.arc
/
CALCDV.C
< prev
next >
Wrap
Text File
|
1988-01-28
|
26KB
|
725 lines
/************************************************************************
* *
* A Simple Calculator for Desqview *
* *
* Written By: Phillip A. Kaufman November, 1987 *
* *
* Copyright 1987, 1988 Phillip A. Kaufman. All rights, except those *
* specifically granted herein are reserved by the author. The right *
* to copy and distribute this material is granted without fee for *
* any and all non-commercial use. This material specifically may *
* not be distributed or sold for a fee nor incorporated in whole or *
* in part into any other product that is distributed or sold for a *
* fee without specific permission of the author. To obtain special *
* permission or to report any difficulties with this material *
* contact: *
* Phillip A. Kaufman *
* 19987 Moran Lane *
* Saratoga, CA 95070 *
* *
* THIS MATERIAL IS DISTRIBUTES "as is" WITHOUT ANY EXPRESSED OR *
* IMPLIED WARRANTY OR LIABILITY FOR DIRECT, INDIRECT OR *
* CONSEQUENTIAL DAMAGES. *
************************************************************************
* Inputs: *
* Decimal Digits; 0 to 9 *
* Floating representation (+/-xxx.xxx) in decimal *
* mode only. *
* Hex digits; A to F REPRESENTED BY Function keys *
* Ops; + - * / There is full chaining of ops *
* HEX and Binary Ops: And, Or, Xor *
* No chaining of logical ops *
* Change Sign # *
* Memory; MClear, MRecall, M+, M- *
* Modes; Hex, Decimal, Binary *
* (hex and binary are integer only) *
* Clear Entry or Accum; C *
* EXIT; ESC *
************************************************************************
* CALCULATOR SCREEN IMAGE *
* *
* +------------------------------+ *
* 0 | | *
* 1 | MEMORY +-----------+ | *
* 2 | 1234567890123 1234567890123 | *
* 3 | +-----------+ | *
* 4 | | *
* 5 | MCLEAR M- DEC HEX BIN | *
* 6 | | *
* 7 | MRECALL M+ AND OR XOR | *
* 8 | | *
* 9 | A(F5) B(F6) 7 8 9 / | *
* 10 | | *
* 11 | C(F7) D(F8) 4 5 6 * | *
* 12 | | *
* 13 | E(F9) F(F10) 1 2 3 - | *
* 14 | | *
* 15 | CLEAR +/-(#) 0 . = + | *
* 16 | | *
* +------------------------------+ *
* 11111111112222222222 *
* 012345678901234567890123456789 *
* *
* *
************************************************************************/
#include <dos.h>
#include <stdio.h>
#include <setjmp.h>
#include <float.h>
#include <signal.h>
/* colors may be changed to suit user */
#define FG 0x07 /* forground color, unselected info */
#define BG 0x01 /* background color, main image */
#define HC 0x0a /* highlight color, selectable keys */
#define WF 0x00 /* answer window FG color */
#define WB 0x07 /* answer window BG color */
#define SC 0x0f /* selected info color */
#define EC 0x06 /* error color */
#define CASE case
#define DEFAULT default
#define OK 1
#define BAD 0
#define TRUE 1
#define FALSE 0
#define YES 1
#define NO 0
#define ROWS 17 /* for convenience - do not change */
#define COLS 30
#define ROW2 ROWS*2
#define COL2 COLS*2
#define attr(f,b) (char)( (((b)&0x0F) << 4) | ((f)&0x0F) ) /*make attr byte*/
#define apos(r,c) ((r)*COL2 + (c)*2) /* memory offset of r,c */
#define MEMR 2 /* memory disp row */
#define MEMC 1 /* memory disp col */
#define ACCR 2 /* accum row */
#define ACCC 16 /* accum col */
#define MEMPOS apos(MEMR,MEMC) /* memory display position */
#define ACPOS apos(ACCR,ACCC) /* accumulator display position */
#define ANSLEN 13 /* answers string length */
#define ERRR 1 /* error display row */
#define ERRC 16 /* error display col */
#define DEC 0 /* modes */
#define HEX 1
#define BIN 2
int mode = DEC; /* startup mode */
unsigned char modeloc[3][2] = {5,16, 5,21, 5,26};
unsigned char aoxloc[3][2] = {7,16, 7,21, 7,26};
/* All characters that appear statically highlighted */
unsigned char hichar[][3] = {
5,1,'M', 5,2,'C', 5,11,'M', 5,12,'-',
5,16,'D', 5,21,'H', 5,26,'B',
7,1,'M', 7,2,'R', 7,11,'M', 7,12,'+',
7,16,'A', 7,21,'O', 7,26,'X',
9,3,'F', 9,4,'5', 9,11,'F', 9,12,'6',
9,18,'7', 9,21,'8', 9,24,'9', 9,28,'/',
11,3,'F', 11,4,'7', 11,11,'F', 11,12,'8',
11,18,'4', 11,21,'5', 11,24,'6', 11,28,'*',
13,3,'F', 13,4,'9', 13,11,'F', 13,12,'1', 13,13,'0',
13,18,'1', 13,21,'2', 13,24,'3', 13,28,'-',
15,1,'C', 15,13,'#',
15,18,'0', 15,21,'.', 15,24,'=', 15,28,'+',
0,0,0}; /* end marker */
/* All characters that appear statically not highlighted */
unsigned char lochar[][3] = {
1,4,'M', 1,5,'E', 1,6,'M', 1,7,'O', 1,8,'R', 1,9,'Y',
5,3,'L', 5,4,'E', 5,5,'A',5,6,'R',
5,17,'E', 5,18,'C', 5,22,'E', 5,23,'X', 5,27,'I', 5,28,'N',
7,3,'E', 7,4,'C', 7,5,'A', 7,6,'L', 7,7,'L',
7,17,'N', 7,18,'D', 7,22,'R', 7,27,'O', 7,28,'R',
9,1,'A', 9,2,'(', 9,5,')', 9,9,'B', 9,10,'(', 9,13,')',
11,1,'C', 11,2,'(', 11,5,')', 11,9,'D', 11,10,'(', 11,13,')',
13,1,'E', 13,2,'(', 13,5,')', 13,9,'F', 13,10,'(', 13,14,')',
15,2,'L', 15,3,'E', 15,4,'A', 15,5,'R',
15,9,'+', 15,10,'/', 15,11,'-', 15,12,'(', 15,14,')',
0,0,0};
#define ERRLEN 11 /* number of chars in error msgs */
char OVERFLOW[] = "OVERFLOW "; /* error messages */
char ZERODIV[] = "DIVIDE BY 0";
char BADKEY[] = "ILLEGAL KEY";
char FORMATERR[]= "FORMAT ERR ";
char ENTLENGTH[]= "# TOO LONG ";
char DISPOV[] = "# TOO BIG ";
char NOERR[] = " ";
char *errptr; /* ptr to current error msg */
union REGS rg; /* cpu regs */
struct SREGS segregs;
union{
long l;
unsigned char far *p;
} addr;
char entry[ANSLEN+2]; /* entry string */
double faccum = 0.0; /* accumulator */
double fsave = 0.0; /* save for chaining */
double ftemp; /* temp for calculations */
double fmemacc = 0.0; /* memory accumulator */
char c; /* input key */
int oper; /* last operator entered */
int memop; /* last memory operator */
int equ; /* an equal sign seen */
int collect; /* collecting digits */
int recall; /* just did memory recall */
#define MEMOP 0
#define ACCOP 1
int optype; /* acc or mem for fp recovery */
int fphandler(); /* take care of floating errors */
jmp_buf mark;
main()
{
register int i;
dvinit(); /* check dv, get display addr */
setrattr(attr(FG,BG),0,0,ROWS-1,COLS-1); /* full window attributes */
setrattr(attr(WF,WB),ACCR,ACCC,ACCR+1,ACCC+ANSLEN-1);
/* answer window attr */
setrattr(attr(EC,WB),ERRR,ERRC,ERRR,ERRC+ANSLEN-1);
/* answer window attr,err */
setrattr(attr(WF,WB),MEMR,MEMC,MEMR,MEMC+ANSLEN-1);
/* mem answer window attr */
dispca(attr(HC,BG),hichar); /* static highlight chars */
dispca(attr(FG,BG),lochar); /* static normal chars */
errptr = NOERR; /* start error free */
signal(SIGFPE,fphandler);
if (setjmp(mark) == -1 ){ /* here on fp error return */
if (optype == ACCOP) faccum = 0.0;
if (optype == MEMOP) fmemacc = 0.0;
doerr();
}
oper = '\0';
memop = '\0';
equ = NO;
collect = NO;
recall = NO;
optype = ACCOP;
/* input scanner and computations */
while(1) {
display(); /* show accum and mem value */
setmode(); /* show current mode */
memop = '\0';
c = getch(); /* wait, get char */
c = toupper(c);
errptr = BADKEY; /* assume bad key */
if ( c == 'M'){ /* memory ops */
errptr = NOERR;
c = getch();
c = toupper(c);
switch (c) {
CASE '+': /* M+ or M- get pushed as = */
CASE '-':
memop = c;
c = '=';
break;
CASE 'C': /* MCLEAR */
fmemacc = 0.0;
c = 0xFF; /* don't want to see C again */
break;
CASE 'R': /* MRECALL */
if (equ == NO) fsave = faccum;
faccum = fmemacc;
recall = YES; /* fake any entry */
collect = YES;
break;
DEFAULT:
errptr = BADKEY; /* bad key */
c = 0xFF; /* bad key sequence */
}
}
switch (c) {
CASE 0x1B: /* ESC ==> exit */
exit(0);
CASE '#': /* Change Sign */
errptr = NOERR;
faccum = - faccum;
break;
CASE 'B': /* binary mode */
errptr = NOERR;
mode = BIN;
collect = NO;
recall = NO;
break;
CASE 'C': /* clear entry or accumulator */
errptr = NOERR;
if (collect){
faccum = 0.0;
}
else {
faccum = 0.0;
fsave = 0.0;
oper = '\0';
equ = NO;
}
collect = NO;
recall = NO;
break;
CASE 'D': /* set decimal mode */
errptr = NOERR;
if (oper == 'A' || oper == 'O' || oper == 'X')
oper = '\0';
mode = DEC;
collect = NO;
recall = NO;
break;
CASE 'H': /* set hex mode */
errptr = NOERR;
mode = HEX;
collect = NO;
recall = NO;
break;
CASE 'A': /* logicals stack for = */
CASE 'O':
CASE 'X':
if (mode != DEC){ /* no decimal logicals */
collect = NO;
recall = NO;
errptr = NOERR;
oper = c;
equ = NO;
}
break;
CASE '+':
CASE '-':
CASE '*': /* standard ops */
CASE '/':
errptr = NOERR;
if (equ == NO && collect){ /* a pending op to do */
ftemp = faccum;
switch (oper) {
CASE '*':
faccum *= fsave;
break;
CASE '/':
if (faccum == 0.0)
errptr = ZERODIV;
else faccum = fsave / faccum;
break;
CASE '+':
faccum += fsave;
break;
CASE '-':
faccum = fsave - faccum;
}
fsave = ftemp;
}
collect = NO;
recall = NO;
oper = c;
equ = NO;
break;
CASE '=': /* execute and chain operations */
errptr = NOERR;
if (equ == NO || (collect && equ)){ /* pending op or
pending entry */
ftemp = faccum;
switch (oper){
CASE 'A':
faccum = (double)
((long)fsave & (long)faccum);
break;
CASE 'O':
faccum = (double)
((long)fsave | (long)faccum);
break;
CASE 'X':
faccum = (double)
((long)fsave ^ (long)faccum);
break;
CASE '*':
ftemp = fsave;
if ((collect == NO) && (equ == NO))
faccum *= faccum;
else
faccum *= fsave;
break;
CASE '/':
if ((collect == NO) && (equ == NO))
faccum = 1 / faccum;
else if (equ){
if (fsave == 0.0){
errptr = ZERODIV;
faccum = 0.0;
}
else faccum = faccum / fsave;
}
else {
if (faccum == 0.0){
errptr = ZERODIV;
faccum = 0.0;
}
else faccum = fsave / faccum;
}
break;
CASE '+':
faccum += fsave;
break;
CASE '-':
if (equ)
faccum = faccum - fsave;
else
faccum = fsave - faccum;
}
}
if (equ == NO)
fsave = ftemp;
equ = YES;
collect = NO;
recall = NO;
switch (memop){
CASE '\0':
break;
CASE '+':
optype = MEMOP;
fmemacc = faccum + fmemacc;
optype = ACCOP;
break;
CASE '-':
optype = MEMOP;
fmemacc = fmemacc - faccum;
optype = ACCOP;
}
memop = '\0';
break;
CASE '0':
CASE '1':
addchar();
break;
CASE '2':
CASE '3':
CASE '4':
CASE '5':
CASE '6':
CASE '7':
CASE '8':
CASE '9':
if ( mode != BIN) {
addchar();
break;
}
CASE '\0': /* special keys */
c = getch(); /* get 2nd part */
if (mode != HEX) break;
if ( c == 0x3F) c = 'A'; /* function key 5 */
else if (c == 0x40) c = 'B'; /* f6 */
else if (c == 0x41) c = 'C'; /* f7 */
else if (c == 0x42) c = 'D'; /* f8 */
else if (c == 0x43) c = 'E'; /* f9 */
else if (c == 0x44) c = 'F'; /* f10 */
else break;
addchar();
break;
CASE '.':
if (mode != DEC) break;
addchar();
break;
CASE 0x53: /* DEL (since follows 0 - not S) */
CASE 0x08: /* Back Space */
errptr = NOERR;
if (collect == YES) {
c = '\0'; /* delete flag */
addchar();
}
}
}
}
/* set attributes for rectangle */
setrattr(attrib, ulr, ulc, lrr, lrc)
unsigned char attrib,ulr,ulc,lrr,lrc;
{
unsigned char far *ptr;
register int i, j;
for ( i = ulr; i < lrr+1; i++){ /* rows counter */
ptr = addr.p + 1 + apos(i,ulc);
for ( j = ulc; j < lrc+1; j++){ /* column position */
*ptr = attrib;
ptr = ptr + 2;
}
}
return;
}
/* display an array of characters with attributes */
dispca(attrib,array)
unsigned char attrib;
unsigned char *array;
{
unsigned char far *ptr;
while (*(array) != 0 && *(array+1) != 0){
ptr = addr.p + apos( *array,*(array+1) );
*ptr = *(array+2);
ptr++;
*ptr = attrib;
array = array +3;
}
return;
}
setmode()
{
int i, mattr;
for ( i = 0; i < 3; i++){
setrattr(attr(HC,BG),modeloc[i][0],modeloc[i][1],modeloc[i][0],
modeloc[i][1]); /* highlight 1st mode letr*/
setrattr(attr(FG,BG),modeloc[i][0],modeloc[i][1]+1,
modeloc[i][0], modeloc[i][1]+2); /* lowlight rest */
}
setrattr(attr(SC,BG),modeloc[mode][0],modeloc[mode][1],
modeloc[mode][0], modeloc[mode][1]+2);
/* highlight select mode word */
if (mode == DEC) mattr = attr(FG,BG);
else mattr = attr(HC,BG);
for ( i = 0; i < 3; i++){ /* set allowed and/or/xor command */
setrattr(mattr,aoxloc[i][0],aoxloc[i][1],
aoxloc[i][0],aoxloc[i][1]);
}
return;
}
addchar() /* check and put an input character on entry string */
{
register int i;
int elen;
double base; /* base for conversion */
double atof(); /* return types */
static int dpoint; /* saw a dp on this sequence */
if (recall == YES) return; /* can't modify mem recall */
errptr = NOERR;
if (collect == NO){ /* first char of entry so clear it out */
if (equ == NO) fsave = faccum;
faccum = 0.0;
entry[0] = '\0';
dpoint = 0;
}
collect = YES;
elen = strlen(entry);
if (dpoint == 0 && entry[elen-1] == '.') entry[--elen] = '\0';
if ( c != '\0'){ /* check length on additions */
if ( (mode == HEX && elen == 8) ||
(mode == DEC && dpoint == 0 && elen == ANSLEN -2) ||
(elen == ANSLEN -1) ){
errptr = ENTLENGTH;
return;
}
}
if (c == '.'){
if (dpoint == 0) dpoint++;
else {
errptr = FORMATERR;
return;
}
}
if (c == '\0'){ /* delete a char */
if (elen != 0){
if (entry[--elen] == '.') dpoint--;
entry[elen] = '\0';
if (elen == 0) { /* if last char del, set "0" */
entry[0] = '0';
elen = 1;
}
}
}
else { /* add a char */
if (elen == 1 && entry[0] == '0'){
if (c == '0') return; /* no extra leading zeros */
else elen--; /* take off leading zero */
}
entry[elen++] = c;
entry[elen] = '\0';
}
if (mode == DEC) {
faccum = atof(entry);
}
else {
if (mode == HEX) base = 16.0;
if (mode == BIN) base = 2.0;
faccum = 0.0;
for ( i = 0; i < elen; i++){
faccum = faccum * base + ( (entry[i]<0x40)?
entry[i] - 0x30 : entry[i] - 0x41 + 10 );
}
}
return;
}
/* update memory and accum display */
display()
{
char abuf[30];
char mbuf[30];
char tbuf[30];
unsigned char far *ptr;
register int i,j;
long int lint;
if (mode == DEC){
if (collect == NO || recall == YES){
sprintf(abuf,"% #12.11lf",faccum);
ffixup(abuf);
}
optype = MEMOP;
sprintf(mbuf,"% #12.11lf",fmemacc);
ffixup(mbuf);
optype = ACCOP;
}
else if (mode == HEX) {
if (collect == NO || recall ==YES){
lint = faccum;
faccum = (double)lint;
sprintf(abuf,"%13lX",lint);
}
optype = MEMOP;
lint = (long)fmemacc;
fmemacc = (double)lint;
sprintf(mbuf,"%13lX",lint);
optype = ACCOP;
}
else {
if (collect == NO || recall == YES){
i = (int)faccum;
faccum = (double)i;
itoa(i, tbuf, 2);
sfixup (tbuf, abuf);
}
optype = MEMOP;
i = (int)(fmemacc);
fmemacc = (double)i;
itoa(i, tbuf, 2);
sfixup (tbuf, mbuf);
optype = ACCOP;
}
if (collect == YES && recall == NO)
sfixup (entry, abuf); /* display entry string */
ptr = addr.p + MEMPOS;
for (i = 0; i < 13; i++){
*ptr = mbuf[i];
ptr = ptr + 2;
}
ptr = addr.p + ACPOS;
for (i = 0; i < 13; i++){
*ptr = abuf[i];
ptr = ptr + 2;
}
doerr();
return;
}
ffixup(buf) /* display fixup for floating point */
char *buf;
{
register int i, dotpos, zeros;
char temp[14];
for (i = 0; i <13 && buf[i] != '.'; i++);
dotpos = i;
if (dotpos >12){
errptr = DISPOV;
buf[12] = '>';
buf[13] = '\0';
doerr();
return;
}
for (i = 12; i >1 && buf[i] == '0'; i--);
if (i < 12){
zeros = 12 - i; /* number of trailing zeros */
temp[0] = buf[0];
for (i = 1; i <= zeros; i++)
temp[i] = ' ';
for (; i <13; i++)
temp[i] = buf[i-zeros];
strcpy (buf,temp);
}
return;
}
sfixup(tbuf,obuf) /* display fixup for strings */
char *tbuf, *obuf;
{
int x;
register int i,j;
x = strlen(tbuf);
if (x > ANSLEN) { /* too long, display with ">" */
errptr = DISPOV;
strncpy (obuf, tbuf, ANSLEN-1);
obuf[ANSLEN-1] = '>';
}
else { /* right justify if short */
for (i = 0; i < ANSLEN-x; i++) obuf[i] = ' ';
for (j = 0; i < ANSLEN; i++,j++) obuf[i] = tbuf[j];
}
return;
}
doerr() /* update display of error string */
{
unsigned char far *ptr;
register int i;
ptr = addr.p + apos(ERRR,ERRC+1);
for (i = 0; i < ERRLEN ; i++){
*ptr = *(errptr+i);
ptr = ptr + 2;
}
return(OK);
}
dvinit() /* Check for Desqview and use its buffer */
{
rg.x.ax = 0x2B01; /* do date set as DV check */
rg.x.cx = 0x4445; /* "DESQ"an illegal date */
rg.x.dx = 0x5351;
int86(0x21,&rg,&rg);
if (rg.h.al != 0xFF){ /* we are in desqview */
rg.h.ah = 0xFE; /* dv get buff addr */
int86(0x10,&rg,&rg);
segread(&segregs);
addr.l=((unsigned long)segregs.es<<16)+(unsigned long)rg.x.di;
}
else {
cputs ("\x07Program requires DESQview!\n");
exit(1);
}
/* put the cursor outside the window */
rg.h.ah = 0x2;
rg.h.bh = 0;
rg.x.dx = 0x151f; /* row 24 col 79*/
int86(0x10,&rg,&rg);
return;
}
int fphandler(sig,num)
int sig,num;
{
if (num == FPE_ZERODIVIDE) errptr = ZERODIV;
else errptr = OVERFLOW;
doerr();
_fpreset();
longjmp(mark,-1);
}
_setargv() /* dummy since we use no command line args */
{
}
_setenvp() /* dummy since we don't use environment variables */
{
}