home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / borland / jnfb88.arc / KEYINT.ARC / MOREKEYU.PAS < prev    next >
Pascal/Delphi Source File  |  1987-10-07  |  6KB  |  141 lines

  1. UNIT MoreKeyU; {More_Keys UNIT}
  2.   (* ==================================== *)
  3.   (* Demonstrates a method for enabling   *)
  4.   (* handy key combinations that the BIOS *)
  5.   (* normally throws away.                *)
  6.   (* ==================================== *)
  7. Interface
  8. USES Crt,Dos;
  9.   (* ======================================== *)
  10.   (* There's nothing at all in the INTERFACE  *)
  11.   (* portion of this unit.  It's completely   *)
  12.   (* self-contained.  The initialization      *)
  13.   (* code at the end loads the new Interrupt  *)
  14.   (* Service Routine and the ExitProc puts    *)
  15.   (* back the old interrupt.                  *)
  16.   (* ======================================== *)
  17. Implementation
  18.  
  19. VAR
  20.   Kbd_Vec, Exit_Vec : Pointer;
  21.  
  22. CONST
  23.   ROM_Data = $0040; {Segment for ROM data about keyboard }
  24.   KB_Flag  = $0017; {Offset for shift states             }
  25.   Head     = $001A; {Offset for Kbd. buffer HEAD pointer }
  26.   Tail     = $001C; {Offset for Kbd. buffer TAIL pointer }
  27.   KeyBuf   = $001E; {Offset for Keyboard buffer itself   }
  28.   BufEnd   = $003E; {Offset for end of keyboard buffer   }
  29.   Kbd_Int  = 9;
  30.  
  31. {$I error.inc}
  32.  
  33.   PROCEDURE INT9_ISR(_Flags, _CS, _IP, _AX, _BX, _CX, _DX,
  34.                              _SI, _DI, _DS, _ES, _BP:word);
  35.   INTERRUPT;
  36.   (* ======================================= *)
  37.   (* This ISR first checks if the <Alt> key  *)
  38.   (* is pressed and the <LeftShift> is NOT   *)
  39.   (* pressed.  IF so, it grabs the scan code *)
  40.   (* waiting in the keyboard and checks if   *)
  41.   (* it is a KEYPAD key.  IF so, it clears   *)
  42.   (* the keyboard and stuffs the keyboard    *)
  43.   (* buffer with the value corresponding     *)
  44.   (* to that key combination as listed in    *)
  45.   (* Appendix K of the TURBO 3.0 manual.     *)
  46.   (*                                         *)
  47.   (* If none of the special cases apply, it  *)
  48.   (* is a normal key, to be given to the     *)
  49.   (* normal keyboard interrupt.              *)
  50.   (*                                         *)
  51.   (* Sounds complicated, but the end result  *)
  52.   (* is that you can use the <Alt>+Keypad    *)
  53.   (* combinations in a program.  If you want *)
  54.   (* <Alt><Number> combinations (e.g., to    *)
  55.   (* get char 219), you use <Alt><LeftShift> *)
  56.   (* <Number>, just as with SuperKey.        *)
  57.   (* ======================================= *)
  58.   BEGIN
  59.   INLINE(
  60.     $FB/              {STI ;Allow interrupts}
  61.     $9C/              {PUSHF ;Save the flags}
  62.     $1E/              {PUSH DS ;Save the Turbo DSeg}
  63.     $E4/$60/          {IN   AL,$60 ;Read the keyboard port}
  64.     $88/$C1/          {MOV  CL,AL}
  65.     $B8/>ROM_DATA/    {MOV  AX,ROM_DATA}
  66.     $8E/$D8/          {MOV  DS,AX ;Set DS to ROM_DATA segment}
  67.     $A0/>KB_FLAG/     {MOV  AL,[>KB_FLAG]}
  68.     $A8/$08/          {TEST AL,$08 ;The 8 bit is ALT}
  69.     $74/$14/          {JZ   Norm_Key ;IF not alt, normal}
  70.     $A8/$02/          {TEST AL,$02 ;The 2 bit is L-Shift}
  71.     $75/$10/          {JNZ  Norm_Key ;If L-shifted, normal}
  72.     $88/$C8/          {MOV  AL,CL}
  73.     $3C/$80/          {CMP  AL,$80 ;Is it a key-release?}
  74.     $73/$0A/          {JNB  Norm_Key ;If so, treat as normal}
  75.     $3C/$47/          {CMP  AL,$47 ;Below Home is normal}
  76.     $72/$06/          {JB   Norm_Key}
  77.     $3C/$53/          {CMP  AL,$53 ;Above Del is normal}
  78.     $7F/$02/          {JG   Norm_Key}
  79.     $EB/$19/          {JMP  SHORT Special_Key}
  80. {Norm_Key:}
  81.     {IF it's not a special key, just CHAIN to the old interrupt}
  82.     $1F/              {POP  DS      ;Restore TURBO DSeg}
  83.     $9D/              {POPF         ;Restore the flags}
  84.     $A1/>KBD_VEC+2/   {MOV  AX,[>KBD_VEC+2] ;Old vector seg to AX}
  85.     $8B/$1E/>KBD_VEC/ {MOV  BX,[>KBD_VEC]   ;Old vector ofs to BX}
  86.     $87/$5E/$0E/      {XCHG BX,[BP+$0E] ;Swap ofs w/ return address}
  87.     $87/$46/$10/      {XCHG AX,[BP+$10] ;Swap seg w/ return address}
  88.     $89/$EC/          {MOV  SP,BP ;UNDO procedure's entry code}
  89.     $5D/              {POP  BP}
  90.     $07/              {POP  ES}
  91.     $1F/              {POP  DS}
  92.     $5F/              {POP  DI}
  93.     $5E/              {POP  SI}
  94.     $5A/              {POP  DX}
  95.     $59/              {POP  CX}
  96.     $CB/              {RETF ;in effect, JMP to old vector}
  97. {Special_Key:}
  98.     $50/              {PUSH AX ;Save the key we got}
  99.     $E4/$61/          {IN   AL,$61  ;Read Kbd controller port}
  100.     $88/$C4/          {MOV  AH,AL}
  101.     $0C/$80/          {OR   AL,$80  ;Set the "reset" bit and}
  102.     $E6/$61/          {OUT  $61,AL  ;  send it back to control}
  103.     $86/$C4/          {XCHG AH,AL   ;Get back control value}
  104.     $E6/$61/          {OUT  $61,AL  ;  and send it too}
  105.     $58/              {POP  AX}
  106.     $04/$67/          {ADD  AL,$67  ;+67h makes it SuperKey code}
  107.     $B4/$00/          {MOV  AH,+$00 ;0 for Scan Code}
  108.     $86/$C4/          {XCHG AH,AL}
  109.     $8B/$1E/>TAIL/    {MOV  BX,[>TAIL]}
  110.     $89/$07/          {MOV  [BX],AX ;Put key in buffer}
  111.     $81/$C3/$02/$00/  {ADD  BX,+$02 ;Advance tail pointer}
  112.     $81/$FB/>BUFEND/  {CMP  BX,>BUFEND ;IF at end of buffer}
  113.     $7C/$03/          {JL   BufOK}
  114.     $BB/>KEYBUF/      {MOV  BX,>KEYBUF ;  set back to beginning}
  115. {BufOK:}
  116.     $89/$1E/>TAIL/    {MOV  [>TAIL],BX}
  117.     $80/$26/>KB_FLAG/$F7/  {AND BYTE PTR [>KB_FLAG],$F7}
  118.                            {Turn off ALT flag }
  119.     $1F/              {POP  DS      ;Restore TURBO DSeg}
  120.     $9D/              {POPF         ;Restore the flags}
  121.     $FA/              {CLI          ;No interrupts }
  122.     $B0/$20/          {MOV  AL,+$20 ;Send an EOI to the}
  123.     $E6/$20);         {OUT  $20,AL  ;  interrupt controller }
  124.   END;
  125.  
  126.   (* ========================================== *)
  127.   (* You _can_ end a UNIT with just an "END."   *)
  128.   (* statement, but if you end it with a        *)
  129.   (* "BEGIN..END." pair, the code between       *)
  130.   (* that pair will be executed automatically   *)
  131.   (* at the beginning of any program that       *)
  132.   (* USES the UNIT.                             *)
  133.   (* ========================================== *)
  134. BEGIN
  135.   CheckBreak := TRUE;
  136.   GetIntVec(Kbd_Int, Kbd_Vec);   {save "old" INT9}
  137.   SetIntVec(Kbd_Int, @INT9_ISR); {install new}
  138.   Exit_Vec := ExitProc;          {save old ExitProc}
  139.   ExitProc := @My_Error;         {install new}
  140. END.
  141.