|Dͻ
|D |5The Happy Hacker |D
|Dͼ

^C^1Bits 'N PC's
^Cby
^CGeorge Leritte

   This month we will talk about keyboard input/output for the PC.  Everybody 
knows that you can get standard keystrokes just by using input statements in 
your favorite language.  All of the letters and numbers and special characters 
can be gotten simply by using input.  However, what about the numeric keypad 
keys or the function keys.  The numeric keypad keys can be accessed by forcing 
users to press the NumLock key and checking for standard number entry.  However, 
this is not the recommended method of getting keypad keystrokes, because you 
cannot tell the difference between a number key and a keypad key in most normal 
operations.  The keypad, function keys and all Alt-combination keys generate 
what is known as extended codes.  There is one method in BASIC to get an 
extended code and one in Turbo Pascal.  You can also easily detect if any of the 
"shift" keys are being pressed.  The "shift" keys are the Ctrl, Alt, Left 
shift, and Right shift keys.  You can also easily determine the status of any of 
the "toggle" keys: the Caps Lock, NumLock, ScrollLock, and Ins keys.  We will 
present BASIC and Turbo Pascal code for these routines. 

   First, we will present the scan codes for the keyboard.  If you have seen in 
any of the manuals a listing of the scan codes and wondered exactly what they 
were, here is your answer.  Below is a crude drawing of the original IBM 
keyboard with each key labeled.  Below each label is its scan code, the number 
the keyboard itself generates when a key is pressed.  BIOS uses this number to 
generate the proper character.  It checks the status of the "shift" keys and 
uses a table to place the proper codes to the keyboard input buffer where all 
DOS and BIOS keyboard services look for the keystroke.  Most languages generate 
two characters if one of the function keys, keypad or Alt-key combinations is 
struck.  In BASIC, these characters are ASCII character "0" and the scan code of 
the key that was struck.  In Turbo Pascal, these characters are ESC and the scan 
code.  There are some exceptions and additions to this rule and Turbo Pascal 
allows some extra keystroke combinations which I will list. 

^1ͻͻ
^1F1F2Esc 1  2  3  4  5  6  7  8  9  0  -  =  -   Num  Scroll
^15960 1  2  3  4  5  6  7  8  9 10 11 12 13 14    69     70  
^1͹͹
^1F3F4-- Q  W  E  R  T  Y  U  I  O  P  [  ]            - 
^16162 15 16 17 18 19 20 21 22 23 24 25 26 27    71 72 73 74
^1͹͹͹
^1F5F6Ctrl  A  S  D  F  G  H  J  K  L  ;  '  `28 -     -  
^16364 29  30 31 32 33 34 35 36 37 38 39 40 41   75 76 77   
^1͹͹  
^1F7F8   \  Z  X  C  V  B  N  M  ,  .  /     *         + 
^1656642 43 44 45 46 47 48 49 50 51 52 53 54  55 79 80 81 78
^1͹͹  
^1F9F0 Alt              Space Bar                  Caps   Ins    Del    
^16768 56                  57                      58     82     83     
^1ͼͼ

   I lump the Ctrl, Alt, and Shift keys into a "shift" key category because 
they all have the same effect, that of changing the default keystroke sent to 
the computer.  "A" is simply a shifted "a", "!" is a shifted "1", and so on.  A 
different code is generated when you press any function key while holding down 
any of the "shift" keys or when you hold the Ctrl and a keypad key.  These 
codes are listed below.  The number is an ASCII value unless it has a plus sign 
before it.  Then it is an extended code preceeded by BASIC's ASCII 0 or Turbo 
Pascal's Escape code.  A number in brackets <> indicates it is available in 
Turbo Pascal only and generates no character or code.  A number or letter in 
quotes means the combination generates that character(s).  If it is empty, it 
generates no character or code. 

