Microsoft KB Archive/86558

{|
 * width="100%"|

How to Trap CTRL+C and CTRL+BREAK Keystrokes

 * }

Q86558

-

The information in this article applies to:


 * The C Run-Time (CRT), included with:
 * Microsoft C for MS-DOS, versions 5.1, 6.0, 6.0a, and 6.0ax
 * Microsoft C/C++ for MS-DOS, version 7.0
 * Microsoft Visual C++, versions 1.0, 1.5

-

SUMMARY
The program below demonstrates how to revector interrupts to your own service routine. Also, it shows how to stop the ^C character from appearing on the screen when CTRL+C is pressed.

MORE INFORMATION
The sample program shows how to trap the CTRL+C and CTRL+BREAK key combinations. The program waits for a keystroke. When a key is pressed, the program checks to see if the keystroke is a CTRL+C or CTRL+BREAK key combination. If the keystroke is CTRL+BREAK, nothing happens. If the keystroke is CTRL+C, a message is displayed and the keyboard buffer is dumped to the screen in hexadecimal values. If the keystroke is neither CTRL+C nor CTRL+BREAK, just the keyboard buffer is dumped to the screen.

Sample Code
/* Compile options needed: None

#include   #include    #include 

#define HIBYTE(x) ((unsigned char) (((unsigned) x >> 8) & 0x00FF)) #define HIWORD(x) \ ((unsigned) (((unsigned long) x >> 16) & 0x0000FFFF)  #define LOBYTE(x) ((unsigned char) ((unsigned) x & 0x00FF))   #define LOWORD(x) ((unsigned) ((unsigned long) x & 0x0000FFFF))

#define BITSET(x, n) ( (((unsigned) x >> n) & 0x0001) == 1 ? 1 : 0)

#define AND(a, b) ( a &= b )  /* a = a AND b */ #define OR(a, b)  ( a |= b )  /* a = a OR  b */ #define XOR(a, b) ( a ^= b )  /* a = a XOR b */

#define SEMINIT(s) ( XOR(s, s) ) #define SEMSET(s)  ( s ? 1 : 0 )

#define INT09  0x0009      /* Keyboard interrupt number */ #define INT1B  0x001B      /* CTRL+C interrupt number */ #define INT23  0x0023      /* CTRL+BREAK interrupt number */

#define ESC    0x1B        /* ASCII escape code */ #define SPACE  0x20        /* ASCII space  code */ #define cScan  0x2E        /* Scan code for the &quot;C&quot; key */ #define CtrlOff 0xFB       /* CTRL+C bit mask */ #define CtrlOn 0x04        /* CTRL+C bit mask */ #define Value  0x001F      /* Replace ^C with this value */

#define KBDMEM 0x0000041C  /* Keyboard buffer tail pointer address */

#define KBDBUF 0x0000041E  /* Keyboard buffer address */ #define KBDFLAG 0x00000417 /* Keyboard flag byte address */

#define KB_DATA 0x0060     /* Keyboard port address  */ #define ADDRESS unsigned far *

/*========================================================*/   /*  Functions pointers */

void (interrupt far *KbdPtr)(void); /* Points to keybrd routine */ void (interrupt far *BrkPtr)(void); /* Points to break routine  */

void (interrupt far *OldInt09)(void); /* Save old kbd handler */ void (interrupt far *OldInt1B)(void); /* Save old ^C handler */ void (interrupt far *OldInt23)(void); /* Save old brk handler */

/*========================================================*/

ADDRESS KbdBuf; ADDRESS KbdCtrl; ADDRESS KbdTail;

void main (void); void KbdHexDump( ADDRESS str );

/*=========================================================*/   /* Interrupt service routines */

void interrupt far Int09; void interrupt far Int1B; void interrupt far Int23;

/*=========================================================*/

unsigned sem; /* ^C was pressed then sem=1, else sem=0 */ unsigned ch; unsigned cell; /* Data from kbd port 60h */

void main (void) {     unsigned i;

OldInt09 = _dos_getvect( INT09 ); OldInt1B = _dos_getvect( INT1B ); OldInt23 = _dos_getvect( INT23 );

KbdPtr = Int09; _dos_setvect( INT09, KbdPtr );

BrkPtr = Int1B; _dos_setvect( INT1B, BrkPtr);

BrkPtr = Int23; _dos_setvect( INT23, BrkPtr );

KbdTail = (ADDRESS) KBDMEM; KbdBuf  = (ADDRESS) KBDBUF; KbdCtrl = (ADDRESS) KBDFLAG;

for(i = 0; i < 16; i++) KbdBuf[i] = (unsigned) (0x3900 | SPACE);

SEMINIT(sem); /* Clear semaphore */ XOR(ch, ch);  /* ch=0  */

while( LOBYTE(ch) != ESC ) {        ch = getch; if ( SEMSET(sem) ) printf(&quot;\nCtrl-C key was pressed!\n&quot;); KbdHexDump( KbdBuf ); }

_dos_setvect( INT09, OldInt09 ); _dos_setvect( INT1B, OldInt1B ); _dos_setvect( INT23, OldInt23 ); }

void KbdHexDump( ADDRESS str ) {     unsigned  j;

printf(&quot;\n&quot;); for( j=0; j < 16; j++ ) {        if ( LOBYTE(str[j]) < 15 ) printf(&quot;0&quot;); if ( str[j] == Value ) printf(&quot;03 &quot;); else printf(&quot;%x &quot;, LOBYTE(str[j])); }     printf(&quot;     &quot;); for( j=0; j < 16; j++ ) {        if ( LOBYTE(str[j]) < SPACE ) printf(&quot;%c&quot;, '.'); else printf(&quot;%c&quot;, LOBYTE(str[j])); }     printf(&quot;\n&quot;); }

/*========================================================*/   /* Interrupt service routines */

void interrupt far Int09( void ) {     unsigned indx;

_disable;

cell = inp( KB_DATA ); if ( BITSET(*KbdCtrl, 2) && LOBYTE(cell) == cScan ) {        sem = 1; indx = ( *KbdTail - LOBYTE(LOWORD(KbdBuf)) ) / 2; AND( *KbdCtrl, CtrlOff ); }     else XOR(sem, sem);

OldInt09;

if ( SEMSET(sem) ) {        OR( *KbdCtrl, CtrlOn ); KbdBuf[indx] = Value; }

}

void interrupt far Int1B(void) {      /* New home for CTRL+C     */ }

void interrupt far Int23(void) {      /* New Home for CTRL+BREAK */ } Additional query words: kbinf 5.10 6.00 6.00a 6.00ax 7.00 1.00 1.50

Keywords : kb16bitonly

Issue type :

Technology : kbVCsearch kbAudDeveloper kbCRT