/* CBREAK.C */ #include #include #include #include "cbreak.h" #define CB_FAR far #define BITSET(x, n) ( (((unsigned) x >> n) & 0x0001) == 1 ? 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 SCANCODE_C (0x2E) /* Scan code for the "C" key */ #define CTRL_OFF_MASK (0xFB) /* CTRL+C bit mask */ #define CTRL_ON_MASK (0x04) /* CTRL+C bit mask */ #define KBDMEM (0x0000041C) /* Keybrd buffer tail pointer address */ #define KBDBUF (0x0000041E) /* Keyboard buffer address */ #define KBDFLAG (0x00000417) /* Keyboard flag byte address */ #define KB_DATA 0x0060 /* Kbd port address */ /*-------------------------------------------------------------------------*/ /* Functions pointers */ void (interrupt CB_FAR *old_break_int09)(); /* Save old kbd handler */ void (interrupt CB_FAR *old_break_int1B)(); /* Save old ^C handler */ void (interrupt CB_FAR *old_break_int23)(); /* Save old brk handler */ /*-------------------------------------------------------------------------*/ unsigned short CB_FAR * kbd_buf; unsigned short CB_FAR * kbd_ctrl; unsigned short CB_FAR * kbd_tail; /*-------------------------------------------------------------------------*/ /* Interrupt service routines */ void interrupt CB_FAR break_int09(void); void interrupt CB_FAR break_int1B(void); void interrupt CB_FAR break_int23(void); /*-------------------------------------------------------------------------*/ unsigned break_sem; /* ^C was pressed then sem=1, else sem=0 */ unsigned break_installed = 0; void break_Install(void) { unsigned i; if ( break_installed != 0 ) return; old_break_int09 = _dos_getvect( INT09 ); old_break_int1B = _dos_getvect( INT1B ); old_break_int23 = _dos_getvect( INT23 ); _dos_setvect( INT09, break_int09 ); _dos_setvect( INT1B, break_int1B ); _dos_setvect( INT23, break_int23 ); kbd_tail = (unsigned short CB_FAR *)(long)KBDMEM; kbd_buf = (unsigned short CB_FAR *)(long)KBDBUF; kbd_ctrl = (unsigned short CB_FAR *)(long)KBDFLAG; for(i = 0; i < 16; i++) kbd_buf[i] = (unsigned) (0x3900 | SPACE); break_sem = 0; break_installed = 1; } void break_Remove(void) { if ( break_installed == 0 ) return; _dos_setvect( INT09, old_break_int09 ); _dos_setvect( INT1B, old_break_int1B ); _dos_setvect( INT23, old_break_int23 ); break_installed = 0; } int break_IsCTRLC(void) { return break_sem == 0 ? 0 : 1; } /*-------------------------------------------------------------------------*/ /* Interrupt service routines */ void interrupt CB_FAR break_int09( void ) { unsigned cell; /* Data from kbd port 60h */ unsigned indx = 0; _disable(); cell = inp( KB_DATA ); break_sem = 0; if ( BITSET(*kbd_ctrl, 2) && (cell & 0x0ff) == SCANCODE_C ) { break_sem = 1; indx = ( *kbd_tail - (KBDBUF & 0x0ff) ) / 2; *kbd_ctrl &= CTRL_OFF_MASK; } old_break_int09(); if ( break_sem != 0 ) { *kbd_ctrl |= CTRL_ON_MASK; kbd_buf[indx] = CTRL_C_REPLACE; } } void interrupt CB_FAR break_int1B(void) { /* New home for CTRL+C */ } void interrupt CB_FAR break_int23(void) { /* New Home for CTRL+BREAK */ } /*-------------------------------------------------------------------------*/ /* #define break_main */ #ifdef break_main #define LOBYTE(x) ( (unsigned char) ((unsigned) x & 0x00FF) ) void KbdHexDump( unsigned short CB_FAR *str ) { unsigned j; printf("\n"); for( j=0; j < 16; j++ ) { if ( LOBYTE(str[j]) < 15 ) printf("0"); if ( str[j] == CTRL_C_REPLACE ) 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"); } #include void main (void) { unsigned ch; break_Install(); ch = 0; while( ch != ESC ) { printf("%ld\n", (long)clock()); ch = getch(); if ( ch == CTRL_C_REPLACE ) printf("\nCtrl-C value\n"); if ( break_IsCTRLC() ) printf("\nCtrl-C key was pressed!\n"); KbdHexDump( kbd_buf ); } break_Remove(); } #endif