Key  +          Shift           Ctrl            Alt
F1              +84             +94             +104
F2              +85             +95             +105
F3              +86             +96             +106
F4              +87             +97             +107
F5              +88             +98             +108
F6              +89             +99             +109
F7              +90             +100            +110
F8              +91             +101            +111
F9              +92             +102            +112
F10             +93             +103            +113
Home            "7"             +119           <+174>
Up Arrow        "8"            <+160>          <+175>
PgUp            "9"             +132           <+176>
Left Arrow      "4"             +115           <+178>
Right Arrow     "6"             +115           <+180>
End             "1"             +117           <+182>
Dn Arrow        "2"            <+164>          <+184>
PgDn            "3"             +118           <+183>
Ins             "0"            <+165>          <+185>
Del             "."            <+166>          <+186>
Tab             +15
Bkspc           8               127
a-z             "A-Z"           1-26            +scan code
1-0             "!-)"           see below       +121-129
-               "_"             31              +130
=               "+"                             +131
[               "{"             27
\               "||"             28
]               "}"             29
PrtSc                           114

   Note: Ctrl-2 generates +3 and Ctrl-6 generates 30.  Any unlisted keys 
provide only that character and its shifted version.

   The BASIC code for getting an extended code is below.  ExtCode is equal to -1 
if an extended code combination has been used and a$ is the string of length 1 
returned.

^1ExtCode = 0
^1a$ = "" : while a$ = "" : a$ = inkey$ : wend
^1if len(a$)=2 then ExtCode = -1 : a$= right$(a$,1)

   The Turbo Pascal code is below.  ExtCode is true if an extended code 
combination has been pressed and Ch is the character returned.

^1if KeyPressed then
^1begin
^1  ExtCode := false;
^1  Read(Kbd,Ch);                                             { ch is character }
^1  if (ch = #27) and keypressed then                     { one more character? }
^1  begin
^1    read(Kbd,Ch);
^1    ExtCode := true                                      { ExtCode is boolean }
^1  end
^1end;

   You can determine the "shift" key status by using the subroutines below.  The 
first is for BASIC and the second is for Turbo Pascal.

^1Key.Status:
^1 def seg = 0 : KeyStat = peek(1047)
^1 bs = (KeyStat and 3) = 3)                    :rem both shifts down
^1 rs = (KeyStat and 1) = 1                     :rem right shift down
^1 ls = (KeyStat and 2) = 2                     :rem left shift down
^1 es = (rs or ls)                              :rem either shift down
^1 ct = (KeyStat and 4) = 4                     :rem Ctrl down
^1 al = (KeyStat and 8) = 8                     :rem Alt down
^1 is = (KeyStat and 128) = 128                 :rem insert active
^1 ca = (KeyStat and 64) = 64                   :rem CapsLock active
^1 nu = (KeyStat and 32) = 32                   :rem NumLock active
^1 sc = (KeyStat and 16) = 16                   :rem ScrollLock active
^1return


^1Function Key_status (check : integer) : boolean;
^1{call with integer indicating type of check.
^1 0 - both shift keys pressed
^1 1 - right shift key pressed
^1 2 - left shift key pressed
^1 3 - either shift key pressed
^1 4 - ctrl key pressed
^1 5 - Alt key pressed
^1 6 - Insert mode activated
^1 7 - CapsLock key activated
^1 8 - NumLock key activated
^1 9 - ScrollLock key active}

^1var
^1  key : integer absolute $0000:$0417

^1begin
^1  KeyStat := key;
^1  Key_status := false;
^1  case check of
^1    0 : Key_status := (KeyStat and 3) = 3;
^1    1 : Key_status := (KeyStat and 1) = 1;
^1    2 : Key_status := (KeyStat and 2) = 2;
^1    3 : Key_status := ((KeyStat and 1) = 1) or ((KeyStat and 2) = 2);
^1    4 : Key_status := (KeyStat and 4) = 4;
^1    5 : Key_status := (KeyStat and 8) = 8;
^1    6 : Key_status := (KeyStat and 128) = 128;
^1    7 : Key_status := (KeyStat and 64) = 64;
^1    8 : Key_status := (KeyStat and 32) = 32;
^1    9 : Key_status := (KeyStat and 16) = 16;
^1end;

   This covers our basic keyboard tricks.  See you next month.
