Category : C Source Code
Archive   : 3TCTGR.ZIP
Filename : TSRCALC.C

 
Output of file : TSRCALC.C contained in archive : 3TCTGR.ZIP
/* TSRCALC.C 12/10/87 Version 1.00
*
* Written By Mark E Johnson
* 2272-F Benson Avenue
* St. Paul, MN 55116
* (612)-698-3686
*
* COPYRIGHT 1987 MARK E JOHNSON. ALL RIGHTS RESERVED
*
* The windows library WINDOWS.INC was taken from the public domain, and
* modified for my use with TurboC from a Lattice C environment. Credit
* is due to the writer, whose identity is unknown.
*
* Compile this with TURBO C. Use the LARGE MODEL ONLY!
* Set MODEL to LARGE
* Set STACK CHECKING OFF
* Set STANDARD STACK FRAME OFF
* Set FLOATING POINT EMULATION (I'm not saving the 8087 context here)
*
* This program installs itself as a resident process. It monitors
* the status of the shift and Alt keys. When you hit Alt-lShift-rShift,
* the program checks the state of DOS's 'critical' flag. If the flag
* indicates no DOS calls are in progress, then the function 'service()'
* will be executed. If the flag indicates that DOS IO is not safe,
* then this program will check at each timer tick and wait to execute
* 'service()'.
*/

/* ----------- INCLUDES ----------- */

#include
#include
#include "window.h"

/* ----------- FUNCTION PROTOTYPES ----------- */

void interrupt tickhandler();
void sound(int , int );
int safe();
void prtint(int, char *, unsigned int);
unsigned int get_psp();
void set_psp(unsigned );
void service(void);

/* ----------- DEFINES ----------- */

#define RSHIFT 1
#define LSHIFT 2
#define ALT 8
#define TESTIT (RSHIFT | LSHIFT | ALT)
#define TICKINT 8
#define NEWTICK 0x50
#define INT28OLD 0x28
#define INT28NEW 0x51
#define FINI 0x5A
#define TRUE 1
#define FALSE 0
#define ESCAPE 0x1B

/* ----------- TYPEDEFS ----------- */

typedef struct { /* MSDOS allocation header format */
char flag; /* 0x5a=end, 0x4a=not end */
unsigned nextpsp, paragraphs;
} HEAD;

/* ----------- VARIABLES ----------- */

union REGS regs;
struct SREGS segregs;

HEAD *header;

extern unsigned _psp; /* Segment address of this programs PSP */
unsigned meminstall; /* Paragraphs of free memory */
char intable[0x400]; /* Buffer of Interrupt table */
char *shiftptr = (char *)0x417L; /* DOS's Shift key status byte */
char *safety_flag;
char **newtick, **oldtick; /* char is just a convenience. */
int hold_service = 0; /* if true, then service routine is running */
char **new28, **old28; /* Vectors for INT 28 */
int wait = 0; /* If > 0 then hot key was pressed, but the
'critical flag' indicates it's not safe
to do DOS I/O */

/* USED FOR DEBUGGING PURPOSES */

int i;
int call28 = 0;

char *bp_pointer;
char bp_value;

char hi_bp = 0;
char lo_bp = 126;

/* Holders for local PSP and current PSP */

unsigned int my_psp, callers_psp;

/* ----- Variables used by calculator program ----- */

char linebuffer[128];
char number[32]; /* holds current number in string form */
double fnumber1,hold; /* holds current number in double form */
double memory;
int mode; /* Flag, Scientific display or number pad */
int op,lastc;
char c;


/* ----------- MAIN PROGRAM ----------- */

void main(void)
{

page = 0;
mon_type = what_mon();
if (mon_type == 1)
attribute = set_color(BLACK, GREEN);
else
attribute = REVERSE;

/* MK_FP creates a far pointer, format: farptr = MK_FP(segment, offset) */

regs.h.ah = 0x34; /* Set up for get critical flag */
intdosx(®s, ®s, &segregs);
safety_flag = MK_FP(segregs.es, regs.x.bx);
printf("\nCritical error flag at %lx is set to %x",safety_flag, *safety_flag);


header = MK_FP(_psp - 1, 0); /* Point to TSR's allocation header */

newtick = MK_FP(0, 4 * NEWTICK); /* Swap interrupt vectors */
oldtick = MK_FP(0, 4 * TICKINT);

disable(); /* Disable hardware interrupts */
*newtick = *oldtick; /* Save old interrupt address */
*oldtick = (char *)tickhandler; /* Put new interrupt addr to table */

/* Set up Interrupt 28 trap */
/*
new28 = MK_FP(0,4 * INT28NEW);
old28 = MK_FP(0,4 * INT28OLD);
*new28 = *old28;
*old28 = (char *)doshandler;
*/

enable(); /* Re-Enable interrupts */

/* memcpy(intable,NULL,0x400); */ /* save old interrupt table */

geninterrupt(0x12); /* Ask BIOS how much memory avail. */
meminstall = _AX * 0x40; /* Store amount in paragraphs */

my_psp = get_psp();

printf("\nKeyboard TSR is now installed."
"\nPress Alt-Lshift-Rshift to activate"
"\nInt 8 handler at %lx",*oldtick);
printf("\nPSP at %04x, %04x",_psp, my_psp);

/* ----- Initialize Calculator globals ----- */
lastc='c'; /* indicates cleared calculator */
mode=TRUE; /* display number pad */
*number = NULL; /* Start with Zero in display */
fnumber1 = hold = 0;

/* Use the function keep(0,n) to set aside n paragraphs and terminate */

keep(0, _SS - _psp + 1);
}

