home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
turbopas
/
bonus507.arc
/
TPKEYS.ARC
/
TPKEYS.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1989-01-25
|
44KB
|
1,502 lines
{$S-,I-,V-}
{$M 16384,16384,600000}
{$I TPDEFINE.INC}
{************************************************************}
{* TPKEYS.PAS 5.04 *}
{* Keyboard installation program for Turbo Professional 5.0 *}
{* By TurboPower Software *}
{************************************************************}
program TpKeys;
uses
TpEnhKbd,
TpString,
TpDos,
TpCrt,
{$IFDEF UseMouse}
TpMouse, {Turbo Professional mouse routines}
{$ENDIF}
TpCmd,
TpClone,
TpWindow,
TpMenu,
{the following units are not actually used}
TpEdit,
TpEntry,
TpPick,
TpHelp;
type
StringPointer = ^string;
var
MainMenu : Menu; {pointer to menu system}
Ch : Char; {menu selection character}
Key : MenuKey; {menu choice key}
OrigMode : Word; {video mode when program started}
OrigAttr : Byte; {vide attribute when program started}
LoColor : Byte; {low video color}
TiColor : Byte; {title color}
CfColor : Byte; {conflict color}
ChColor : Byte; {changed key color}
EdColor : Byte; {edit window color}
FrColor : Byte; {border frame color}
StColor : Byte; {status message color}
const
NameLength = 26; {Maximum length for command name}
PriCmdCol = 28; {Where '1: ' appears}
PriMinCol = 31; {Where primary key sequence starts}
PriMaxCol = 45; {Where primary key sequence ends}
SecCmdCol = 46; {Where '2: ' appears}
SecMinCol = 49; {Where secondary key sequence starts}
SecMaxCol = 63; {Where secondary key sequence ends}
TerCmdCol = 64; {Where '3: ' appears}
TerMinCol = 67; {Where tertiary key sequence starts}
TerMaxCol = 80; {Where tertiary key sequence ends}
CmdWid = 14; {Number of columns where the command is displayed}
FirstRow = 4; {First row where keys are installed}
LastRow = 22; {Last row where keys are installed}
StatCol = 2; {Column for status messages}
StatRow = 24; {Row for status messages}
StatWid = 78; {maximum length of status messages}
EditWinLeft = 3; {coordinates for key edit window}
EditWinRight = 78;
EditWinTop = 11;
EditWinBot = 13;
EditCmdWid = 74; {internal width of key edit window}
EditCmdCol = 65; {column for Command/Literal message}
SingBarChar = '─';
DoubBarChar = '═';
EditPrompt : string[72] =
'-delete C-clear R-restore ┘-accept ESC-cancel Scroll Lock-literal';
BrowsePrompt : string[67] =
'--scroll PgUp-PgDn-page ┘-modify R-restore defaults ESC-exit';
type
String80 = string[80];
NameString = string[NameLength];
NameArray = array[1..MaxCommands] of NameString;
MapArray = array[1..MaxCommands] of Byte;
ByteArray = array[0..MaxKeys] of Byte;
var
EditCP : ClonePack; {TPEDIT - clone file}
EntryCP : ClonePack; {TPENTRY - clone file}
HelpCP : ClonePack; {TPHELP - clone file}
MenuCP : ClonePack; {TPMENU - clone file}
PickCP : ClonePack; {TPPICK - clone file}
EditPos : LongInt; {TPEDIT - file pointer}
EntryPos : LongInt; {TPENTRY - file pointer}
HelpPos : LongInt; {TPHELP - file pointer}
MenuPos : LongInt; {TPMENU - file pointer}
PickPos : LongInt; {TPPICK - file pointer}
MenuKeySet2 : array[0..MenuKeyMax] of Byte; {TPMENU - packed keys}
EditUK : UnpackedKeyArray; {TPEDIT - unpacked keys}
EntryUK : UnpackedKeyArray; {TPENTRY - unpacked keys}
HelpUK : UnpackedKeyArray; {TPHELP - unpacked keys}
MenuUK : UnpackedKeyArray; {TPMENU - unpacked keys}
PickUK : UnpackedKeyArray; {TPPICK - unpacked keys}
OUK : UnpackedKeyArray; {Original unpacked key array}
P : UnpackedKeyPtr; {Pointer to current unpacked key array}
N : ^NameArray; {Pointer to current name array}
NNames : Word; {Current number of command names}
M : ^MapArray; {Pointer to current order map array}
NMaps : Word; {Current number of displayed commands}
Modified : Boolean; {True when installation changes may have occurred}
{$IFDEF UseMouse}
const
MapLeftButton : Boolean = True;
{used to translate mouse buttons to keys}
ButtonCodes : array[$E9..$EF] of Word = (
$011B, {all three buttons = ESC}
$011B, {right and center buttons = ESC}
$011B, {left and center buttons = ESC}
$011B, {center button = ESC}
$011B, {both buttons = ESC}
$011B, {right button = ESC}
$1C0D); {left button = Enter}
{$ENDIF}
{.F-}
const
EditFileName : string[6] = 'TPEDIT';
{names of TpEdit commands -- array must start with 1 (RSchar)}
EditNames : array[RSchar..RSuser9] of NameString = (
'', {RSchar}
'Enter control char', {RSctrlChar}
'Accept string', {RSenter}
'Cancel', {RSquit}
'Restore string', {RSrestore}
'Cursor to start of line', {RShome}
'Cursor to end of line', {RSend}
'Cursor left', {RSleft}
'Cursor right', {RSright}
'Cursor left one word', {RSwordLeft}
'Cursor right one word', {RSwordRight}
'Delete previous char', {RSback}
'Delete char at cursor', {RSdel}
'Delete to end of line', {RSdelEol}
'Delete from start of line', {RSdelBol}
'Delete entire line', {RSdelLine}
'Delete word', {RSdelWord}
'Toggle insert mode', {RSins}
'Help', {RShelp}
'User 0', {RSuser0}
'User 1', {RSuser1}
'User 2', {RSuser2}
'User 3', {RSuser3}
'User 4', {RSuser4}
'User 5', {RSuser5}
'User 6', {RSuser6}
'User 7', {RSuser7}
'User 8', {RSuser8}
'User 9' {RSuser9}
);
{Display map for TpEdit commands -- 0 inserts a divider bar}
EditDisplay = 31;
EditMap : array[1..EditDisplay] of Byte = (
RSleft, RSright, RSwordLeft, RSwordRight, RShome, RSend,
0,
RSback, RSdel, RSdelEol, RSdelBol, RSdelLine, RSdelWord, RSins,
0,
RSenter, RSquit, RSctrlChar, RSrestore, RShelp,
0,
RSuser0, RSuser1, RSuser2, RSuser3, RSuser4,
RSuser5, RSuser6, RSuser7, RSuser8, RSuser9);
EntryFileName : string[7] = 'TPENTRY';
EntryNames : array[ESChar..ESmouse] of NameString = (
'', {ESchar}
'Enter control char', {ESctrlChar}
'Restore string', {ESrestore}
'Cursor to start of line', {EShome}
'Cursor to end of line', {ESend}
'Cursor left', {ESleft}
'Cursor right', {ESright}
'Cursor left one word', {ESwordLeft}
'Cursor right one word', {ESwordRight}
'Delete previous char', {ESback}
'Delete char at cursor', {ESdel}
'Delete entire field', {ESdelLine}
'Delete to end of field', {ESdelEol}
'Delete from start of field', {ESdelBol}
'Delete word', {ESdelWord}
'Toggle insert mode', {ESins}
'Help', {EShelp}
'Next subfield', {EStab}
'Previous subfield', {ESbackTab}
'Increment choice', {ESincChoice}
'Decrement choice', {ESdecChoice}
'Next field', {ESnextField}
'Previous field', {ESprevField}
'Next field down', {ESdownField}
'Next field up', {ESupField}
'Next record', {ESnextRec}
'Previous record', {ESprevRec}
'First field', {ESfirstFld}
'Last field', {ESlastFld}
'Previous page', {ESpageUp}
'Next page', {ESpageDown}
'', {ESnested} {shouldn't be assigned!}
'User 0', {ESuser0}
'User 1', {ESuser1}
'User 2', {ESuser2}
'User 3', {ESuser3}
'User 4', {ESuser4}
'User 5', {ESuser5}
'User 6', {ESuser6}
'User 7', {ESuser7}
'User 8', {ESuser8}
'User 9', {ESuser9}
'Accept data', {ESdone}
'Cancel', {ESquit}
'', {ESclickExit} {shouldn't be assigned!}
'Mouse select' {ESmouse}
);
EntryDisplay = 48;
EntryMap : array[1..EntryDisplay] of Byte = (
ESleft, ESright, ESwordLeft, ESwordRight, EShome, ESend, EStab, ESbackTab,
0,
ESback, ESdel, ESdelEol, ESdelBol, ESdelLine, ESdelWord, ESins,
0,
ESnextField, ESprevField, ESdownField, ESupField,
ESnextRec, ESprevRec, ESfirstFld, ESlastFld, ESpageUp, ESpageDown,
0,
ESdone, ESquit, ESmouse, ESctrlChar, ESrestore, EShelp,
0,
ESincChoice, ESdecChoice,
0,
ESuser0, ESuser1, ESuser2, ESuser3, ESuser4,
ESuser5, ESuser6, ESuser7, ESuser8, ESuser9);
HelpFileName : string[6] = 'TPHELP';
HelpNames : array[HKSAlpha..HKSUser3] of NameString = (
'', {HKSAlpha}
'Cursor up', {HKSUp}
'Cursor down', {HKSDown}
'Page up', {HKSPgUp}
'Page down', {HKSPgDn}
'Cursor left', {HKSLeft}
'Cursor right', {HKSRight}
'Exit from help system', {HKSExit}
'Select cross-ref topic', {HKSSelect}
'Previous help topic', {HKSPrev}
'First help page', {HKSHome}
'Last help page', {HKSEnd}
'Display help index', {HKSIndex}
'Mouse select', {HKSProbe}
'User 0', {HKSuser0}
'User 1', {HKSuser1}
'User 2', {HKSuser2}
'User 3' {HKSuser3}
);
HelpDisplay = 19;
HelpMap : array[1..HelpDisplay] of Byte = (
HKSUp, HKSDown, HKSLeft, HKSRight,
HKSHome, HKSEnd, HKSPgUp, HKSPgDn,
0,
HKSSelect, HKSProbe, HKSPrev, HKSIndex, HKSExit,
0,
HKSUser0, HKSUser1, HKSUser2, HKSUser3);
MenuFileName : string[6] = 'TPMENU';
MenuNames : array[MKSAlpha..MKSuser3] of NameString = (
'', {MKSAlpha}
'Cursor up', {MKSUp}
'Cursor down', {MKSDown}
'', {unused}
'', {unused}
'Cursor left', {MKSLeft}
'Cursor right', {MKSRight}
'Exit from menu', {MKSExit}
'Select item', {MKSSelect}
'Help', {MKSHelp}
'First menu item', {MKSHome}
'Last menu item', {MKSEnd}
'Mouse select', {MKSProbe}
'User 0', {MKSuser0}
'User 1', {MKSuser1}
'User 2', {MKSuser2}
'User 3' {MKSuser3}
);
MenuDisplay = 17;
MenuMap : array[1..MenuDisplay] of Byte = (
MKSUp, MKSDown, MKSLeft, MKSRight,
0,
MKSHome, MKSEnd,
0,
MKSSelect, MKSProbe, MKSExit, MKSHelp,
0,
MKSUser0, MKSUser1, MKSUser2, MKSUser3);
PickFileName : string[6] = 'TPPICK';
PickNames : array[PKSAlpha..PKSUser3] of NameString = (
'', {PKSAlpha}
'Cursor up', {PKSUp}
'Cursor down', {PKSDown}
'Page up', {PKSPgUp}
'Page down', {PKSPgDn}
'Cursor left', {PKSLeft}
'Cursor right', {PKSRight}
'Exit from pick list', {PKSExit}
'Select item', {PKSSelect}
'Help', {PKSHelp}
'First menu item', {PKSHome}
'Last menu item', {PKSEnd}
'Mouse select', {PKSProbe}
'User 0', {PKSuser0}
'User 1', {PKSuser1}
'User 2', {PKSuser2}
'User 3' {PKSuser3}
);
PickDisplay = 19;
PickMap : array[1..PickDisplay] of Byte = (
PKSUp, PKSDown, PKSLeft, PKSRight,
0,
PKSHome, PKSEnd, PKSPgUp, PKSPgDn,
0,
PKSSelect, PKSProbe, PKSExit, PKSHelp,
0,
PKSUser0, PKSUser1, PKSUser2, PKSUser3);
{.F+}
{$IFDEF UseMouse}
function ReadKeyWord : Word;
{-Get a key from the keyboard or mouse}
var
I : Word;
begin
I := ReadKeyOrButton;
case Hi(I) of
$E9..$EE :
ReadKeyWord := ButtonCodes[Hi(I)];
$EF :
if MapLeftButton then
ReadKeyWord := ButtonCodes[$EF]
else
ReadKeyWord := $EF00;
else
ReadKeyWord := I
end;
end;
function ReadKey : Char;
{-Special ReadKey routine that accounts for mouse}
const
ScanCode : Char = #0;
var
Key : Word;
begin
if ScanCode <> #0 then begin
{return the scan code}
ReadKey := ScanCode;
ScanCode := #0;
end
else begin
{get the next keystroke}
Key := ReadKeyWord;
{return the low byte}
ReadKey := Char(Lo(Key));
{if it's 0, save the scan code for the next call}
if Lo(Key) = 0 then
ScanCode := Char(Hi(Key));
end;
end;
function KeyPressed : Boolean;
{-Special KeyPressed routine that accounts for mouse}
begin
KeyPressed := TpCrt.KeyPressed or MousePressed;
end;
{$ENDIF}
function ErrorMessage(Status : Word) : string;
{-Return Turbo runtime error messages}
var
S : string;
begin
case Status of
000 : S := '';
002 : S := 'File not found';
003 : S := 'Path not found';
004 : S := 'Too many open files';
005 : S := 'File access denied';
006 : S := 'Invalid file handle';
012 : S := 'Invalid file access code';
015 : S := 'Invalid drive number';
016 : S := 'Cannot remove current directory';
017 : S := 'Cannot rename across drives';
100 : S := 'Disk read error';
101 : S := 'Disk write error';
102 : S := 'File not assigned';
103 : S := 'File not open';
104 : S := 'File not open for input';
105 : S := 'File not open for output';
106 : S := 'Invalid numeric format';
150 : S := 'Disk is write-protected';
151 : S := 'Unknown unit';
152 : S := 'Drive not ready';
153 : S := 'Unknown command';
154 : S := 'CRC error in data';
155 : S := 'Bad drive request structure length';
156 : S := 'Disk seek error';
157 : S := 'Unknown media type';
158 : S := 'Sector not found';
159 : S := 'Printer out of paper';
160 : S := 'Device write fault';
161 : S := 'Device read fault';
162 : S := 'Hardware failure';
200 : S := 'Division by zero';
201 : S := 'Range check error';
202 : S := 'Stack overflow';
203 : S := 'Insufficient memory';
204 : S := 'Invalid pointer operation';
205 : S := 'Floating point overflow';
206 : S := 'Floating point underflow';
207 : S := 'Invalid floating point operation';
else
S := 'Turbo runtime error '+Long2Str(Status);
end;
ErrorMessage := S;
end;
procedure Error(Msg : string);
{-Report error and halt}
begin
{$IFDEF UseMouse}
if MouseInstalled then
HideMouse;
{$ENDIF}
Window(1, 1, ScreenWidth, ScreenHeight);
ClrScr;
WriteLn(Msg);
Halt(1);
end;
procedure ClrStatLine;
{-Clear status line}
begin
FastWrite(CharStr(' ', StatWid), StatRow, StatCol, StColor);
end;
procedure InitMenu(var M : Menu);
{-Initialize menu system}
const
Color1 : MenuColorArray = ($1F, $5F, $1B, $5F, $1B, $00, $00, $00);
Mono1 : MenuColorArray = ($0F, $70, $07, $70, $0F, $00, $00, $00);
Frame1 : FrameArray = '╒╘╕╛═│';
begin
{we'll do our own color mapping}
MapColors := False;
if (WhichHerc <> HercInColor) and (CurrentMode <> 3) then
Color1 := Mono1;
M := NewMenu([], nil);
SubMenu(1, 1, 0, Horizontal, Frame1, Color1,
' TPKEYS - Turbo Professional 5.0 Keyboard Installation ');
MenuWidth(80);
MenuItem(' TPEDIT ', 4, 0, 1, '');
MenuItem(' TPENTRY ', 18, 0, 2, '');
MenuItem(' TPHELP ', 34, 0, 3, '');
MenuItem(' TPMENU ', 50, 0, 4, '');
MenuItem(' TPPICK ', 65, 0, 5, '');
PopSublevel;
ResetMenu(M);
end;
procedure Init;
{-Initialize data structures}
begin
{Assure 80 column}
CheckBreak := False;
OrigMode := LastMode;
OrigAttr := TextAttr;
{assure 80 column text mode}
case CurrentMode of
0..1 : TextMode(CurrentMode+2);
2..3, 7 : {ok} ;
else TextMode(3);
end;
{assure 25-line mode}
if Hi(LastMode) <> 0 then
SelectFont8x8(False);
{Set up colors}
if (CurrentMode = 3) or (WhichHerc = HercInColor) then begin
LoColor := $0F;
TiColor := $0B;
ChColor := $0C;
EdColor := $1F;
CfColor := $4F;
FrColor := $1F;
StColor := $1B;
end
else begin
LoColor := $07;
TiColor := $0F;
ChColor := $0F;
EdColor := $70;
CfColor := $70;
FrColor := $0F;
StColor := $07;
end;
TextAttr := LoColor;
ClrScr;
Modified := False;
FrameWindow(StatCol-1, StatRow-1, StatCol+StatWid, StatRow+1,
FrColor, FrColor, '');
ClrStatLine;
{$IFDEF UseMouse}
if MouseInstalled then begin
{use a diamond for our mouse cursor}
if (CurrentMode = 3) or (WhichHerc = HercInColor) then
SoftMouseCursor($0000, $4F04)
else
SoftMouseCursor($0000, $0F04);
ShowMouse;
{enable mouse support}
EnableMenuMouse;
end;
{$ENDIF}
end;
procedure StatMessage(Msg : string);
{-Write a message to status line}
var
Col : Byte;
begin
{$IFDEF UseMouse}
if MouseInstalled then
HideMouse;
{$ENDIF}
ClrStatLine;
if Length(Msg) > StatWid then
Msg[0] := Char(StatWid);
Col := (80-Length(Msg)) shr 1;
FastWrite(Msg, 24, StatCol+Col, StColor);
GoToXYAbs(StatCol+Col+Length(Msg), 24);
{$IFDEF UseMouse}
if MouseInstalled then
ShowMouse;
{$ENDIF}
end;
function PromptYesNo(Msg : string) : Boolean;
{-Return true if yes answer}
var
Ch : Char;
begin
StatMessage(Msg);
repeat
Ch := Upcase(ReadKey);
until (Ch = 'Y') or (Ch = 'N');
PromptYesNo := (Ch = 'Y');
end;
procedure PromptEsc(Msg : string);
{-Prompt for <Esc> to be pressed}
var
Ch : Char;
begin
StatMessage(Msg+'. Press <Esc>');
repeat
Ch := ReadKey;
until Ch = #27;
end;
procedure PressEsc(Msg : string);
{-Write a message and wait for <Esc>}
var
Ch : Char;
begin
StatMessage(Msg+'. Press <Esc> to correct...');
repeat
Ch := ReadKey;
until Ch = #27;
end;
procedure CheckCloneError(FPos : LongInt; Msg : string);
{-Check the opening of the installation program}
begin
if CloneError <> 0 then
if FPos = 0 then
Error(Msg)
else
Error(ErrorMessage(CloneError));
end;
procedure InitClonePrim(FName : String80; var CP : ClonePack;
var ID : string; var Pos : LongInt);
{-Primitive routine to initialize a unit for cloning}
begin
{open file for cloning}
FName := DefaultExtension(FName, 'TPU');
if not ExistOnPath(FName, FName) then
CloneError := 2
else
Pos := InitForCloning(FName, CP, ID, Length(ID)+1);
{check for errors}
if CloneError = 2 then
Error(FName+' not found')
else
CheckCloneError(Pos, FName+' ID string not found');
{skip over ID string}
Inc(Pos, Length(ID)+1);
end;
procedure Open;
{-Open the TPU files for installation}
begin
{don't change time *or* date stamps on TPU files--it might force
unnecessary recompilation of other units}
DateUpdate := UpdateNone;
WriteLn('Finding identification strings...');
InitClonePrim(EditFileName, EditCP, EditKeyID, EditPos);
InitClonePrim(EntryFileName, EntryCP, EntryKeyID, EntryPos);
InitClonePrim(MenuFileName, MenuCP, MenuKeyID, MenuPos);
InitClonePrim(HelpFileName, HelpCP, HelpKeyID, HelpPos);
InitClonePrim(PickFileName, PickCP, PickKeyID, PickPos);
end;
procedure LoadPrim(var CP : ClonePack; FPos : LongInt;
var Defaults; DefSize : Word);
{-Primitive routine to load defaults for a unit}
begin
{load defaults}
LoadDefaults(CP, FPos, Defaults, DefSize);
{check for errors}
CheckCloneError(1, '');
end;
procedure Load;
{-Load the default settings}
begin
LoadPrim(EditCP, EditPos, EditKeySet, SizeOf(EditKeySet));
LoadPrim(EntryCP, EntryPos, EntryKeySet, SizeOf(EntryKeySet));
LoadPrim(MenuCP, MenuPos, MenuKeySet2, SizeOf(MenuKeySet2));
LoadPrim(HelpCP, HelpPos, HelpKeySet, SizeOf(HelpKeySet));
LoadPrim(PickCP, PickPos, PickKeySet, SizeOf(PickKeySet));
end;
procedure UnpackPrim(var PK, UK);
{-Primitive routine to unpack the commands for a unit}
var
I : Word;
begin
I := UnpackKeys(PK, UK, MaxCommands, 3);
end;
procedure Unpack;
{-Unpack all of the key arrays}
begin
UnpackPrim(EditKeySet, EditUK);
UnpackPrim(EntryKeySet, EntryUK);
UnpackPrim(MenuKeySet2, MenuUK);
UnpackPrim(HelpKeySet, HelpUK);
UnpackPrim(PickKeySet, PickUK);
end;
procedure PackPrim(var PK, UK; MaxBytes : Word);
{-Primitive routine to pack the commands for a unit}
var
I : Word;
begin
I := PackKeys(PK, MaxCommands, MaxBytes, UK);
end;
procedure Pack;
{-Pack all of the key arrays}
begin
PackPrim(EditKeySet, EditUK, EditKeyMax);
PackPrim(EntryKeySet, EntryUK, EntryKeyMax);
PackPrim(MenuKeySet2, MenuUK, MenuKeyMax);
PackPrim(HelpKeySet, HelpUK, HelpKeyMax);
PackPrim(PickKeySet, PickUK, PickKeyMax);
end;
procedure StorePrim(var CP : ClonePack; FPos : LongInt;
var Defaults; DefSize : Word);
{-Primitive routine to store the packed commands for a unit}
begin
{store modified defaults}
StoreDefaults(CP, FPos, Defaults, DefSize);
{check for errors}
CheckCloneError(1, '');
{close clone file}
CloseForCloning(CP);
{check for errors}
CheckCloneError(1, '');
end;
function CheckModifiedFlags(var UnpackedKeys; NumCmds : Word) : Boolean;
{-Check to see if any of the Modified flags are set in UnpackedKeys}
var
I : Word;
UK : UnpackedKeyArray absolute UnpackedKeys;
begin
{assume success}
CheckModifiedFlags := False;
{turn off all Conflict flags}
for I := 1 to NumCmds do
if UK[I].Modified then begin
CheckModifiedFlags := True;
Exit;
end;
end;
procedure Store;
{-Store the new default settings}
begin
StatMessage('Storing new defaults....');
if CheckModifiedFlags(EditUK, MaxCommands) then
StorePrim(EditCP, EditPos, EditKeySet, SizeOf(EditKeySet));
if CheckModifiedFlags(EntryUK, MaxCommands) then
StorePrim(EntryCP, EntryPos, EntryKeySet, SizeOf(EntryKeySet));
if CheckModifiedFlags(MenuUK, MaxCommands) then
StorePrim(MenuCP, MenuPos, MenuKeySet2, SizeOf(MenuKeySet2));
if CheckModifiedFlags(HelpUK, MaxCommands) then
StorePrim(HelpCP, HelpPos, HelpKeySet, SizeOf(HelpKeySet));
if CheckModifiedFlags(PickUK, MaxCommands) then
StorePrim(PickCP, PickPos, PickKeySet, SizeOf(PickKeySet));
end;
{$L PREF.OBJ}
{$F+}
function EscapeSequence(B : Byte) : StringPointer; external;
{-Return a pointer to a text string representing extended scan code B}
{$F-}
procedure KeyToString(Key : Word; var S : string; SingleKey : Boolean);
{-Returns a string (S) representing a Key. Special is set to False if
a simple character is being returned.}
begin
if (Lo(Key) = 0) or (Lo(Key) = $E0) then
S := '<'+EscapeSequence(Hi(Key))^+'>'
else begin
if (Lo(Key) <= 31) and not SingleKey then
S := '<^'+Chr(Lo(Key)+64)+'>'
else
case Lo(Key) of
008 : S := '<BkSp>'; {Backspace}
009 : S := '<Tab>'; {Tab}
010 : S := '<^Enter>'; {^Enter}
013 : S := '<Enter>'; {Enter}
027 : S := '<Esc>'; {Escape}
1..31 : {Control characters}
S := '<^'+Chr(Lo(Key)+64)+'>';
032 : S := '<Space>';
127 : S := '<^BkSp>'; {ASCII DEL}
255 : S := '<#255>'; {#255}
else
{Normal character}
S := '<'+Char(Lo(Key))+'>';
end;
end;
end;
procedure DrawKeys(Keys : KeyString; Row, Col : Integer; Attr : Byte;
MoveCursor : Boolean; CmdWidth : Byte);
{-Draw the keystrokes in specified attribute}
var
KLen : Byte absolute Keys;
I : Integer;
KW : Word;
KeyStr : string[20];
CurCol : Integer;
Special : Boolean;
S : String80;
SLen : Byte absolute S;
begin
I := 1;
SLen := 0;
while I <= KLen do begin
if Keys[I] = #0 then begin
if I = KLen then
KW := 0
else begin
Inc(I);
KW := Swap(Byte(Keys[I]));
end;
end
else
KW := Byte(Keys[I]);
KeyToString(KW, KeyStr, KLen = 1);
S := S+KeyStr;
Inc(I);
end;
if SLen >= CmdWidth then begin
CurCol := CmdWidth;
SLen := CmdWidth;
end
else begin
CurCol := SLen;
S := Pad(S, CmdWidth);
end;
FastWrite(S, Row, Col, Attr);
if MoveCursor then
GoToXY(Col+CurCol, Row);
end;
procedure DrawCmd(Cmd, Row : Integer);
{-Write a single command, Cmd, at screen Row}
var
Attr : Byte;
St : String80;
Index : Word;
begin
{$IFDEF UseMouse}
if MouseInstalled then
HideMouse;
{$ENDIF}
if Cmd = 0 then begin
{Separator bar}
St := CharStr(SingBarChar, 80);
FastWrite(St, Row, 1, TiColor);
end
else begin
Index := ((Cmd-1)*3)+1;
{Name of command}
St := Pad(N^[Cmd], PriCmdCol-1);
St := St+'1:';
FastWrite(Pad(St, 80), Row, 1, TiColor);
{Primary keys}
with P^[Index] do begin
if Length(Keys) = 0 then
Attr := LoColor
else if Conflict then
Attr := CfColor
else if Modified then
Attr := ChColor
else
Attr := LoColor;
DrawKeys(Keys, Row, PriMinCol, Attr, False, CmdWid);
end;
{Secondary keys}
FastWrite('2:', Row, SecCmdCol, TiColor);
with P^[Index+1] do begin
if Length(Keys) = 0 then
Attr := LoColor
else if Conflict then
Attr := CfColor
else if Modified then
Attr := ChColor
else
Attr := LoColor;
DrawKeys(Keys, Row, SecMinCol, Attr, False, CmdWid);
end;
{Tertiary keys}
FastWrite('3:', Row, TerCmdCol, TiColor);
with P^[Index+2] do begin
if Length(Keys) = 0 then
Attr := LoColor
else if Conflict then
Attr := CfColor
else if Modified then
Attr := ChColor
else
Attr := LoColor;
DrawKeys(Keys, Row, TerMinCol, Attr, False, CmdWid);
end;
end;
{$IFDEF UseMouse}
if MouseInstalled then
ShowMouse;
{$ENDIF}
end;
procedure EditCmd(Cmd : Word; var Key : KeyRec);
{-Edit one keystroke sequence}
const
SMask = $10; {Scroll lock bit mask}
ComStr : string[9] = ' Command ';
LitStr : string[9] = ' Literal ';
var
KFlag : Byte absolute $0040 : $0017;
SLock : Byte;
LLock : Byte;
KW : Word;
K : KeyString;
KLen : Byte absolute K;
B : KeyString;
Done : Boolean;
Attr : Byte;
function AddKey(B : Byte) : Char;
{-Map alpha characters to control key equivalents}
begin
Char(B) := System.Upcase(Char(B));
case Char(B) of
'A'..'Z' :
AddKey := Char(B-64);
else
AddKey := Char(B);
end;
end;
begin
StatMessage(EditPrompt);
{$IFDEF UseMouse}
if MouseInstalled then
HideMouse;
{$ENDIF}
FrameWindow(EditWinLeft, EditWinTop, EditWinRight, EditWinBot,
EdColor, EdColor, ' '+N^[Cmd]+' ');
LLock := $FF;
K := Key.Keys;
B := K;
Done := False;
repeat
{$IFDEF UseMouse}
if MouseInstalled then
HideMouse;
{$ENDIF}
DrawKeys(K, EditWinTop+1, EditWinLeft+1, EdColor, True, EditCmdWid);
{$IFDEF UseMouse}
if MouseInstalled then
ShowMouse;
{$ENDIF}
repeat
SLock := KFlag and SMask;
if SLock <> LLock then begin
{$IFDEF UseMouse}
if MouseInstalled then
HideMouse;
{$ENDIF}
if SLock = 0 then
FastWrite(ComStr, EditWinBot, EditCmdCol, EdColor)
else
FastWrite(LitStr, EditWinBot, EditCmdCol, EdColor);
{$IFDEF UseMouse}
if MouseInstalled then
ShowMouse;
{$ENDIF}
LLock := SLock;
end;
until KeyPressed;
{$IFDEF UseMouse}
KW := ReadKeyOrButton;
{$ELSE}
KW := ReadKeyWord;
{$ENDIF}
if SLock <> 0 then begin
{Literal mode}
if Lo(KW) = 0 then begin
if KLen+1 < KeyLength then
K := K+#0+Char(Hi(KW));
end
else
K := K+AddKey(KW);
end
{Command mode}
else begin
{$IFDEF UseMouse}
{remap mouse commands}
case Hi(KW) of
$ED : {ClickBoth - toggle scroll lock}
KFlag := KFlag xor SMask;
$E9..$EF : {remap other mouse buttons}
KW := ButtonCodes[Hi(KW)];
end;
{$ENDIF}
if (KW <> $ED00) then
case Lo(KW) of
00 : {Extended key}
if KLen+1 < KeyLength then
K := K+#0+Char(Hi(KW));
08 : {Backspace}
if KLen > 0 then begin
Dec(KLen);
if (KLen > 0) and (K[KLen] = #0) then
Dec(KLen);
end;
13 : {Enter}
Done := True;
27 : {Esc}
begin
K := B;
Done := True;
end;
67, 99 : {C - clear}
KLen := 0;
82, 114 : {R - restore}
K := B;
65..90, 97..122 : {alpha keys-map to control chars}
K := K+AddKey(KW);
else
K := K+Char(KW);
end;
end;
until Done;
{restore previous prompt}
StatMessage(BrowsePrompt);
with Key do begin
Keys := K;
Modified := (K <> B);
if Modified or (KLen = 0) then
Conflict := False;
end;
end;
procedure DrawPage(FirstCmd : Integer);
{-Write a full page of commands, starting at FirstC}
var
Row : Integer;
Cmd : Integer;
begin
Row := FirstRow;
Cmd := FirstCmd;
{$IFDEF UseMouse}
if MouseInstalled then
HideMouse;
{$ENDIF}
while (Row <= LastRow) and (Cmd <= NMaps) do begin
DrawCmd(M^[Cmd], Row);
Inc(Row);
Inc(Cmd);
end;
{$IFDEF UseMouse}
if MouseInstalled then
ShowMouse;
{$ENDIF}
end;
procedure EditKeys(Msg : String80; var TopCmd, CurCmd, ColNum : Integer);
{-Edit the keys in P^}
var
MapCmd : Integer;
MapIndex : Integer;
OldTopCmd : Integer;
Row : Integer;
Col : Integer;
R : Integer;
KW : Word;
K : KeyRec;
{$IFDEF UseMouse}
MRow, MCol : Byte;
NewRow, NewColNum : Byte;
{$ENDIF}
begin
{$IFDEF UseMouse}
if MouseInstalled then
HideMouse;
{$ENDIF}
Window(1, FirstRow, 80, LastRow);
{$IFDEF UseMouse}
MouseWindow(1, FirstRow, 80, LastRow);
{$ENDIF}
ClrScr;
Window(1, 1, 80, LastRow);
StatMessage(BrowsePrompt);
{$IFDEF UseMouse}
if MouseInstalled then
ShowMouse;
{$ENDIF}
{Initialize pick state}
DrawPage(TopCmd);
Row := FirstRow+(CurCmd-TopCmd);
repeat
{Perform display mapping}
MapCmd := M^[CurCmd];
if MapCmd <> 0 then begin
MapIndex := (MapCmd-1)*3+1+ColNum;
K := P^[MapIndex];
end;
case ColNum of
0 : Col := PriMinCol;
1 : Col := SecMinCol;
2 : Col := TerMinCol;
end;
GoToXY(Col, Row);
{$IFDEF UseMouse}
MapLeftButton := False;
{$ENDIF}
{Get a command}
KW := ReadKeyWord;
{$IFDEF UseMouse}
MapLeftButton := True;
{$ENDIF}
case KW of
$1C0D : {Enter}
if MapCmd <> 0 then begin
EditCmd(MapCmd, K);
P^[MapIndex] := K;
DrawPage(TopCmd);
end;
$4800 : {Up arrow}
if CurCmd > 1 then begin
Dec(CurCmd);
if Row = FirstRow then begin
TopCmd := CurCmd;
{$IFDEF UseMouse}
if MouseInstalled then
HideMouse;
{$ENDIF}
InsLine;
DrawCmd(M^[CurCmd], Row);
{$IFDEF UseMouse}
if MouseInstalled then
ShowMouse;
{$ENDIF}
end
else
Dec(Row);
end;
$5000 : {Down arrow}
if CurCmd < NMaps then begin
Inc(CurCmd);
if Row = LastRow then begin
Inc(TopCmd);
GoToXY(1, FirstRow);
{$IFDEF UseMouse}
if MouseInstalled then
HideMouse;
{$ENDIF}
DelLine;
DrawCmd(M^[CurCmd], LastRow);
{$IFDEF UseMouse}
if MouseInstalled then
ShowMouse;
{$ENDIF}
end
else
Inc(Row);
end;
$4B00 : {Left Arrow}
if ColNum > 0 then
Dec(ColNum);
$4D00 : {Right Arrow}
if ColNum < 2 then
Inc(ColNum);
$4900 : {PgUp}
begin
OldTopCmd := TopCmd;
R := FirstRow;
while (CurCmd > 1) and (R < LastRow) do begin
Dec(CurCmd);
if Row = FirstRow then
TopCmd := CurCmd
else
Dec(Row);
Inc(R);
end;
if OldTopCmd <> TopCmd then
DrawPage(TopCmd);
end;
$5100 : {PgDn}
begin
OldTopCmd := TopCmd;
R := FirstRow;
while (CurCmd < NMaps) and (R < LastRow) do begin
Inc(CurCmd);
if Row = LastRow then
Inc(TopCmd)
else
Inc(Row);
Inc(R);
end;
if TopCmd <> OldTopCmd then
DrawPage(TopCmd);
end;
$4700 : {Home}
if CurCmd > 1 then begin
CurCmd := 1;
TopCmd := 1;
Row := FirstRow;
ColNum := 0;
DrawPage(TopCmd);
end;
$4F00 : {End}
if CurCmd < NMaps then begin
if LastRow-FirstRow+1 > NMaps then
Row := FirstRow+NMaps-1
else
Row := LastRow;
CurCmd := NMaps;
TopCmd := NMaps-(Row-FirstRow);
ColNum := 2;
DrawPage(TopCmd);
end;
$1372, $1352 : {r, R}
begin
P^ := OUK;
DrawPage(TopCmd);
end;
{$IFDEF UseMouse}
Integer($EF00) : {left mouse button}
if MouseInstalled then begin
MRow := MouseKeyWordY;
MCol := MouseKeyWordX+MouseXLo;
if MRow <= NMaps then begin
{find the new row and column}
NewRow := MRow+MouseYLo;
if (MCol <= PriMaxCol) then
NewColNum := 0
else if (MCol <= SecMaxCol) then
NewColNum := 1
else
NewColNum := 2;
if (Row = NewRow) and (ColNum = NewColNum) then begin
{cursor already in right place--same as <Enter>}
if MapCmd <> 0 then begin
EditCmd(MapCmd, K);
P^[MapIndex] := K;
DrawPage(TopCmd);
end;
end
else begin
{move to new row/column}
Row := NewRow;
ColNum := NewColNum;
CurCmd := TopCmd+Pred(MRow);
end;
end;
end;
{$ENDIF}
$011B : {Esc}
Exit;
end;
until False;
end;
procedure InstallKeys(Msg : String80;
var UK : UnpackedKeyArray;
var Names; NumNames : Word;
var Map; NumMaps : Word;
MaxBytes : Word);
{-Install specified keylist}
var
ChangesMade : Boolean;
I, J, ColNum : Integer;
CurCmd, TopCmd : Integer;
Code : Byte;
begin
{Put parameters into globals for easier access}
P := @UK;
N := @Names;
NNames := NumNames;
M := @Map;
NMaps := NumMaps;
{start with first command}
CurCmd := 1;
TopCmd := 1;
ColNum := 0;
{Save backup copy of keys}
OUK := UK;
repeat
{Random access editing}
EditKeys(Msg, TopCmd, CurCmd, ColNum);
{$IFDEF UseMouse}
FullMouseWindow;
{$ENDIF}
ChangesMade := CheckModifiedFlags(UK, MaxCommands);
if ChangesMade then
StatMessage('Checking for conflicts...');
if ChangesMade and ConflictsFound(UK, MaxCommands) then begin
{display error message}
PressEsc('Conflicts found');
{find first conflict}
I := 1;
while not UK[I].Conflict do
Inc(I);
Code := UK[I].CommandCode;
CurCmd := 1;
while M^[CurCmd] <> Code do
Inc(CurCmd);
{calculate new TopCmd based on CurCmd}
J := LastRow-FirstRow;
if (CurCmd < TopCmd) or (CurCmd > TopCmd+J) then begin
TopCmd := CurCmd;
if (TopCmd+J > NumMaps) then
TopCmd := NumMaps-J;
if TopCmd < 1 then
TopCmd := 1;
end;
{calculate new ColNum}
ColNum := Pred(I) mod 3;
end
else begin
{calculate size of packed key array}
if ChangesMade and (SizeKeys(UK, MaxCommands) > MaxBytes) then
{Keys too big to fit}
PressEsc('Keys won''t fit in installation area')
else begin
Modified := Modified or ChangesMade;
{$IFDEF UseMouse}
if MouseInstalled then
HideMouse;
{$ENDIF}
Window(1, FirstRow, 80, LastRow);
ClrScr;
Window(1, 1, 80, 25);
ClrStatLine;
{$IFDEF UseMouse}
if MouseInstalled then
ShowMouse;
{$ENDIF}
Exit;
end;
end;
until False;
end;
procedure Stop(Installed : Boolean);
{-Clean up at end}
begin
{$IFDEF UseMouse}
if MouseInstalled then
HideMouse;
{$ENDIF}
if LastMode <> OrigMode then begin
TextMode(OrigMode);
TextAttr := OrigAttr;
end
else begin
TextAttr := OrigAttr;
ClrScr;
end;
if Installed then
WriteLn('Changes saved')
else
WriteLn('Files not changed');
Halt;
end;
procedure SaveAndExit;
{-If modified, prompt to install changes}
begin
if Modified and PromptYesNo('Install changes permanently? (Y/N) ') then begin
{pack the key arrays}
Pack;
{store the packed key arrays}
Store;
{done}
Stop(True);
end
else
{done}
Stop(False);
end;
begin
{open TPU files and find installation areas}
Open;
{load the installation areas}
Load;
{unpack the keystroke arrays}
Unpack;
{set up display, colors, etc}
Init;
{Initialize the main menu}
InitMenu(MainMenu);
repeat
{get menu choice}
StatMessage('Select unit to install, or press <Esc> to quit');
Key := MenuChoice(MainMenu, Ch);
if MenuCmdNum = MKSSelect then begin
case Key of
1 : {TPEDIT}
InstallKeys(EditFileName, EditUK, EditNames, RSuser9-2,
EditMap, EditDisplay, EditKeyMax);
2 : {TPENTRY}
InstallKeys(EntryFileName, EntryUK, EntryNames, ESmouse-2,
EntryMap, EntryDisplay, EntryKeyMax);
3 : {TPHELP}
InstallKeys(HelpFileName, HelpUK, HelpNames, HKSUser3-2,
HelpMap, HelpDisplay, HelpKeyMax);
4 : {TPMENU}
InstallKeys(MenuFileName, MenuUK, MenuNames, MKSuser3-2,
MenuMap, MenuDisplay, MenuKeyMax);
5 : {TPPICK}
InstallKeys(PickFileName, PickUK, PickNames, PKSUser3-2,
PickMap, PickDisplay, PickKeyMax);
end;
end;
until MenuCmdNum = MKSExit;
{clean up}
SaveAndExit;
end.