(*  File    - RB_KBD.INC
   By      - Greg Teater
   Date    - December 29, 1987

   Purpose - This procedure, RB_Kbd,  waits for a key  to  be pressed on
             the Rainbow keyboard.  It returns the value  of a character
             or of a function key and the status of  the Control, Shift,
             and Lock keys.

   Details - All Rainbow keys return a unique code which can be captured
             with a firmware level 1 call.    This  call  is achieved by
             loading the DI register with a $06  and  making  a software
             interrupt $18.  If a key was pressed,  then the CL register
             returns a $FF, the AH register contains the status  of  the
             Control,  Shift, and Lock keys and the AL register contains
             the  code  of  the  function  or character key.  If the  AH
             register is odd, then a function key was pressed.  If even,
             then a character key was pressed.

             If the  CL register contains a $01, then the level 2 buffer
             has characters in  it.    These are then cleared out and CL
             set to $00 to  force  it  to  check  again  for  a  level 1
             character.  This is needed  to keep the level 2 buffer from
             filling, which can cause a hang problem.


   Usage   - Five variables are returned when RB_Kbd terminates.

                 (var Ch          : char;         { Character Pressed  }
                  var F_Key       : F_Key_Type;   { Function Key Value }
                  var Ctrl_Key,                   {\                   }
                      Shift_Key,                  { >  True If On      }
                      Lock_Key    : boolean);     {/                   }

             The F_Key should be used to test if a character was pressed
             or a function key.  If a character was pressed  then  F_Key
             will equal _Char.  If a function key was pressed, then  the
             F_Key will equal  the  corresponding value according to the
             Function  Key Return Value Table.  You  should always  test
             F_Key first for _Char then procede accordingly.

             The calling command should be structured as follows:

             RB_Kbd (Ch, F_Key, Ctrl_Key, Shift_Key, Lock_Key);


              F U N C T I O N   K E Y   R E T U R N   V A L U E

_Help _Do _PrintScreen _Char _F4 _Interrupt _Resume _Cancel _MainScreen _Exit
_AddtlnOptions  _F17  _F18  _F19  _F20  _Find  _InsertHere  _Remove   _Select
_PrevScreen _NextScreen  _UpArrow  _DownArrow _RightArrow _LeftArrow _KeyPad0
KeyPad1  _KeyPad2  _KeyPad3  _KeyPad4  _KeyPad5  _KeyPad6  _KeyPad7  _KeyPad8
_KeyPad9 _KeyPadMinus _KeyPadComma _KeyPadPeriod  _KeyPadEnter _PF1 _PF2 _PF3
_PF4 _Break

(*--------------------------------------------------------------------------*)

type
 F_Key_Type = (
   _Help, _Do, _Compose, _PrintScreen, _Char, _F4, _nul2, _Interrupt,
   _nul3, _Resume, _nul4, _Cancel, _nul5, _MainScreen, _nul6, _Exit,
   _nul7, _AddtlnOptions, _nul8, _F17, _nul9, _F18, _nul10, _F19,
   _nul11, _F20, _nul12, _Find, _nul13, _InsertHere, _nul14, _Remove,
   _nul15, _Select, _nul16, _PrevScreen, _nul17, _NextScreen, _nul18,
   _UpArrow, _nul19, _DownArrow, _nul20, _RightArrow, _nul21,
   _LeftArrow, _nul22, _KeyPad0, _nul23, _nul24, _KeyPad1, _nul25,
   _nul26, _KeyPad2, _nul27, _nul28, _KeyPad3, _nul29, _nul30, _KeyPad4,
   _nul31, _nul32, _KeyPad5, _nul33, _nul34, _KeyPad6, _nul35, _nul36,
   _KeyPad7, _nul37, _nul38, _KeyPad8, _nul39, _nul40, _KeyPad9, _nul41,
   _nul42, _KeyPadMinus, _nul43, _nul44, _KeyPadComma, _nul45, _nul46,
   _KeyPadPeriod, _nul47, _nul48, _KeyPadEnter, _nul49, _nul50, _PF1,
   _nul51, _nul52, _PF2, _nul53, _nul54, _PF3, _nul55, _nul56, _PF4,
   _nul57, _nul58, _Break);

const
 F_Keys : array [$0..$65] of F_Key_Type = (
   _Help, _Do, _Compose, _PrintScreen, _Char, _F4, _nul2, _Interrupt,
   _nul3, _Resume, _nul4, _Cancel, _nul5, _MainScreen, _nul6, _Exit,
   _nul7, _AddtlnOptions, _nul8, _F17, _nul9, _F18, _nul10, _F19,
   _nul11, _F20, _nul12, _Find, _nul13, _InsertHere, _nul14, _Remove,
   _nul15, _Select, _nul16, _PrevScreen, _nul17, _NextScreen, _nul18,
   _UpArrow, _nul19, _DownArrow, _nul20, _RightArrow, _nul21,
   _LeftArrow, _nul22, _KeyPad0, _nul23, _nul24, _KeyPad1, _nul25,
   _nul26, _KeyPad2, _nul27, _nul28, _KeyPad3, _nul29, _nul30, _KeyPad4,
   _nul31, _nul32, _KeyPad5, _nul33, _nul34, _KeyPad6, _nul35, _nul36,
   _KeyPad7, _nul37, _nul38, _KeyPad8, _nul39, _nul40, _KeyPad9, _nul41,
   _nul42, _KeyPadMinus, _nul43, _nul44, _KeyPadComma, _nul45, _nul46,
   _KeyPadPeriod, _nul47, _nul48, _KeyPadEnter, _nul49, _nul50, _PF1,
   _nul51, _nul52, _PF2, _nul53, _nul54, _PF3, _nul55, _nul56, _PF4,
   _nul57, _nul58, _Break);

procedure RB_Kbd (var Ch          : char;          { Character Pressed  }
                 var F_Key       : F_Key_Type;    { Function Key Value }
                 var Ctrl_Key,                    {\                   }
                     Shift_Key,                   { >  True If On      }
                     Lock_Key    : boolean);      {/                   }

 var    register : record case integer of
                     1 : (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags : integer);
                     2 : (AL,AH,BL,BH,CL,CH,DL,DH : byte);
                   end;

 begin  { RB_Kbd }
  repeat
    register.di := $06;                  { set up to read keyboard         }
    Intr ($18,register);                 { lets read it                    }
    if register.cl = $01    { does the level 2 buffer contain characters ? }
      then
        begin                                                        { yes }
          register.dl := $FF;         { \                                  }
          register.ah := $0C;         {  \                                 }
          register.al := $06;         {   -  Clears Level 2 input buffer   }
          MsDos (register);           {  /                                 }
          register.cl := $00;                       { force back into loop }
       end;
  until register.cl = $FF;               { repeat until key is pressed     }

   if odd (register.ah)                  { true if function key was pressed }
     then F_Key := F_Keys [register.al]  { assign function key type name    }
     else
       begin
         F_key := _Char;                { assign something to test for when }
                                        { RB_Kbd returns                    }
         Ch := chr (register.al);       { assign char value of key          }
       end;

   Ctrl_Key := register.ah in [$4,$5,$6,$7,$C,$D,$E,$F];    {  true if on   }
   Shift_Key := register.ah in [$2,$3,$6,$7,$A,$B,$E,$F];   {  or pressed   }
   Lock_Key := register.ah in [$8..$F];                     {               }
 end; { RB_Kbd }