unit KeyNames;

{ Graphics Vision Unit,
  Copr. 1995, 1997 Matthias Koeppe

  Determines the name of a key specified by its scan-code, using
  language-dependent components.
}

{$ifndef FPK}
{$A+,B-,F+,G+,I-,O+,P-,Q-,R-,S-,T-,V+,X+}
{$endif FPK}

interface

{$ifdef FPK}
uses Objects, Drivers, Strings, GVFPK, GvTexts, GvViews, GvMenus;
{$else}
{$ifdef Windows}
uses WinRes, WinGr, GvViews, GvMenus;
{$else}
uses WinRes, GvViews, GvMenus;
{$endif}
{$endif}

const
  sComposeKeys   = 200;
  sSequenceKeys  = 201;
  sAltModifier   = 202;
  sCtrlModifier  = 203;
  sShiftModifier = 204;
  sFunctionKey   = 205;
  sEscapeKey     = 206;
  sTabKey        = 207;
  sPrintKey      = 208;
  sScrollKey     = 209;
  sPauseKey      = 210;
  sBackspaceKey  = 211;
  sEnterKey      = 212;
  sInsertKey     = 213;
  sDeleteKey     = 214;
  sHomeKey       = 215;
  sEndKey        = 216;
  sPageUpKey     = 217;
  sPageDownKey   = 218;
  sSpaceKey      = 219;
  sLeftKey       = 220;
  sRightKey      = 221;
  sUpKey         = 222;
  sDownKey       = 223;
  sMinusKey      = 224;
  sPlusKey       = 225;
  sAltMinusKey   = 226;
  sAltEqualKey   = 227;
  sCursorKeys    = 228;

function kn(KeyCode: Word): string;

{ Simplified menu NewItem function
}
function NewItemKn(const Name: TMenuStr; KeyCode: Word; Command: Word;
  AHelpCtx: Word; Next: PMenuItem): PMenuItem;
function NewItemKnHc(const Name: TMenuStr; KeyCode: Word; Command: Word;
  Next: PMenuItem): PMenuItem;

{ Simplified NewStatusKey function
}
function NewStatusKeyKn(const Text: String; KeyCode: Word; Command: Word;
  Next: PStatusItem): PStatusItem;

{ Add accelerator codes and key names to a menu
}
{$ifndef FPK}
procedure AddAccelerators(Menu: PMenu; Accelerators: PAccelerators);
{$endif FPK}

implementation

{$ifndef FPK}
uses Objects, GvTexts, Drivers, Strings;
{$endif FPK}

{$ifdef FPK}
var
  Temp: PChar;
{$endif}

function kn(KeyCode: Word): string;
var
  c: Char;
  Result_: PChar;
  Cur: PChar;

	procedure F(num: integer);
	var
	  s: string[2];
	begin
	  Cur := StrEnd(StrGet(sFunctionKey, Cur, 255));
	  Str(num, s);
	  Cur := StrEnd(StrPCopy(Cur, s));
	end;

	procedure S(Key: Integer);
	begin
	  Cur := StrEnd(StrGet(Key, Cur, 255));
	end;

	procedure Ch(c: Char);
        begin
	  Cur[0] := c;
	  Inc(Cur);
	  Cur[0] := #0;
	end;

	procedure Compose(Modifier: Integer);
	begin
	  Cur := StrEnd(StrGet(Modifier, Cur, 255));
	  Cur := StrEnd(StrGet(sComposeKeys, Cur, 255));
	end;

	procedure Comp(Modifier: Integer; Key: Integer);
	begin
	  Compose(Modifier);
	  Cur := StrEnd(StrGet(Key, Cur, 255));
	end;