/* ----------- SUPPORT ROUTINES ----------- */

#include "window.inc"

unsigned int get_psp()
{
_AH = 0x51;
geninterrupt(0x21);
return(_BX);
}

void set_psp(unsigned segment)
{
_BX = segment;
_AH = 0x50;
geninterrupt(0x21);
}


/* This is the real guts of the whole program */

void interrupt tickhandler()
{
geninterrupt(NEWTICK); /* Chain the interrupt first, if
you don't then the hardware will
be left disabled, causing a
crash when any I/O is attempted
*/

/* check to see if the HOT KEY as already been pressed */

if (hold_service == 0) /* Don't re-execute service if */
{ /* it's already running! */
if (wait > 0) /* Waiting for critical error flag */

if(*safety_flag == 0) /* It must be 0 to be safe */
{
service(); /* Execute application */
wait = 0; /* Re-set HOT KEY flag */
}
else
wait++;

else

/* On every tick, check for the HOT key sequence: Alt-Lshft-Rshft */

if( (*shiftptr & TESTIT) == TESTIT) /* We got a match */
{
sound(100,100);
if(*safety_flag == 0)
service();
else
wait++;
}
/* implied end of 'if (wait > 0) else' */
} /* if (hold_service == 1) */

}

/* Interrupt trap for INT 28, Must be patched with debug before use */
/* Right now as it stands, this function doesn't do anything usefull */

void interrupt doshandler(unsigned bp, unsigned di, unsigned si, unsigned ds,
unsigned es)
{

/*
asm mov ax,[bp+18] ;if we could get the next line of C code to
asm mov bp_value,ax ;compile to this, Things would be alot easier
*/

bp_value = bp; /* This compiles to: mov ax,[bp+0] change to [bp+18] */
if (hi_bp < bp_value)
hi_bp = bp_value;

if (lo_bp > bp_value)
lo_bp = bp_value;

call28++;
geninterrupt(INT28NEW);
}


/* Sound a tone, from the Turbo C manual */

void sound(int tone, int x)
{
int i,j;
char originalbits, bits;
unsigned char bcount;

bits = originalbits = inportb(0x61);

bcount = x;

for (i=0; i <= bcount; i++)
{
outportb(0x61, bits & 0xfc);
for (j=0; j <= tone; j++)
;
outportb(0x61,bits | 2);
for (j=0; j <= tone; j++)
;
}
outportb(0x61, originalbits); /* restore port setting */
}



/* -------------------------------------- */
/* From Here on down is the Resident Calculator Program.
* To make you own C program resident, Place it here instead, It
* is much easier to debug if you first write your 'service' program
* as a standard C program, and debug it as you normally would. Then
* rename the 'main()' procedure to 'service()'. If you have initialization
* code, place it in the 'main()' procedure of this file, so that it
* only gets executed once. Make sure that your program never executes
* an 'exit()', but simply drops through the last brace. At the beginning
* of your program, add the line 'hold_service = 1;' to keep it from being
* re-entered on the next clock interrupt. Before termination, add the
* line 'hold_service = 0;' to re-enable it.
*/

/* This is the Application Service Routine that is called after tickhandler
determines it is safe to perform DOS functions. I believe that at this
point, it is safe to do many types of DOS IO */

