This is kbdhdl.c in view mode; [Download] [Up]
/* Keyboard interrupt handler and primary ms-dos multi-tasking interface */
#include <dos.h>
#include "kbdhdl.h"
extern void doschain(void);
extern void (far *odos)(void);
extern int indos; /* Set when in a dos function */
extern int inexec; /* Set when in the EXEC function */
#define sstoax() __emit__(0x8c,0xd0)
#define sptoax() __emit__(0x89,0xe0)
#define axtoss() __emit__(0x8e,0xd0)
#define axtosp() __emit__(0x89,0xc4)
#define simint(a) __emit__(0x9c,0xfa); (a)()
#define kimask 2 /* This is the 8259 kbd interrupt mask bit */
int psp; /* This program's PSP */
int ine=0; /* Set if running an editor function */
int brkflg=0; /* Set whenever Ctrl-break is hit */
int chk=0; /* Set when a key was hit while in dos */
void (far *oldhdl)(void); /* Original handlers which we replace */
void (far *kkkhdl)(void);
void (far *brkhdl)(void);
/* Replacement for 'int 0x16', the bios keyboard function */
/* This is replaced so that we can simulate terminal
* input on the background DOS process
*/
#define stisize 64
unsigned char stibuf[stisize];
unsigned stinew;
unsigned stiold;
void interrupt kkk(unsigned bp,unsigned di,unsigned si,unsigned ds,
unsigned es,unsigned dx,unsigned cx,unsigned bx,unsigned ax,unsigned ip,
unsigned cs,unsigned flags)
{
enable();
if((ax&0xff00)==0x0000)
{
while(stinew==stiold);
ax=stibuf[stiold]+(((unsigned)stibuf[stiold+1])<<8);
stiold+=2;
if(stiold==stisize) stiold=0;
}
else if((ax&0xff00)==0x0100)
{
if(stinew!=stiold)
{
ax=stibuf[stiold]+(((unsigned)stibuf[stiold+1])<<8);
flags&=(0xff-0x40);
}
else flags|=0x40;
}
else if((ax&0xff00)==0x0200)
ax=*(unsigned char far *)0x417+0x200;
}
/* Simulate terminal input */
void sti(unsigned char ascii,unsigned char scan)
{
disable();
stibuf[stinew++]=ascii;
stibuf[stinew++]=scan;
if(stinew==stisize) stinew=0;
enable();
}
/* Replacement break key handler */
void interrupt brkh()
{
brkflg=1;
}
/* Return true if there are any keys */
int kcheck(void)
{
_BX=0;
_AH=1;
simint(kkkhdl);
__emit__(0x74,1,0x43);
if(_BX) return 1;
else return 0;
}
/* Dump any keys in queue */
void kdump(void)
{
while(kcheck())
{
_AH=0; /* Get the character */
simint(kkkhdl);
}
}
/* Replacement keyboard interrupt handler */
unsigned stackflg=0,oldss,oldsp,stackseg,stackp;
void interrupt dos(unsigned bp,unsigned di,unsigned si,unsigned ds,
unsigned es,unsigned dx,unsigned cx,unsigned bx,unsigned ax,unsigned ip,
unsigned cs,unsigned flags);
void khandle(void)
{
/* Saved context information */
int opsp;
unsigned dtaseg;
unsigned dtaofst;
/* Install normal dos vector for us */
disable();
*(void far * far *)0x84=odos;
enable();
/* Switch PSP */
_AH=0x51;
geninterrupt(0x21);
opsp=_BX;
_BX=psp;
_AH=0x50;
geninterrupt(0x21);
/* Save DTA */
_AH=0x2f;
geninterrupt(0x21);
dtaofst=_BX;
dtaseg=_ES;
/* Other information that should be preserved here:
*
* critical error handler (yes)
* extended error information (yes- see green book for setting error byte)
* current drive (yes)
* current path (yes)
*
* Also:
* should intercept int20 for exiting
* should intercept absolute disk read/write
* should intercept TSR int (int 27H)
*/
up: /* Test for keys */
disable(); /* Disable keyboard interrupts */
outportb(0x21,inportb(0x21)|kimask);
enable();
if(kcheck())
{
char scan, ascii;
disable(); /* Reenable keyboard interrupts */
outportb(0x21,inportb(0x21)&~kimask);
enable();
_AH=0; /* Get the character */
simint(kkkhdl);
ascii=_AL;
scan=_AH;
if(key(ascii,scan)) goto bye;
goto up; /* See if any more keys to process */
}
ine=0;
bye:;
/* Restore DTA */
_DX=dtaofst;
_DS=dtaseg;
_AH=0x1a;
geninterrupt(0x21);
_DS=_CS;
/* Restore PSP */
_BX=opsp;
_AH=0x50;
geninterrupt(0x21);
/* Install our DOS interceptor */
disable();
*(void far * far *)0x84=MK_FP(_CS,doschain);
enable();
}
void interrupt dos(unsigned bp,unsigned di,unsigned si,unsigned ds,
unsigned es,unsigned dx,unsigned cx,unsigned bx,unsigned ax,unsigned ip,
unsigned cs,unsigned flags)
{
if(chk && ine==0)
{
ine=1;
if(_SS!=stackseg)
{
stackflg=1;
sstoax();
oldss=_AX;
sptoax();
oldsp=_AX;
disable();
_AX=stackseg;
axtoss();
_AX=stackp;
axtosp();
enable();
}
khandle();
if(stackflg)
{
stackflg=0;
_AX=oldss;
axtoss();
_AX=oldsp;
axtosp();
}
chk=0;
disable();
outportb(0x21,inportb(0x21)&~kimask);
enable();
}
}
void interrupt kbdhdl()
{
simint(oldhdl);
disable();
if(stackflg==0 && ine==0 && indos==0 && inexec==0 && chk==0)
{
ine=1;
chk=1;
enable();
if(_SS!=stackseg)
{
stackflg=1;
sstoax();
oldss=_AX;
sptoax();
oldsp=_AX;
disable();
_AX=stackseg;
axtoss();
_AX=stackp;
axtosp();
enable();
}
khandle();
if(stackflg)
{
disable();
_AX=oldss;
axtoss();
_AX=oldsp;
axtosp();
enable();
stackflg=0;
}
chk=0;
disable();
outportb(0x21,inportb(0x21)&~kimask);
enable();
}
else
{
if(indos || inexec)
{
chk=1;
return;
}
enable();
}
}
void kopen(void)
{
/* Remeber where our stack is */
sstoax();
stackseg=_AX;
sptoax();
stackp=_AX-512; /* 512 bytes of background stack, the rest foreground */
/* Remember which PSP we are */
_AH=0x51;
geninterrupt(0x21);
psp=_BX;
/* Install vectors */
disable();
oldhdl=*(void far * far *)0x24;
*(void far * far *)0x24=MK_FP(_CS,kbdhdl);
kkkhdl=*(void far * far *)0x58;
*(void far * far *)0x58=MK_FP(_CS,kkk);
brkhdl=*(void far * far *)0x6c;
*(void far * far *)0x6c=MK_FP(_CS,brkh);
odos=*(void far * far *)0x84;
*(void far * far *)0x84=MK_FP(_CS,doschain);
enable();
}
/* Restore vectors */
void kclose(void)
{
disable();
*(void far * far *)0x24=oldhdl;
*(void far * far *)0x58=kkkhdl;
*(void far * far *)0x6c=brkhdl;
*(void far * far *)0x84=odos;
enable();
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.