From: "Anthony.Appleyard" Organization: Materials Science Centre To: djgpp-workers AT delorie DOT com Date: Wed, 14 Jan 1998 08:20:31 GMT Subject: MCLSSAA2 AT fs2 DOT mt DOT umist DOT ac DOT uk: Hooking interrupt 9 Reply-to: Anthony DOT Appleyard AT umist DOT ac DOT uk Message-ID: <27011525706@fs2.mt.umist.ac.uk> Precedence: bulk > > extern int (*_djgpp_kbd_callback)(int X); /* initial value == 0 */ > > ///// This line should be inserted in some suitable #insert<***.h> file. > > No, decide which file it goes in and supply a patch to put it there. ... ================================================================== Herewith a DIFF for insert\sys\exceptn.h :- ------------------------------------------------------------------ *** exceptn.h Mon Dec 4 22:39:44 1995 --- exceptn2.h Tue Jan 13 14:35:24 1998 *************** *** 27,32 **** --- 27,33 ---- #define __djgpp_exception_state (*__djgpp_exception_state_ptr) #endif + extern int (*_djgpp_kbd_callback)(int X); extern unsigned short __djgpp_our_DS; extern unsigned short __djgpp_app_DS; /* Data selector invalidated by HW ints */ extern unsigned short __djgpp_ds_alias; /* Data selector always valid */ *************** *** 38,43 **** --- 39,150 ---- void __djgpp_exception_toggle(void); int __djgpp_set_ctrl_c(int enable); /* On by default */ + enum{ /* numbers of the keys */ + k_esc = 1, + k_1, + k_2, + k_3, + k_4, + k_5, + k_6, + k_7, + k_8, + k_9, + k_0, + k_1rof0, + k_2rof0, + k_backspace, + k_tab, + k_Q, + k_W, + k_E, + k_R, + k_T, + k_Y, + k_U, + k_I, + k_O, + k_P, + k_1rofP, + k_2rofP, + k_enter, + k_lctrl, + k_A, + k_S, + k_D, + k_F, + k_G, + k_H, + k_J, + k_K, + k_L, + k_1rofL, + k_2rofL, + k_1lof1, + k_lshift, + k_3rofL, + k_Z, + k_X, + k_C, + k_V, + k_B, + k_N, + k_M, + k_1rofM, + k_2rofM, + k_3rofM, + k_rshift, + k_padstar, + k_lalt, + k_space, + k_capslock, + k_F1, + k_F2, + k_F3, + k_F4, + k_F5, + k_F6, + k_F7, + k_F8, + k_F9, + k_F10, + k_numlock, + k_scrolllock, + k_pad7, + k_pad8, + k_pad9, + k_padminus, + k_pad4, + k_pad5, + k_pad6, + k_padplus, + k_pad1, + k_pad2, + k_pad3, + k_pad0, + k_paddot, + k_1lofZ = 0x56, + k_F11, + k_F12, + k_padenter = 0x11c, /* + 0x100 = as second half of an 0xe0 pair */ + k_rctrl = 0x11d, + k_numshift = 0x12a, + k_padslash = 0x135, + k_ralt = 0x138, + k_home = 0x147, + k_uparrow = 0x148, + k_pageup = 0x149, + k_leftarrow = 0x14b, + k_rightarrow = 0x14d, + k_end = 0x14f, + k_downarrow = 0x150, + k_pagedown = 0x151, + k_insert = 0x152, + k_delete = 0x153, + k_lwin = 0x15b, + k_rwin = 0x15c, + k_menu = 0x15d}; + #endif /* !_POSIX_SOURCE */ #endif /* !__STRICT_ANSI__ */ #endif /* !__dj_ENFORCE_ANSI_FREESTANDING */ ================================================================== Herewith a DIFF for src\libc\go32\exceptn.s :- ------------------------------------------------------------------ *** exceptn.s Mon Jan 12 14:54:06 1998 --- exceptn2.s Tue Jan 13 15:07:40 1998 *************** *** 284,292 **** --- 284,327 ---- iret .align 4 + .global __djgpp_kbd_callback + __djgpp_kbd_callback: .int 0 /* int (*_djgpp_kbd_callback)(int X); */ + /* If not 0, the interrupt 9 hook routine will call this function with:- */ + /* X &255 == keyboard event */ + /* (X>> 8)&255 == keyboard shift status as if from (AH=2, int 16h) */ + /* (X>>16)&255 == keyboard extended shift status as if from (AH=12h, int 16h) */ + _calldjgpp_kbd_callback: + xorl %eax,%eax /* must return 0 if no function */ + pushl %ebx /* save EBX */ + movl __djgpp_kbd_callback,%ebx + testl %ebx,%ebx /* if zero, there is no function */ + je no_user_hdlr + pushw %fs + pushf + cli /* disable interrupts */ + movw __go32_info_block+26,%ax + movw %ax,%fs /* FS = _dos_ds */ + .byte 0x64 /* use segment reg FS */ + movw 0417,%ax /* [0x417] [0x418] are shift status */ + sall $8,%eax /* move EAX one byte up */ + inb $0x60,%al /* read keyboard event into AL */ + pushl %eax /* parameter for call */ + call *%ebx /* call the function */ + popf + popw %fs /* don't restore EAX, it's the result */ + no_user_hdlr: + popl %ebx + ret + .global ___djgpp_kbd_hdlr ___djgpp_kbd_hdlr: pushl %eax + call _calldjgpp_kbd_callback /* If djgpp_kbd_callback returns */ + testl %eax,%eax /* nonzero, no default handling of the event */ + je dont_call_fn + popl %eax + iret + dont_call_fn: pushl %ds .byte 0x2e /* CS: */ testb $1, ___djgpp_hwint_flags /* Disable? */ *************** *** 317,322 **** --- 352,363 ---- .global ___djgpp_kbd_hdlr_pc98 ___djgpp_kbd_hdlr_pc98: pushl %eax + call _calldjgpp_kbd_callback /* If djgpp_kbd_callback returns */ + testl %eax,%eax /* nonzero, no default handling of the event */ + je dont_call + popl %eax + iret + dont_call: pushl %ds .byte 0x2e /* CS: */ testb $1, ___djgpp_hwint_flags /* Disable? */ ================================================================== Herewith a .TXH file for it, say call it djgppkbh.txh :- ------------------------------------------------------------------ @node _djgpp_kbd_callback, stdio @subheading Syntax @example #include extern int (*_djgpp_kbd_callback)(int X); @end example @subheading Description If _djgpp_kbd_callback is not zero, it is a pointer to a user-definable function which is automatically called whenever a keyboard event occurs such as a key being pressed or released. They would let the program see the raw keyboard events. When it is called:- X &255 == the keyboard event code (X>> 8)&255 == keyboard shift status as if from (AH=2, int 16h) (X>>16)&255 == keyboard extended shift status as if from (AH=12h, int 16h) If _djgpp_kbd_callback(X) returns nonzero, that keyboard event is not passed on to DOS. This would let the user e.g. recognise and intercept `Prt Scr' and use it for some purpose of his own instead of DOS handling it. bits of shift status bits of extended shift status 7 Insert active 7 SysReq key pressed 6 CapsLock active 6 CapsLock pressed 5 NumLock active 5 NumLock pressed 4 ScrollLock active 4 ScrollLock pressed 3 Alt key pressed 3 right Alt key pressed 2 Ctrl key pressed 2 right Ctrl key pressed 1 left shift key pressed 1 left Alt key pressed 0 right shift key pressed 0 left Ctrl key pressed The current values of these two bytes are kept in conventional memory at addresses 0x417 and 0x418 respectively. The keyboard keys are numbered between 0 and 127. The code for pressing a key is as listed in the insert file SYS/EXCEPTN.H; the code for releasing that key is 0x80 = 128 higher. Some of the keys when pressed or released produce two keyboard events, of which the first is 0xe0, and the second is the key's code (plus 128 on release). I represent this feature here by adding 0x100 = 256 to the code. `Numshift' is an imaginary key whose press and release codes are sometimes manufactured by something in BIOS around some of the `grey key' events. If `numshift' is treated as an extra shift key, the effect is that those `grey keys' are shifted by the current Numlock state and not by the two real shift keys. Don't blame me, blame whoever invented the PC BIOS. On my PC pressing Pause/Break key produces the sequence `e1 1d 45', and releasing it produces `e1 9d c5': i.e. `e1' followed by the codes for `left ctrl' and `numlock' in that order. In the sequence, the `e1 1d' seems to be the functioning part that causes the pausing or the break. On my PC: pressing `Prt Scr'/`Sys Req' key produces `e0 2a' followed by three `press padstar' sequences; releasing `Prt Scr'/`Sys Req' produces a `release padstar' sequence followed by `e0 aa'. Due to wide differences between national keyboard layouts, I have named the non-alphanumeric printing keys neutrally, e.g. `k_2rof0' means "the key two to the right of 0" (`=' `+' on UK and USA keyboards). This refers to the layout on a desktop keyboard. Laptop keys tend to be somewhat differently arranged. @subheading Return Value This should be 0 if you want the keyboard event to be processed as usual after you have processed it, otherwise 1. @subheading Example @example char print_wanted = 0; ...... int trap_prscr(int X){ if((X&0xff) == 0x2a) /* if it is left shift or Prt Scr */ if(!((X>>8)&15)) /* not if shift or ctrl or alt */ if(_farpeekb(_dos_ds,0x496)&2) /* if it is next after 0xe0 event */ { /* then it is a Prt Scr */ print_wanted = 1; /* leave note to call my own printout routine */ return 1; /* no, I DON'T want DOS's method right now */ } return 0; /* else default */ } ...... int main(){ ...... _djgpp_kbd_callback = trap_prscr; ...... @end example