void service(void)
{
extern unsigned int page;
extern unsigned int attribute;
extern unsigned int mon_type;
int line;

/* Set hold_service to true, to keep the clock interrupt from re-
activating the service routine from within itself
*/

hold_service = 1;
win_save('s'); /* Save user screen */
make_window(1,1,24,13,1); /* Make a window */

disp_calc();
display();
while(TRUE)
{
getnum(number);
if (iindex(c,"1234567890.`") != -1)
{
sscanf(number,"%lf",&fnumber1); /* convert to float */
display();
}
else
{
if (c == 0x0D) /* is same as equals */
c = '=';
if (c == 0x7F) /* is same as C */
c = 'C';
if (c == ',') /* comma is same as + */
c = '+';

switch(toupper(c))
{

case 'C' : /* Clear calculator */
*number = NULL;
fnumber1=0;
{ disp_calc(); }
display();
hold=0;
op=' ';
break;

case '-' : /* Unary or Dyadic minus */
if (number == NULL && (lastc == 'c' | lastc == 'C') )
{
*number=c;
fnumber1=0;
display();
}
else
{
operation();
hold=fnumber1;
sprintf(number,"%lf",fnumber1);
display();
*number=NULL;
op=c;
}
break;

case '+' : /* Plus key */
operation();
hold=fnumber1;
sprintf(number,"%lf",fnumber1);
display();
*number=NULL;
op=c;
break;

case '*' : /* Times key */
operation();
hold=fnumber1;
sprintf(number,"%lf",fnumber1);
display();
*number=NULL;
op=c;
break;

case '/' : /* Divide key */
operation();
hold=fnumber1;
sprintf(number,"%lf",fnumber1);
display();
*number=NULL;
op=c;
break;

case 'Q' : /* Square root */

if (fnumber1 > 0)
fnumber1=sqrt(fnumber1);
sprintf(number,"%lf",fnumber1);
display();
break;

case '=' : /* Equals key */
operation();
sprintf(number,"%lf",fnumber1);
display();
op=' ';
*number=NULL;
hold=fnumber1;
break;

case '>' : /* Store display to memory */
memory=memory+fnumber1;
sprintf(number,"%lf",fnumber1);
display();
*number=NULL;
break;

case '<' : /* Recall memory */
fnumber1=memory;
sprintf(number,"%lf",fnumber1);
display();
break;

case 'L' : /* Clear memory */
memory=0;
display();
break;

case 0x1B : /* Control-C exits program */
goto exit;

} /* case */
} /* iindex else */
} /* while(true) */
exit:
win_save('r'); /* Restore original screen */

/* Reset hold_service so that the use may HOT KEY it again */
hold_service = 0;
}

getnum(num)
char *num;

/* Append a digit from console to the array pointed to by NUM. */
/* the GLOBAL variable 'c' (defined in the main program) will */
/* contain the last character typed. */

{
static char *p1;
static int point;

if (strlen(num) == NULL)
{
p1=num;
point=FALSE;
}

c = getch();

if (c == 0x08) /* process backspace */
c='`';

if (iindex(c,"1234567890.`") != -1)
{
if(c == '`' && strlen(number) > 0)
{
if( *--p1 == '.' )
point=FALSE;
*p1 = '\0';
}
else
{
if(c != '.' || (c == '.' && point == FALSE))
{
*p1++ = c;
*p1='\0';
if( c == '.' )
point=TRUE;
}
}
}
return(c);
}

operation()
{

if (op == '+' )
fnumber1 = fnumber1+hold;
if (op == '-' )
fnumber1 = hold-fnumber1;
if (op == '*' )
fnumber1 = hold*fnumber1;
if (op =='/' )
fnumber1 = hold/fnumber1;
if (op == '^' )
fnumber1 = fnumber1; /* power does nothing now */

}

disp_calc()
{

print(2,2,"+=====================+");
print(2,3,"| |");
print(2,4,"+---------------------+");
print(2,5,"| Micro-Tool Calc |");
if (mode == TRUE )
{
print(2,6,"| |");
print(2,7,"|m+ 7 8 9 +, |");
print(2,8,"|> - |");
print(2,9,"|mr Help 4 5 6 * |");
print(2,10,"|< / |");
print(2,11,"|mcL Win 1 2 3 |");
print(2,12,"| |");
print(2,13,"|Del Bksp 0 . = |");
print(2,14,"+=====================+");
print(2,15," Press to quit ");
}
else
{
print(2,6,"| Q G \" |");
print(2,7,"|sqr log in-cm |");
print(2,8,"| X T ' |");
print(2,9,"|exp tan cm-in |");
print(2,10,"| S N F |");
print(2,11,"|sin asn fahr-cent |");
print(2,12,"| O A E |");
print(2,13,"|cos acs cent-fahr |");
print(2,14,"+=====================+");
}
}

display() /* display number on calculator */
{
sprintf(linebuffer,"%18lf",fnumber1);
print(4,3,linebuffer);
if (op == '-' && number != NULL ) /* do nothing */ ;
else
{
print(4,3,"-");
}
if (memory != 0.0 )
print(3,3,"m");
else
print(3,3," ");
}


append(s,c)
char *s, c;

/* append the character 'c' to the CHAR array pointed to by 's' */

{
while(*s != '\0')
s++;
*s++ = c;
*s = '\0';
}


int iindex(c,s) /* return position that C occurs in S, or -1 */
char c, *s;
{
int i, retval;

retval = -1;
i=0;
while(*s != '\0')
{
if(*s++ == c)
{
retval=i;
break;
}
i++;
}
return(retval);
}


  3 Responses to “Category : C Source Code
Archive   : 3TCTGR.ZIP
Filename : TSRCALC.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/