(*
 * Svgalib-Gpc - Pascal porting of Svgalib header files.
 * Copyright 1999, 2000 (C) Nicola Girardi <girardi@vicenza.linux.it>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *)

(*
 *  This is not the plain translation of vgakeyboard.h, but it's
 *  a modified raw keyboard support as vganormalkeyboard.pas is
 *  for normal keyboard mode.
 *
 *  If you want to use your own handlers just go to vgakeyboard.h
 *  and look at the prototypes you need. Then you know, it's up to you.
 *)

unit VgaRawKeyboard;

interface

uses GPC; (* for TFDDs *)

(* Keyboard interface for svgalib.
 * Can be used independently.
 *)

const NR_KEYS = 128;

type
  TStateType = array [0 .. NR_KEYS - 1] of Byte;
  PStateType = ^TStateType;

var KeyboardState: PStateType;

const SCANCODE_ESCAPE = 1;

      SCANCODE_1 = 2;
      SCANCODE_2 = 3;
      SCANCODE_3 = 4;
      SCANCODE_4 = 5;
      SCANCODE_5 = 6;
      SCANCODE_6 = 7;
      SCANCODE_7 = 8;
      SCANCODE_8 = 9;
      SCANCODE_9 = 10;
      SCANCODE_0 = 11;

      SCANCODE_MINUS = 12;
      SCANCODE_EQUAL = 13;

      SCANCODE_BACKSPACE = 14;
      SCANCODE_TAB = 15;

      SCANCODE_Q = 16;
      SCANCODE_W = 17;
      SCANCODE_E = 18;
      SCANCODE_R = 19;
      SCANCODE_T = 20;
      SCANCODE_Y = 21;
      SCANCODE_U = 22;
      SCANCODE_I = 23;
      SCANCODE_O = 24;
      SCANCODE_P = 25;
      SCANCODE_BRACKET_LEFT = 26;
      SCANCODE_BRACKET_RIGHT = 27;

      SCANCODE_ENTER = 28;

      SCANCODE_LEFTCONTROL = 29;

      SCANCODE_A = 30;
      SCANCODE_S = 31;
      SCANCODE_D = 32;
      SCANCODE_F = 33;
      SCANCODE_G = 34;
      SCANCODE_H = 35;
      SCANCODE_J = 36;
      SCANCODE_K = 37;
      SCANCODE_L = 38;
      SCANCODE_SEMICOLON = 39;
      SCANCODE_APOSTROPHE = 40;
      SCANCODE_GRAVE = 41;

      SCANCODE_LEFTSHIFT = 42;
      SCANCODE_BACKSLASH = 43;

      SCANCODE_Z = 44;
      SCANCODE_X = 45;
      SCANCODE_C = 46;
      SCANCODE_V = 47;
      SCANCODE_B = 48;
      SCANCODE_N = 49;
      SCANCODE_M = 50;
      SCANCODE_COMMA = 51;
      SCANCODE_PERIOD = 52;
      SCANCODE_SLASH = 53;

      SCANCODE_RIGHTSHIFT = 54;
      SCANCODE_KEYPADMULTIPLY = 55;

      SCANCODE_LEFTALT = 56;
      SCANCODE_SPACE = 57;
      SCANCODE_CAPSLOCK = 58;

      SCANCODE_F1 = 59;
      SCANCODE_F2 = 60;
      SCANCODE_F3 = 61;
      SCANCODE_F4 = 62;
      SCANCODE_F5 = 63;
      SCANCODE_F6 = 64;
      SCANCODE_F7 = 65;
      SCANCODE_F8 = 66;
      SCANCODE_F9 = 67;
      SCANCODE_F10 = 68;

      SCANCODE_NUMLOCK = 69;
      SCANCODE_SCROLLLOCK = 70;

      SCANCODE_KEYPAD7 = 71;
      SCANCODE_CURSORUPLEFT = 71;
      SCANCODE_KEYPAD8 = 72;
      SCANCODE_CURSORUP = 72;
      SCANCODE_KEYPAD9 = 73;
      SCANCODE_CURSORUPRIGHT = 73;
      SCANCODE_KEYPADMINUS = 74;
      SCANCODE_KEYPAD4 = 75;
      SCANCODE_CURSORLEFT = 75;
      SCANCODE_KEYPAD5 = 76;
      SCANCODE_KEYPAD6 = 77;
      SCANCODE_CURSORRIGHT = 77;
      SCANCODE_KEYPADPLUS = 78;
      SCANCODE_KEYPAD1 = 79;
      SCANCODE_CURSORDOWNLEFT = 79;
      SCANCODE_KEYPAD2 = 80;
      SCANCODE_CURSORDOWN = 80;
      SCANCODE_KEYPAD3 = 81;
      SCANCODE_CURSORDOWNRIGHT = 81;
      SCANCODE_KEYPAD0 = 82;
      SCANCODE_KEYPADPERIOD = 83;

      SCANCODE_LESS = 86;

      SCANCODE_F11 = 87;
      SCANCODE_F12 = 88;

      SCANCODE_KEYPADENTER = 96;
      SCANCODE_RIGHTCONTROL = 97;
      SCANCODE_CONTROL = 97;
      SCANCODE_KEYPADDIVIDE = 98;
      SCANCODE_PRINTSCREEN = 99;
      SCANCODE_RIGHTALT = 100;
      SCANCODE_BREAK = 101; (* Beware: is 119 *)
      SCANCODE_BREAK_ALTERNATIVE = 119; (* on some keyboards! *)

      SCANCODE_HOME = 102;
      SCANCODE_CURSORBLOCKUP = 103; (* Cursor key block *)
      SCANCODE_PAGEUP = 104;
      SCANCODE_CURSORBLOCKLEFT = 105; (* Cursor key block *)
      SCANCODE_CURSORBLOCKRIGHT = 106; (* Cursor key block *)
      SCANCODE_END = 107;
      SCANCODE_CURSORBLOCKDOWN = 108; (* Cursor key block *)
      SCANCODE_PAGEDOWN = 109;
      SCANCODE_INSERT = 110;
      SCANCODE_REMOVE = 111;

      SCANCODE_RIGHTWIN = 126;
      SCANCODE_LEFTWIN = 125;

      KEY_EVENTRELEASE = 0;
      KEY_EVENTPRESS = 1;

      MAX_KEYNAME_LEN = 20;


