unit KeyTable; {$I-,V-,X+} interface uses Dos, Drivers, Views, Editors; const N = 33; evInvalidKey = 1024; { entspricht /$2^{10}$/ } edNoKeyTab = 11; kbBlank = $3920; function ReadKeyTable: boolean; function EditKeyTable: boolean; procedure ShowKeyTable; procedure GetComm (var Pos: Word; var E: TEvent); implementation var T: array [0..199] of record k1,k2,cm: word end; top: integer; ShiftState: byte absolute $40:$17; const Commands: array [0..N-1] of record s: string [12]; v: word end= ((S:'Cut'; v:Cmcut), (s:'Copy'; v:cmcopy), (s:'Paste'; v:cmPaste), (s:'Undo'; v:cmUndo), (s:'Clear'; v:cmClear), (s:'Save'; v:cmSave), (s:'SaveAs'; v:cmSaveAs), (s:'Find'; v:cmFind), (s:'Replace'; v:cmReplace), (s:'SearchAgain'; v:cmSearchAgain), (s:'CharLeft'; v:cmCharLeft), (s:'CharRight'; v:cmCharRight), (s:'WordLeft'; v:cmWordLeft), (s:'WordRight'; v:cmWordRight), (s:'LineStart'; V:cmLineStart), (s:'LineEnd'; v:cmLineEnd), (s:'LineUp'; v:cmLineup), (s:'LineDown'; v:cmLineDown), (s:'PageUp'; v:cmPageUp), (s:'PageDown'; V:cmPageDown), (s:'TextStart'; v:cmTextStart), (s:'TextEnd'; v:cmTextEnd), (s:'NewLine'; v:cmNewLine), (s:'BackSpace'; v:cmBackSpace), (s:'DelChar'; V:cmDelChar), (s:'DelWord'; v:cmDelWord), (s:'DelStart'; v:cmDelStart), (s:'DelEnd'; v:cmDelEnd), (s:'DelLine'; V:cmDelLine), (s:'InsMode'; v:cmInsMode), (s:'StartSelect'; v:cmStartSelect), (s:'HideSelect'; v:cmHideSelect), (s:'IndentMode'; v:CmIndentMode)); KVal: array [$47..$53] of word= (1,2,3,4,5,0,6,7,8,9,10,11,12); KName: array [0..13] of String[6]= ('???','Home','UP','Pgup','Minus', 'Left','Right','Plus','End', 'Down','Pgdn','Ins','Del', 'PrtSrc'); MName: array [0..3] of String [5]= ('','Shift','Ctrl','Alt'); SName: array [$72..$77] of word= (13,5,6,8,10,1); type Str2=String[2]; function Num(b: byte): Str2; begin if b=0 then Num:='10' else Num:=Chr(b+$30); end; function Conv(key: word): String; var cc: char; scan,cval: byte; begin scan:=Hi(key); cval:=Lo(key); case scan of $00: Conv:=''; $01: Conv:='ESC'; $04..$07: Conv:=MName[scan mod 2 xor 1+1]+' '+KName[scan div 2+9]; $0E: if cval=8 then Conv:='Bksp' else Conv:='Ctrl Bksp'; $0F: if cval=9 then Conv:='Tab' else Conv:='Shift Tab'; $1C: if cval=13 then Conv:='Cr' else Conv:='Ctrl Cr'; $10..$32: begin cc:=GetAltChar(scan*256); case cval of 0: Conv:='Alt '+cc; 1..$1B: Conv:='Ctrl '+Cc; $41..$5B, $61..$7B: Conv:=cc; end; end; $39: Conv:=''; $3B..$44: Conv:='F'+Num(scan-$3A); $47..$53: Conv:=KName[KVal[scan]]; $54..$71: Conv:=MName[(scan-$49) div 10]+' '+'F'+Num((scan-$49) Mod 10); $72..$77: Conv:='Ctrl '+KName[SName[scan]]; $84: Conv:='Ctrl Pgup'; else Conv:='???' end; end; function find(key: word): integer; var i,j,m: integer; found: boolean; begin i:=-1; j:=top; found:=false; while (i=key then j:=m end; while (j>0) and (T[j-1].k1=key) do Dec(j); find:=j end; function insert(k1,k2,cm:word): integer; var i: integer; begin insert:=-1; if k1=0 then Exit; insert:=-2; if (k1=kbEsc) and (k2=kbEsc) then Exit; insert:=0; i:=find (k1); if (T[i].k1=k1) and (k2=0) or (T[i].k2=0) then Exit; while (T[i].k1=k1) and (T[i].k2evNothing; if (ShiftState and 3 <> 0) and (E.ScanCode in [$47..$51]) then E.CharCode:=#0; Write(Conv(E.KeyCode)); if E.KeyCode=kbBlank then ReadKbd:=0 else ReadKbd:=E.KeyCode; end; function EditKeyTable; var state,k: integer; f: File; begin top:=0; T[0].k1:=$FFFF; T[0].k2:=$FFFF; for k:=0 to N-1 do begin repeat write(Commands[k].s,': '); state:=insert(ReadKbd,ReadKbd,k); writeln; if state=0 then writeln('Key(s) already defined'); until (state<0); if state=-2 then begin EditKeyTable:=ReadKeyTable; Exit; end; end; EditKeyTable:=True; Assign(f,'edit.cfg'); Rewrite(f,1); blockwrite(f,top,2); blockwrite(f,T,top*sizeof(T[0])); close(f) end; function ReadKeyTable; var f: file; Result: word; begin top:=0; ReadKeyTable:=False; assign(f,'edit.cfg'); reset(f,1); if IOResult<>0 then begin EditorDialog(edNoKeyTab,NiL); Exit end; blockread(f,top,2,Result); if Result<>2 then begin EditorDialog(edNoKeyTab,Nil); Close(f); Exit; end; blockread(f,T,sizeof(T[0])*top); cloSe(f); ReadKeyTable:=True; T[top].k1:=$FFFF; T[top].k2:=$FFFF end; procedure GetComm; begin if (ShiftState and 3<>0) and (E.ScanCode in [$47..$51]) then E.CharCode:=#0; if Pos=0 then begin Pos:=find(E.KeyCode); if T[Pos].k1<>E.KeyCode then Pos:=0 else if T[Pos].k2=0 then begin E.Command:=Commands[T[pos].cm].v; E.What:=evCommand; Pos:=0; end else E.What:=evNothing; end else begin while (T[Pos+1].k1=T[Pos].k1) and (T[Pos+1].k2<=E.KeyCode) do Inc(Pos); if T[POS].k2=E.KeyCode then begin E.What:=evCommand; E.Command:=Commands[T[pos].cm].v; end else E.What:=evInvalidKey; Pos:=0; end; end; procedure ShowKeyTable; var k: integer; f: text; begin Assign(f,'out.$$$'); Rewrite(f); for k:=0 to top-1 do writeln(f,Commands[T[k].cm].s,' : ',Conv(T[k].k1),Conv(T[k].k2)); Close(f) end; end.