```Unit KeyBoard;

{ Ž¡ëç­® ª« ¢¨ âãà  ¯®áë« ¥â á¨¬¢®«ë ¢ ª®¬¯ìîâ¥à }
{ á ¬ ªá¨¬ «ì­®© áª®à®áâìî 4 èâãª¨ ¢ á¥ªã­¤ã. }
{ —â®¡ë ¨£àãèª  ­¥ ¯à®áâ ¨¢ «  ¢ ®¦¨¤ ­¨¨ ¢¢®¤  á ª« ¢¨ âãàë }
{ ­ã¦­® à¥ «¨§®¢ âì á«¥¤ãîé¨©  «£®à¨â¬: }
{ 1) ¢ ­ ç «¥ ¯à®£à ¬¬ë ¤®¯ãáâ¨âì, çâ® ¢á¥ ª« ¢¨è¨ ®â¯ãé¥­ë }
{    ¢ æ¨ª«¥ ¯à®£à ¬¬ë: }
{ 2) áç¨â âì ­ ¦ âë¬¨ â¥ ª« ¢¨è¨, ª®â®àë¥ ­¥ ®â¯ãé¥­ë }
{ 3) ¯®  ­ «®£¨¨ áç¨â âì ®â¯ãé¥­­ë¬¨ ­¥ ­ ¦ âë¥ }
{ ‘®¡áâ¢¥­­® íâ®â ¬®¤ã«ì ¨ ¯®¬®£ ¥â à¥ «¨§®¢ âì á¥©  «£®à¨â¬: }
{ Set_Handler -> 1) }
{ New_Handler -> 2), 3) }

Interface

{ ‡¤¥áì áª ­ª®¤ë ¯®çâ¨ ¢á¥å ª« ¢¨è }

Const
sEsc          =       1;
s1            =       2;
s2            =       3;
s3            =       4;
s4            =       5;
s5            =       6;
s6            =       7;
s7            =       8;
s8            =       9;
s9            =     \$0A;
s0            =     \$0B;
sMinus        =     \$0C;              { - _ }
sEqual        =     \$0D;              { = + }
sBackSpace    =     \$0E;
sTab          =     \$0F;
sQ            =     \$10;
sW            =     \$11;
sE            =     \$12;
sR            =     \$13;
sT            =     \$14;
sY            =     \$15;
sU            =     \$16;
sI            =     \$17;
sO            =     \$18;
sP            =     \$19;
sLBraket      =     \$1A;             (* [ { *)
sRBraket      =     \$1B;             (* ] } *)
sEnter        =     \$1C;
sCtrl         =     \$1D;
sA            =     \$1E;
sS            =     \$1F;
sD            =     \$20;
sF            =     \$21;
sG            =     \$22;
sH            =     \$23;
sJ            =     \$24;
sK            =     \$25;
sL            =     \$26;
sSemicolon    =     \$27;              { ; :  }
sQuote        =     \$28;              { ' "  }
sApostrophe   =     \$29;              { ` ~  }
sLShift       =     \$2A;
sSlash        =     \$2B;              { \ |  }
sZ            =     \$2C;
sX            =     \$2D;
sC            =     \$2E;
sV            =     \$2F;
sB            =     \$30;
sN            =     \$31;
sM            =     \$32;
sComma        =     \$33;              { , <  }
sPoint        =     \$34;              { . >  }
sBackSlash    =     \$35;              { / ?  }
sRShift       =     \$36;
sAsteriks     =     \$37;              { *  ­  æ¨äà®¢®© ª« ¢¨ âãà¥ }
sAlt          =     \$38;
sSpace        =     \$39;              { ¯à®¡¥« }
sCapsLock     =     \$3A;
sF1           =     \$3B;
sF2           =     \$3C;
sF3           =     \$3D;
sF4           =     \$3E;
sF5           =     \$3F;
sF6           =     \$40;
sF7           =     \$41;
sF8           =     \$42;
sF9           =     \$43;
sF10          =     \$44;
sNumLock      =     \$45;
sScrollLock   =     \$46;
sHome         =     \$47;
sUp           =     \$48;
sPageUp       =     \$49;
sGrayMinus    =     \$4A;              { -  ­  æ¨äà®¢®© ª« ¢¨ âãà¥ }
sLeft         =     \$4B;
sFive         =     \$4C;              { 5  ­  æ¨äà®¢®© ª« ¢¨ âãà¥ }
sRight        =     \$4D;
sGrayPlus     =     \$4E;              { +  ­  æ¨äà®¢®© ª« ¢¨ âãà¥ }
sEnd          =     \$4F;
sDown         =     \$50;
sPageDown     =     \$51;
sInsert       =     \$52;
sDelete       =     \$53;
sF11          =     \$57;
sF12          =     \$58;

