[comp.sys.ibm.pc] Control C/Break handler for MSC

jdm@hodge.UUCP (jdm) (09/17/89)

	A number of people have requested a handler to trap
	Control C and Control Break key strokes.  Here is a
	little dittie released just for that purpose from the
	good people at Microsoft.




/*=============================> Ctrl.c <==================================*/
/*									   */
/*     This sample program illustrates how to trap the Ctrl-C and	   */
/*     Ctrl-Break keys. It will wait for the user to press a key.	   */
/*     When a key is pressed it will check to see if the key is a	   */
/*     Ctrl-C or a Ctrl-Break. If the key is a Ctrl-Break, nothing	   */
/*     will happen. If the key is a Ctrl-C, a message is displayed	   */
/*     and the keyboard buffer is dumped to the screen in hex values.	   */
/*     If the key pressed is neither Ctrl-C nor Ctrl-Break than just	   */
/*     the keyboard buffer is dumped.					   */
/*									   */
/*     Copyright (c) Microsoft Corp. 1988. All rights reserved. 	   */
/*									   */
/*=========================================================================*/

#include <stdio.h>
#include <dos.h>
#include <conio.h>

#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 "C" 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	    /* Kbd port address 		       */
#define ADDRESS unsigned far *

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

void (interrupt far *KbdPtr)(void);	/* points to keyboard 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);
void interrupt far Int1B(void);
void interrupt far Int23(void);

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

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("\nCtrl-C key was pressed!\n");

	    KbdHexDump( KbdBuf );
       }

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








void
KbdHexDump( ADDRESS str )
{
    unsigned  j;

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

/*============================================================================*/
/* 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. */
}