(* Read raw keyboard device and handle events. Returns 0 if no event. *)
function KeyboardUpdate : Integer; asmname 'keyboard_update';

(* Similar to keyboard_update, but wait for an event to happen. *)
(* [This doesn't seem to work very well -- use select on fd] *)
procedure KeyboardWaitForUpdate; asmname 'keyboard_waitforupdate';

(* Result of keypressed. *)
const KEY_NOTPRESSED = 0;
      KEY_PRESSED = 1;

(* Modes for translatekeys. *)
const TRANSLATE_CURSORKEYS = 1;  (* Map cursor block to keypad cursor. *)
      TRANSLATE_DIAGONAL = 2;    (* Map keypad diagonal to keypad cursor. *)
      TRANSLATE_KEYPADENTER = 4; (* Map keypad enter to main enter key. *)
      DONT_CATCH_CTRLC = 8;      (* Disable Crtl-C check. *)


var KeyboardFile: Text; (* the keyboard file we want to select on *)

(* check if any key is pressed *)
function RawAnyKeyPressed : Boolean;

(* tells if 'scancode' was pressed *)
function RawKeyPressed(scancode: Integer) : Boolean;

(* waits for input (if it's not there yet) and read it *)
function RawWaitKey : Integer;

procedure RawKeyboardInit;
procedure RawKeyboardFlush; (* sets all keys to be released *)
procedure RawKeyboardClose;


implementation

var KeyboardFD : Integer = -1;

(* fd to select on *)
function KeyboardSelectFunc (var PrivateData; Writing: Boolean) : Integer;
begin
  if Writing then KeyboardSelectFunc:= -1
             else KeyboardSelectFunc:= KeyboardFD;
end;

(* used by Reset(RawKeyboardFile) *)
procedure KeyboardOpenProc (var PrivateData; Mode: TOpenMode);

function  svgalib_keyboard_init_return_fd : Integer; asmname 'keyboard_init_return_fd';
(*procedure svgalib_keyboard_setdefaulteventhandler; asmname 'keyboard_setdefaulteventhandler';*)
procedure svgalib_keyboard_translatekeys(mask: Integer); asmname 'keyboard_translatekeys';

begin
   if KeyboardFD = -1 then
      begin
        KeyboardFD:= svgalib_keyboard_init_return_fd;
        (*svgalib_keyboard_setdefaulteventhandler;*)

        (* svgalib_keyboard_init_return_fd already set this
         *
         * you can change this writing you own TOpenProc procedure
         * with your own handler
         *)

        svgalib_keyboard_translatekeys(TRANSLATE_CURSORKEYS or TRANSLATE_DIAGONAL or TRANSLATE_KEYPADENTER);
        (* this is the default for ME *)
      end;
end;


(* used by Close(RawKeyboardFile) *)
procedure KeyboardCloseProc(var PrivateData);
procedure svgalib_keyboard_close; asmname 'keyboard_close';
begin
  svgalib_keyboard_close;
  KeyboardFD:= -1;
end;

(* used by Flush(KeyboardFile) *)
procedure KeyboardFlushProc(var PrivateData);
(* Force keyboard state to nothing pressed (all zeroes). *)
procedure svgalib_keyboard_clearstate; asmname 'keyboard_clearstate';
begin
   svgalib_keyboard_clearstate;
end;

procedure RawKeyboardFlush;
begin
   Flush(KeyboardFile);
end;


procedure RawKeyboardInit;
begin
  AssignTFDD(KeyboardFile, KeyboardOpenProc, KeyboardSelectFunc,
             TSelectProc(nil), TReadFunc(nil), TWriteFunc(nil),
             KeyboardFlushProc, KeyboardCloseProc, TDoneProc(nil),
             Pointer(nil));

  Reset(KeyboardFile);
end;

procedure RawKeyboardClose;
begin
  Close(KeyboardFile);
end;

function KeyboardGetState : PStateType; asmname 'keyboard_getstate';

function RawAnyKeyPressed : Boolean; (* tells if any key is pressed *)
var i, Dummy : Integer; (* to avoid warnings *)
begin
  if (KeyboardFD = -1) (* keyboard uninitialized *)
     then RawAnyKeyPressed:= false;

  Dummy:= KeyboardUpdate; (* check for events *)

  KeyboardState:= KeyboardGetState;

  RawAnyKeyPressed:= false;

  for i:= Low(KeyboardState^) to High(KeyboardState^) do
      if ( KeyboardState^[i] = KEY_PRESSED ) then
         begin
           RawAnyKeyPressed:= true;
           Exit;
         end;
end;
   

function RawKeyPressed (scancode: Integer) : Boolean; (* tells if Key is pressed *)
var Dummy: Integer; (* to avoid warnings *)
begin
  if (KeyboardFD = -1) (* keyboard uninitialized *)
     then RawKeyPressed:= false;

  Dummy:= KeyboardUpdate; (* check for events *)
  KeyboardState:= KeyboardGetState;

  RawKeyPressed:= ( KeyboardState^[scancode] = KEY_PRESSED );
end;

function RawWaitKey : Integer;
var
  i: Integer;
begin
   RawKeyboardFlush;
   KeyboardWaitForUpdate;

   for i:= 0 to (NR_KEYS-1) do
      if ( KeyboardState^[i] = KEY_PRESSED ) then RawWaitKey:= i;
end;

end.


syntax highlighted by Code2HTML, v. 0.8.8b