Var
KeyMap : Array [0..\$7F] of Boolean;   { ‘¬¥é¥­¨¥-áª ­ª®¤ ª« ¢¨è¨, TRUE - }
{ ­ ¦ â  á¥©ç á, FALSE - ®â¯ãé¥­  }
SymMap : Array [0..\$7F] of Char;      { ‘¬¥é¥­¨¥-áª ­ª®¤ ª« ¢¨è¨, }
{ á®¤¥à¦¨¬®¥ - ASCII-á¨¬¢®«ë ¤«ï ª« ¢¨è }

Procedure Set_Handler;
{ “áâ ­ ¢«¨¢ ¥â ­®¢ë© ®¡à ¡®âç¨ª ª« ¢¨ âãà­®£® ¯à¥àë¢ ­¨ï, }
{ ª®£¤  ­®¢ë© ®¡à ¡®âç¨ª  ªâ¨¢¥­, â® …‚Ž‡ŒŽ†Ž ¯®«ì§®¢ âìáï }
{ KeyPressed, ReadKey ¨ Read,   â ª¦¥ ®áâ ­ ¢«¨¢ âì ¯à®£à ¬¬ã }
{ ¯® Ctrl+C (Ctrl+Break) ¨«¨ ¥¥ ®â« ¦¨¢ âì. }
{ KeyPressed ¨ ReadKey ¨¬¥îâ  ­ «®£¨ - á¬®âà¨ ­¨¦¥ }

Procedure Remove_Handler;
{ ‚®§¢à é ¥â áâ àë© ®¡à ¡®âç¨ª ª« ¢¨ âãà­®£® }
{ ¯à¥àë¢ ­¨ï ­  ¥£® § ª®­­®¥ ¬¥áâ® }

Procedure WaitForACSReleased;
{ †¤¥â ®â¯ãáª ­¨ï Alt,Ctrl,Shift; ¨á¯®«ì§ã¥âáï ’Ž‹œŠŽ ……„ }
{ ãáâ ­®¢ª®© ­®¢®£® ®¡à ¡®âç¨ª  ª« ¢¨ âãà­®£® ¯à¥àë¢ ­¨ï }

Function KeyPressedNow : Boolean;
{ ‚®§¢à é ¥â TRUE ¥á«¨ ¢ „€›‰ ¬®¬¥­â ¢à¥¬¥­¨ }
{ ¤¥©áâ¢¨â¥«ì­® ­ ¦ â  å®âï¡ë ®¤­  ª« ¢¨è , ¨­ ç¥ ¢®§¢à é ¥â FALSE. }
{ ˆá¯®«ì§ã¥âáï ¢¬¥áâ¥ á ¬ áá¨¢ ¬¨ KeyMap ¨ SymMap }

Function KeyPressed2 : Boolean;
{ ®«­ë©  ­ «®£ ä-æ¨¨ KeyPressed ¨§ ¬®¤ã«ï CRT. }

{ €­ «®£ ä-æ¨¨ ReadKey (¬®¤ã«ì CRT). }
{  §­¨æ  ¢ â®¬, çâ® íâ  ä-æ¨ï ¢®§¢à é ¥â }
{ ­¥ á¨¬¢®« ª« ¢¨è¨,   ¥¥ áª ­ª®¤, ¯®§¢®«ïï }
{ ¤®¡à âìáï ¤® ª ¦¤®© ª« ¢¨è¨. }
{ ˆá¯®«ì§ã¥âáï ¢¬¥áâ¥ á KeyPressed2 }

{ €­ «®£ ä-æ¨¨ ReadKey (¬®¤ã«ì CRT). }
{  §­¨æ  ¢ â®¬, çâ® íâ  ä-æ¨ï ¢®§¢à é ¥â }
{ á¨¬¢®« ª« ¢¨è¨ ¡¥§ ãç¥â  á®áâ®ï­¨© Alt,Ctrl,Shift ¨ Caps Lock. }
{ …á«¨ ­ ¦ â ï ª« ¢¨è  ­¥ ¨¬¥¥â ­  á¥¡¥ á¨¬¢®« , â® ¢®§¢à é ¥âáï }
{ ­ã«¥¢®© á¨¬¢®«, ­¨ ® ª ª¨å à áè¨à¥­­ëå ª®¤ å §¤¥áì à¥ç¨ ¡ëâì ­¥ }
{ ¬®¦¥â. ˆá¯®«ì§ã¥âáï ¢¬¥áâ¥ á KeyPressed2 }

Procedure ClearKeyboardBuf;

Implementation

Uses DOS;

Const
Old_Handler : Pointer = Nil;          { ‘î¤  á®åà ­¨¬  ¤à¥á áâ à®£® ®¡à ¡®âç¨ª  }
KeyBufSize            = 16;           { Š« ¢¨ âãà­ë© ¡ãä¥à ¡ã¤¥â á®¤¥à¦ âì }
{ ¬ ªá¨¬ã¬ 16 áª ­ª®¤®¢ }