begin
{$ifdef FPK}
  asm
    movl __Result, %eax
    movl %eax, _TEMP
  end;
  Result_ := Temp;
{$else}
  asm
     les di, @Result;
     mov Result_.word, di
     mov Result_.2.word, es
  end;
{$endif}
  Cur := Result_ + 1;
  If Lo(KeyCode) = 0 then
  case Hi(KeyCode) of
    $3B..$44:
      F(Hi(KeyCode) - $3A);
    $54..$5D:
      begin
	Compose(sShiftModifier);
	F(Hi(KeyCode) - $53)
      end;
    $5E..$67:
      begin
	Compose(sCtrlModifier);
        F(Hi(KeyCode) - $5D)
      end;
    $68..$71:
      begin
        Compose(sAltModifier);
        F(Hi(KeyCode) - $67)
      end;
  {$ifndef FPK}
    Hi(kbAltEqual):
      S(sAltEqualKey);
    Hi(kbAltMinus):
      S(sAltMinusKey);
    Hi(kbAltSpace):
      Comp(sAltModifier, sSpaceKey);
    Hi(kbCtrlDel):
      Comp(sCtrlModifier, sDeleteKey);
    Hi(kbCtrlEnd):
      Comp(sCtrlModifier, sEndKey);
    Hi(kbCtrlHome):
      Comp(sCtrlModifier, sHomeKey);
    Hi(kbCtrlIns):
      Comp(sCtrlModifier, sInsertKey);
    Hi(kbCtrlLeft):
      Comp(sCtrlModifier, sLeftKey);
    Hi(kbCtrlPgDn):
      Comp(sCtrlModifier, sPageDownKey);
    Hi(kbCtrlPgUp):
      Comp(sCtrlModifier, sPageUpKey);
    Hi(kbCtrlPrtSc):
      Comp(sCtrlModifier, sPrintKey);
    Hi(kbCtrlRight):
      Comp(sCtrlModifier, sRightKey);
    Hi(kbDel):
      S(sDeleteKey);
    Hi(kbDown):
      S(sDownKey);
    Hi(kbEnd):
      S(sEndKey);
    Hi(kbHome):
      S(sHomeKey);
    Hi(kbIns):
      S(sInsertKey);
    Hi(kbLeft):
      S(sLeftKey);
    Hi(kbPgDn):
      S(sPageDownKey);
    Hi(kbPgUp):
      S(sPageUpKey);
    Hi(kbRight):
      S(sRightKey);
    Hi(kbShiftDel):
      Comp(sShiftModifier, sDeleteKey);
    Hi(kbShiftIns):
      Comp(sShiftModifier, sInsertKey);
    Hi(kbShiftTab):
      Comp(sShiftModifier, sTabKey);
    Hi(kbUp):
      S(sUpKey);
  {$endif}
    else begin
      c := GetAltChar(KeyCode);
      If c <> #0
      then begin
	Compose(sAltModifier);
	Ch(c)
      end
    end;
  end else
  case KeyCode of
    kbBack:
      S(sBackspaceKey);
    kbCtrlBack:
      Comp(sCtrlModifier, sBackspaceKey);
    kbCtrlEnter:
      Comp(sCtrlModifier, sEnterKey);
    kbEnter:
      S(sEnterKey);
    kbEsc:
      S(sEscapeKey);
    kbGrayMinus:
      S(sMinusKey);
    kbGrayPlus:
      S(sPlusKey);
    kbTab:
      S(sTabKey);
    else begin
      c := GetCtrlChar(KeyCode);
      If c <> #0
      then begin
	Compose(sCtrlModifier);
	Ch(c)
      end;
    end;
  end;
  Result_[0] := Chr((Cur - Result_) - 1);
end;

function NewItemKn(const Name: TMenuStr; KeyCode: Word; Command: Word;
  AHelpCtx: Word; Next: PMenuItem): PMenuItem;
begin
  NewItemKn := NewItem(Name, kn(KeyCode), KeyCode, Command, AHelpCtx, Next)
end;

function NewItemKnHc(const Name: TMenuStr; KeyCode: Word; Command: Word;
  Next: PMenuItem): PMenuItem;
begin
  NewItemKnHc := NewItem(Name, kn(KeyCode), KeyCode, Command, hc + Command, Next)
end;

function NewStatusKeyKn(const Text: String; KeyCode: Word; Command: Word;
  Next: PStatusItem): PStatusItem;
begin
  NewStatusKeyKn := NewStatusKey('~' + kn(KeyCode) + '~ ' + Text,
    KeyCode, Command, Next)
end;

{$ifndef FPK}
procedure AddAccelerators(Menu: PMenu; Accelerators: PAccelerators);
var
  Item: PMenuItem;
begin
  If Menu <> nil
  then begin
    Item := Menu^.Items;
    while Item <> nil do
      with Item^ do
      begin
	If Command = 0
	then AddAccelerators(SubMenu, Accelerators)
	else begin
	  If Accelerators <> nil
	  then begin
	    if KeyCode = 0
	    then KeyCode := LookUpAccelerator(Accelerators, Command)
	  end;
	  If (KeyCode <> 0) and (Param = nil)
	  then Param := NewStr(kn(KeyCode))
	end;
	Item := Next
      end
  end
end;
{$endif FPK}

end.