Symbs : Array [sEsc..sSpace] of Char =
#27'1234567890-='#8#9'QWERTYUIOP[]'#13#0'ASDFGHJKL;''`'#0'\'+
'ZXCVBNM,./'#0'*'#0' ';

Var
KeyBuf : Array [0..KeyBufSize] of Byte;       { Š®«ìæ¥¢®© ª« ¢¨ âãà­ë© ¡ãä¥à }
BufTail : Word;                               { •¢®áâ ¡ãä¥à  }
KeyCount : Byte;                              { Š®«-¢® áª ­ª®¤®¢ ª« ¢¨è }
{ ¢ ¡ãä¥à¥ }

Procedure New_Handler; Interrupt; Assembler;
{ Using assembler because we need a fast interrupt-handling routine }
Asm
Push  AX
Push  BX
In    AL, 060h
Mov   AH, AL
And   AL, 07Fh                                { AL = ‘ª ­ª®¤ }
LEA   BX, KeyMap
Test  AH, 080h
JNZ   @released                               { ‘â àè¨© ¡¨â - ä« £ ®â¯ãáª ­¨ï }
Mov   Byte Ptr [BX], TRUE                     { Š« ¢¨è  ¡ë«  ­ ¦ â  }
Cmp   KeyCount, KeyBufSize
JE    @done                                   { ãä¥à ¡¨âª®¬ ­ ¡¨â }
LEA   BX, KeyBuf
Mov   [BX], AL                                { ‘®åà ­¨«¨ áª ­ª®¤ ¢ KeyBuf }
Inc   KeyCount                                { More keys avaible to read }
Inc   BufTail                                 { ‘«¥¤ãîé ï ¯®§¨æ¨ï ¤«ï á®åà ­¥­¨ï }
Cmp   BufTail, KeyBufSize
JNE   @done
Mov   BufTail, 0                              { ‘ª®àà¥ªâ¨à®¢ «¨ ¯®§¨æ¨î }
Jmp   @done
@released:
Mov   Byte Ptr [BX], FALSE                    { Š« ¢¨è  ¡ë«  ®â¯ãé¥­  }
@done:
Mov   AL, 020h                                { ‘®®¡é¨«¨ ª®­âà®««¥àã }
Out   020h, AL                                { ¯à¥àë¢ ­¨©, çâ® ¯à¥àë¢ ­¨¥ }
{ ®¡à ¡®â ­® }
Pop   BX
Pop   AX
End;

Procedure Set_Handler;
Begin
If Old_Handler <> Nil then Exit;
FillChar (KeyMap, \$80, False);        { ˆ§­ ç «ì­® áç¨â ¥¬ ¢á¥ ª« ¢¨è¨ }
KeyCount := 0;                        { ®â¯ãé¥­­ë¬¨ }
BufHead := 0;                         { -//- }
BufTail := 0;                         { -//- }
GetIntVec (9, Old_Handler);
SetIntVec (9, @New_Handler)
End;

Procedure Remove_Handler;
Begin
If Old_Handler = Nil then Exit;
SetIntVec (9, Old_Handler);
Old_Handler := Nil
End;

Procedure WaitForACSReleased;
Begin
While Mem[\$40:\$17] and \$0F <> 0 do
End;

Function KeyPressedNow : Boolean; Assembler;
{    áá¥¬¡«¥à¥ à ¡®â ¥â èãáâà¥¥, ç¥¬ ­   áª «¥ }
Asm
Mov   AX, DS
Mov   ES, AX
LEA   DI, KeyMap+1                            {  ç¨­ ¥¬ á Escape }
Mov   CX, 058h                                { ‚á¥ ª« ¢¨è¨ ¯«îá F11 ¨ F12 }
Mov   AL, FALSE                               { à¥¤¯®«®¦¨«¨, çâ® ¯ãáâ® }
CLD
RepE  ScaSB                                   { ‘ª ­­¨àã¥¬ ¬ áá¨¢ KeyMap }
JE    @end                                    { ãáâ® }
Mov   AL, TRUE                                { —â®-â® ­ ¦ â® }
@end:
End;

Function KeyPressed2 : Boolean;
Begin
KeyPressed2 := KeyCount<>0                    { ãä¥à ­¥ ¯ãáâ }
End;

Begin
While KeyCount=0 do;
Dec (KeyCount)                                { Ž¤­ã ª« ¢¨èã ¤®«®© }
End;

Begin
End;

Procedure ClearKeyboardBuf;
Begin
Asm PushF; CLI End;
KeyCount := 0;
Asm PopF End
End;

Var I : Byte;

Begin
{ ‡ ¯®«­¥­¨¥ ¬ áá¨¢  á¨¬¢®«®¢ }
FillChar (SymMap, \$80, 0);
For I := sEsc to sSpace do
SymMap[I] := Symbs[I];
SymMap[sGrayMinus] := '-';
SymMap[sGrayPlus] := '+'
End.
```
Published in: Pascal