home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 25
/
CD_ASCQ_25_1095.iso
/
dos
/
prg
/
tjgold
/
install.002
/
GTTTNEST.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1995-07-12
|
32KB
|
967 lines
{--------------------------------------------------------------------------}
{ Product: TechnoJock's Turbo Toolkit }
{ Version: GOLD }
{ Build: 1.01 }
{ }
{ Copyright 1986-1995 TechnoJock Software, Inc. }
{ All Rights Reserved }
{ Restricted by License }
{--------------------------------------------------------------------------}
{**********************************}
{** Unit: GTTTNEST **}
{**********************************}
{$S-,R-,V-}
{$IFNDEF DEBUG}
{$D-}
{$ENDIF}
Unit GTTTNEST;
{$I GOLDFLAG.INC}
INTERFACE
Uses CRT, GoldAttr, GoldFast, DOS, GoldWin, GoldKey, GoldStr, GoldHard;
const
MaxLevels = 10; {maximum number of nested menus - alter if necessary}
MenuStrLength = 40; {maximum length of a menu topic - alter if necessary}
DontClear = 0; {signal to return to same position in menu}
RefreshTopic = 1; {signal to rewrite highlighted topic}
RefreshMenu = 2; {signal to reload current menu}
ClearCurrent = 3; {signal to remove current menu}
ClearAll = 4; {signal to remove all menus}
Undefined = 99; {despatcher has not been assigned}
type
NestKeyProc = procedure(var Ch:char; Code:Integer);
DespatcherProc = procedure(Var Code: integer; var Finish:byte);
MenuStr = string[MenuStrLength];
NDisplay = record
X: byte; {top X coord}
Y: byte; {top Y coord}
LeftSide: boolean; {does menu start on left or right}
AllowEsc: boolean; {can user escape from the top level}
BoxType: byte; {single,double etc}
BoxFCol: byte; {Border foreground color}
BoxBCol: byte; {Border background color}
CapFCol: byte; {Capital letter foreground color}
BacCol: byte; {menu background color}
NorFCol: byte; {normal foreground color}
LoFCol: byte; {inactive topic foreground color}
HiFCol: byte; {highlighted topic foreground color}
HiBCol: byte; {highlighted topic background color}
LeftChar: char; {left-hand topic highlight character}
RightChar: char; {right-hand topic highlight character}
Hook: NestKeyProc; { a procedure called after every key is pressed}
Despatcher: Despatcherproc; { the main procedure to execute}
end;
TopicPtr = ^TopicRecord;
MenuPtr = ^NestMenu;
TopicRecord = record
Name: MenuStr;
Active: boolean;
HotKey: char;
RetCode: integer;
SubMenu: MenuPtr;
NextTopic: TopicPtr;
end;
NestMenu = record
Title: MenuStr; {title for menu}
TopicWidth: byte; {width of topics in menu}
VisibleLines: word; {no. topics in box, 0 is DisplayLines - 2}
FirstTopic: TopicPtr; {used internally, do not alter}
TotalTopics: word; {used internally, do not alter}
end;
var
Nfatal: boolean;
NError: integer;
NTTT: NDisplay;
procedure DefaultSettings;
procedure AssignDespatcher(D:DespatcherProc);
procedure InitializeMenu(var Menu:NestMenu; Tit: menuStr; Width: byte;
DisplayLines: word);
procedure AddTopic(var Menu:NestMenu; Nam: MenuStr; Activ: boolean;
HKey: char; Code: integer; Sub: MenuPtr);
procedure ModifyTopic(var Menu:NestMenu; TopicNo: word; Nam: MenuStr;
Activ: boolean; HKey: char; Code: integer;
Sub: MenuPtr);
procedure ModifyTopicName(var Menu:NestMenu; TopicNo: word; Nam: MenuStr);
procedure ModifyTopicActive(var Menu:NestMenu; TopicNo: word; Activ: Boolean);
procedure ModifyTopicHotKey(var Menu:NestMenu; TopicNo: word; HKey: char);
procedure ModifyTopicRetCode(var Menu:NestMenu; TopicNo: word; Code: integer);
procedure ModifyTopicSubMenu(var Menu:NestMenu; TopicNo : word; Sub : MenuPtr);
procedure DeleteATopic(var Menu:NestMenu;TopicNo: word);
procedure DeleteAllTopics(var Menu:NestMenu);
procedure ShowNest(var Menu:NestMenu);
IMPLEMENTATION
var DespatcherAssigned: boolean;
procedure NestTTTError(No: byte);
{Updates Nerror and optionally displays error message then halts program}
var Msg: string;
begin
Nerror := No;
if Nfatal = true then
begin
case No of
1: Msg := 'Insufficient memory to add topic';
2: Msg := 'Insufficient memory to save screen';
3: Msg := 'No active picks in menu';
4: Msg := 'Screen was not previously saved cannot restore';
5: Msg := 'Too many levels in menu. Change MaxLevels in NestTTT';
6: Msg := 'Topic does not exist, cannot modify';
7: Msg := 'A user procedure has not been assigned to despatcher';
else Msg := '?) -- Utterly confused';
end; {case}
Msg := 'Fatal Error (NestTTT -- '+Msg;
Writeln(Msg);
delay(5000); {display long enough to read if child process}
halt;
end;
end; { NestTTTError }
{$F+}
procedure EmptyDespatcher(var Code: integer; var Finish: byte);
{}
begin
Finish := Undefined;
end; { EmptyDespatcher }
procedure NoNestHook(var Ch: char; Code: integer);
{}
begin
end; { NoNestHook }
{$F-}
procedure DefaultSettings;
begin
with NTTT do
begin
X := 0;
Y := 0;
DespatcherAssigned := false;
LeftSide := true;
AllowEsc := true;
BoxType := 1;
if ColorScreen then
begin
BoxFCol := yellow;
BoxBCol := blue;
CapFCol := white;
BacCol := blue;
NorFCol := lightgray;
LoFCol := black;
HiFCol := white;
HiBCol := red;
end else
begin
BoxFCol := white;
BoxBCol := black;
CapFCol := white;
BacCol := black;
NorFCol := lightgray;
LoFCol := darkgray;
HiFCol := white;
HiBCol := black;
end;
LeftChar := Chr(16);
RightChar := Chr(17);
{$IFNDEF VER40}
Hook := NoNestHook;
Despatcher := EmptyDespatcher;
{$ELSE}
NestUserHook := nil;
NestDespatcher := nil;
{$ENDIF}
end; {with}
end; { DefaultSettings }
{$IFNDEF VER40}
procedure AssignDespatcher(D: DespatcherProc);
{}
begin
NTTT.Despatcher := D;
DespatcherAssigned := true;
end; { AssignDespatcher }
{$ENDIF}
procedure InitializeMenu(var Menu: NestMenu; Tit: menuStr; Width: byte;
DisplayLines: word);
{}
begin
with Menu do
begin
Title := Tit;
TopicWidth := Width;
VisibleLines := DisplayLines;
FirstTopic := nil;
TotalTopics := 0;
end; {with}
end; { InitializeMenu }
procedure AddTopic(var Menu: NestMenu; Nam: MenuStr; Activ: boolean;
HKey: char; Code: integer; Sub: MenuPtr);
{Adds a new topic to the menu.}
var TempPtr: TopicPtr;
begin
if MaxAvail < SizeOf(TempPtr^) then
begin
NestTTTError(1); {not enough memory}
exit;
end else
NError := 0;
if Menu.FirstTopic = nil then
begin
getmem(Menu.FirstTopic,SizeOf(TempPtr^));
TempPtr := Menu.FirstTopic;
end else
begin
TempPtr := Menu.FirstTopic; {start at bottom}
while TempPtr^.NextTopic <> nil do {loop to unallocated block}
TempPtr := TempPtr^.NextTopic;
getmem(TempPtr^.NextTopic,SizeOf(TempPtr^));
TempPtr := TempPtr^.NextTopic;
end;
with TempPtr^ do
begin
Name := Nam;
if (Name = '-') or (Name = '=') then
Active := false
else
Active := Activ;
HotKey := Hkey;
RetCode := Code;
SubMenu := Sub;
NextTopic := nil;
end;
inc(Menu.TotalTopics);
end; { AddTopic }
function PointertoTopic(Men:NestMenu;TopicNo:word): TopicPtr;
{returns a pointer to the TopicNo'th entry in menu, or nil
if greater than TotalTopics}
var W: word;
TempPtr: TopicPtr;
begin
with Men do
begin
if TopicNo > TotalTopics then
TempPtr := nil
else
begin
TempPtr := FirstTopic;
for W := 2 to TopicNo do
TempPtr := TempPtr^.NextTopic
end;
end;
PointertoTopic := TempPtr;
end; { PointertoTopic }
procedure ModifyTopic(var Menu: NestMenu; TopicNo: word; Nam: MenuStr;
Activ: boolean; HKey: char; Code: integer;
Sub: MenuPtr);
{Changes all the settings for a topic}
var TempPtr: TopicPtr;
begin
TempPtr := PointerToTopic(Menu,TopicNo);
if TempPtr = nil then
NestTTTError(6);
with TempPtr^ do
begin
Name := Nam;
if (Name = '-') or (Name = '=') then
Active := false
else
Active := Activ;
HotKey := Hkey;
RetCode := Code;
SubMenu := Sub;
end; {with}
end; { ModifyTopic }
procedure ModifyTopicName(var Menu: NestMenu; TopicNo: word; Nam: MenuStr);
{Change title or name of a topic}
var TempPtr: TopicPtr;
begin
TempPtr := PointerToTopic(Menu,TopicNo);
if TempPtr = nil then
NestTTTError(6);
TempPtr^.Name := Nam;
if (Nam = '-') or (Nam = '=') then
TempPtr^.Active := false;
end; { ModifyTopicName }
procedure ModifyTopicActive(var Menu: NestMenu; TopicNo: word; Activ: boolean);
{Changes active status of a topic}
var TempPtr: TopicPtr;
begin
TempPtr := PointerToTopic(Menu,TopicNo);
if TempPtr = nil then
NestTTTError(6);
TempPtr^.Active := Activ;
end; { ModifyTopicActive }
procedure ModifyTopicHotKey(var Menu: NestMenu; TopicNo: word; HKey: char);
{Changes Hotkey character of a topic}
var TempPtr: TopicPtr;
begin
TempPtr := PointerToTopic(Menu,TopicNo);
if TempPtr = nil then
NestTTTError(6);
TempPtr^.HotKey := HKey;
end; { ModifyTopicHotKey }
procedure ModifyTopicRetCode(var Menu: NestMenu; TopicNo: word; Code: integer);
{Changes Return code for a topic}
var TempPtr: TopicPtr;
begin
TempPtr := PointerToTopic(Menu,TopicNo);
if TempPtr = nil then
NestTTTError(6);
TempPtr^.Retcode := Code;
end; { ModifyTopicHotKey }
procedure ModifyTopicSubMenu(var Menu: NestMenu; TopicNo: word; Sub: MenuPtr);
{Changes Return code for a topic}
var TempPtr: TopicPtr;
begin
TempPtr := PointerToTopic(Menu,TopicNo);
if TempPtr = nil then
NestTTTError(6);
TempPtr^.SubMenu := Sub;
end; { ModifyTopicHotKey }
procedure DeleteATopic(var Menu: NestMenu; TopicNo: word);
{}
var TempPtrA,TempPtrB: TopicPtr;
begin
if TopicNo = 1 then
begin
if Menu.FirstTopic = nil then
NestTTTError(6);
TempPtrA := Menu.FirstTopic^.NextTopic;
freemem(Menu.FirstTopic,SizeOf(TempPtrA^));
Menu.FirstTopic := TempPtrA;
end else
begin
TempPtrA := PointerToTopic(Menu,pred(TopicNo));
if TempPtrA = nil then
NestTTTError(6);
TempPtrB := PointerToTopic(Menu,TopicNo);
if TempPtrB = nil then
NestTTTError(6);
TempPtrA^.NextTopic := TempPtrB^.NextTopic;
freemem(TempPtrB,SizeOf(TempPtrB^));
end;
dec(Menu.TotalTopics);
end; { DeleteATopic }
procedure DeleteAllTopics(var Menu: NestMenu);
{}
var TempPtrA,TempPtrB: TopicPtr;
begin
TempPtrA := Menu.FirstTopic;
while (TempPtrA <> nil) do
begin
TempPtrB := TempPtrA^.NextTopic;
if TempPtrA <> nil then
begin
freemem(TempPtrA,SizeOf(TempPtrA^));
TempPtrA := TempPtrB;
end;
end;
Menu.FirstTopic := nil;
end; { DeleteAllTopics }
procedure ShowNest(var Menu: NestMenu);
{}
type
LevelInfo = record
Pick: word;
TheMenu: MenuPtr; {link to menu}
X1: integer; {coords of saved screens}
Y1: integer;
X2: integer;
Y2: integer;
TopPick: byte;
HiPick: byte;
SavedScreen: pointer; {location of saved screen}
end;
var
I: word;
TempPtr: TopicPtr;
FinCode: byte;
Nest: array[1..MaxLevels] of LevelInfo;
CurrentLevel: byte;
LiveMenu: Nestmenu;
ChL: char;
Found,
Finished: boolean;
function TopicPointer(TopicNo: word): TopicPtr;
{subfunction}
begin
TopicPointer := PointertoTopic(LiveMenu,TopicNo);
end; { TopicPointer }
procedure ComputeCoords(var LiveMenu: NestMenu);
{subfunction determines X1,Y1,X2,Y2 for new menu}
begin
with Nest[Currentlevel] do
begin
if LiveMenu.VisibleLines = 0 then
LiveMenu.VisibleLines := HardVars.Depth-2;
if LiveMenu.TotalTopics < LiveMenu.VisibleLines then
LiveMenu.VisibleLines := LiveMenu.TotalTopics;
if CurrentLevel = 1 then
begin
if NTTT.X = 0 then
begin
if NTTT.LeftSide then
begin
X1 := 1;
X2 := LiveMenu.TopicWidth + 4;
end else {RightSide}
begin
X2 := 80;
X1 := 80 - LiveMenu.TopicWidth - 3;
end;
end else {X not Zero}
begin
if NTTT.LeftSide then
begin
X1 := NTTT.X;
X2 := pred(X1)+LiveMenu.TopicWidth + 4;
if X2 > 80 then
begin
X2 := 80;
X1 := X2 - 3 - LiveMenu.TopicWidth;
end;
end else {RightSide}
begin
X2 := NTTT.X;
X1 := X2 - LiveMenu.TopicWidth - 3;
if X1 < 1 then
begin
X1 := 1;
X2 := X1 +LiveMenu.TopicWidth +3;
end;
end;
end;
if NTTT.Y = 0 then
Y1 := 1
else
Y1 := NTTT.Y;
if LiveMenu.TotalTopics >= LiveMenu.VisibleLines then
Y2 := Y1 + succ(LiveMenu.VisibleLines)
else
Y2 := Y1 + succ(LiveMenu.TotalTopics);
if Y2 > HardVars.Depth then
begin
Y2 := HardVars.Depth;
LiveMenu.VisibleLines := Y2 - succ(Y1);
end;
end else {not the first level menu}
begin
if NTTT.LeftSide then
begin
X1 := pred(Nest[pred(CurrentLevel)].X2);
X2 := X1 + 3 + LiveMenu.TopicWidth;
if X2 > 80 then
begin
X2 := 80;
X1 := X2 - 4 - LiveMenu.TopicWidth;
end;
end else {rightside}
begin
X2 := succ(Nest[pred(CurrentLevel)].X1);
X1 := X2 - LiveMenu.TopicWidth - 3;
if X1 < 1 then
begin
X1 := 1;
X2 := X1 +LiveMenu.TopicWidth +3;
end;
end;
Y1 := succ(Nest[Pred(CurrentLevel)].Y1) +
Nest[Pred(CurrentLevel)].HiPick -
Nest[Pred(CurrentLevel)].TopPick;
if LiveMenu.TotalTopics >= LiveMenu.VisibleLines then
Y2 := succ(Y1) + LiveMenu.VisibleLines
else
Y2 := succ(Y1) + LiveMenu.TotalTopics;
if Y2 > HardVars.Depth then
begin
Y2 := HardVars.Depth;
if Y2 - succ(LiveMenu.VisibleLines) >= 1 then
Y1 := Y2 - succ(LiveMenu.VisibleLines)
else
begin
Y1 := 1;
LiveMenu.VisibleLines := HardVars.Depth - 2;
end;
end;
end;
end; { with }
end; { ComputeCoords }
procedure SaveScreen;
{saved part of screen overlayed by menu}
begin
with Nest[CurrentLevel] do
begin
if MaxAvail < succ(Y2-Y1)*succ(X2-X1)*2 then
NestTTTError(2)
else
begin
getmem(SavedScreen,succ(Y2-Y1)*succ(X2-X1)*2);
PartSave(X1,Y1,X2,Y2,SavedScreen^);
end;
end;
end; { SaveScreen }
procedure RestoreScreen;
{saved part of screen overlayed by menu}
begin
with Nest[CurrentLevel] do
begin
if SavedScreen = nil then
NestTTTError(4)
else
begin
PartRestore(X1,Y1,X2,Y2,SavedScreen^);
FreeMem(SavedScreen,succ(Y2-Y1)*succ(X2-X1)*2);
end;
end;
end; { RestoreScreen }
procedure ComputeFirstActivePick;
{}
var I : word;
begin
With Nest[Currentlevel] do
begin
TopPick := 1;
HiPick := 1;
while (TopicPointer(HiPick)^.Active = false)
and (HiPick < LiveMenu.TotalTopics) do
inc(HiPick);
if (TopicPointer(HiPick)^.Active = false) then {no active picks in menu}
begin
NestTTTError(3);
exit;
end;
if HiPick > LiveMenu.VisibleLines then
TopPick := HiPick - pred(LiveMenu.VisibleLines);
end; { with }
end; { ComputeFirstActivePick }
procedure ComputeTopicWidth(var Livemenu: NestMenu);
{}
var I: word;
W,Biggest: Byte;
begin
Biggest := 0;
for I := 1 To LiveMenu.TotalTopics do
begin
W := length(TopicPointer(I)^.Name);
if Biggest < W then
Biggest := W;
end;
if Biggest < length(LiveMenu.Title) then
Biggest := length(LiveMenu.Title);
LiveMenu.TopicWidth := Biggest;
end; { ComputeTopicWidth }
procedure WriteTopic(TopicNo:word;Hilight:boolean);
{}
var A,Y: byte;
T: TopicPtr;
begin
T := TopicPointer(TopicNo);
if T = Nil then
exit;
if HiLight then
A := Cattr(NTTT.HiFCol,NTTT.HiBCol)
else
begin
if T^.Active then
A := Cattr(NTTT.NorFcol,NTTT.BacCol)
else
A := Cattr(NTTT.LoFcol,NTTT.BacCol);
end;
with Nest[Currentlevel] do
begin
Y := succ(Y1) + TopicNo - TopPick;
if HiLight then
WriteAT(succ(X1),Y,A,
NTTT.LeftChar+
PadLeft(T^.Name,LiveMenu.TopicWidth,' ')+
NTTT.Rightchar)
else
case T^.Name[1] of
'-': HorizLine(Succ(X1),Pred(X2),Y,Cattr(NTTT.BoxFCol,NTTT.BacCol),1);
'=': HorizLine(Succ(X1),Pred(X2),Y,Cattr(NTTT.BoxFCol,NTTT.BacCol),1);
else
begin
WriteAT(succ(X1),Y,A,' '+
PadLeft(T^.Name,LiveMenu.TopicWidth,' ')+' ');
if (T^.Active) and (FirstCapitalPos(T^.Name) > 0) then
WriteAT(succ(X1)+FirstCapitalPos(T^.Name),Y,
Cattr(NTTT.CapFCol,NTTT.BacCol),
FirstCapital(T^.Name));
end;
end; {case}
end;
end; { WriteTopic }
procedure DisplayAllTopics;
{}
var I : Integer;
begin
with Nest[CurrentLevel] do
begin
for I := TopPick to TopPick+pred(LiveMenu.VisibleLines) do
WriteTopic(I,false);
WriteTopic(HiPick,true);
end;
end; { DisplayAllTopics }
procedure DisplayLiveMenu;
{}
begin
with Nest[CurrentLevel] do
begin
FBox(X1,Y1,X2,Y2,Cattr(NTTT.BoxFCol,NTTT.BoxBCol),NTTT.BoxType);
WriteBetween(X1,X2,Y1,Cattr(NTTT.BoxFCol,NTTT.BoxBCol),Livemenu.Title);
end;
DisplayAllTopics;
end; { DisplayLiveMenu }
function NextPickDown(Wrap:boolean): word;
{}
var P: word;
begin
with Nest[CurrentLevel] do
begin
P := HiPick;
if P < LiveMenu.TotalTopics then
begin
inc(P);
while (P < LiveMenu.TotalTopics)
and (TopicPointer(P)^.Active = false) do
inc(P);
if TopicPointer(P)^.Active = false then
begin
if Wrap and (LiveMenu.TotalTopics <= LiveMenu.VisibleLines) then
begin
P := TopPick; {scroll to top}
while (P < LiveMenu.TotalTopics)
and (TopicPointer(P)^.Active = false) do
inc(P);
end else
P := Hipick;
end;
end else {P is at bottom of menu}
begin
if Wrap and (LiveMenu.TotalTopics <= LiveMenu.VisibleLines) then
P := TopPick; {scroll to top}
while (P < LiveMenu.TotalTopics)
and (TopicPointer(P)^.Active = false) do
inc(P);
end;
NextPickDown := P;
end; {with}
end; { NextPickDown }
function NextPickUp(Wrap:boolean): word;
{}
var P: word;
begin
with Nest[CurrentLevel] do
begin
P := HiPick;
if P > 1 then
begin
dec(P);
while (P > 1)
and (TopicPointer(P)^.Active = false) do
dec(P);
if TopicPointer(P)^.Active = false then
begin
if Wrap and (LiveMenu.TotalTopics <= LiveMenu.VisibleLines) then
begin
P := LiveMenu.TotalTopics; {scroll to top}
while (P > 1) and (TopicPointer(P)^.Active = false) do
dec(P);
end else
P := Hipick;
end;
end else {P is at top of menu}
begin
if Wrap and (LiveMenu.TotalTopics <= LiveMenu.VisibleLines) then
begin
P := LiveMenu.TotalTopics; {scroll to top}
while (P > 1) and (TopicPointer(P)^.Active = false) do
dec(P);
end;
end;
NextPickUp := P;
end; {with}
end; { NextPickUp }
procedure LoadMenu(var NewMenu: NestMenu);
{}
begin
if CurrentLevel < MaxLevels then
inc(CurrentLevel)
else
NestTTTError(5);
Nest[CurrentLevel].TheMenu := @NewMenu;
LiveMenu := NewMenu;
if LiveMenu.TopicWidth <= 0 then
begin
ComputeTopicWidth(LiveMenu);
NewMenu.TopicWidth := LiveMenu.TopicWidth;
end;
ComputeCoords(LiveMenu);
ComputeCoords(NewMenu);
ComputeFirstActivePick;
SaveScreen;
DisplayLiveMenu;
end; { LoadMenu }
procedure ExecuteCommand;
{}
var TempPtr: TopicPtr;
Code: integer;
begin
TempPtr := TopicPointer(Nest[CurrentLevel].HiPick);
if TempPtr^.SubMenu <> nil then
LoadMenu(TempPtr^.SubMenu^)
else
begin
Code := TempPtr^.Retcode;
{$IFNDEF VER40}
NTTT.Despatcher(Code,Fincode);
{$ELSE}
if NestDespatcher <> Nil then
CallFromNestDespatcher(Code,Fincode)
else
Fincode := Undefined;
{$ENDIF}
case Fincode of
Undefined : NestTTTError(7);
DontClear : ;
RefreshTopic : WriteTopic(Nest[CurrentLevel].HiPick,True);
RefreshMenu : DisplayAllTopics;
ClearCurrent : begin
RestoreScreen;
if CurrentLevel > 1 then
begin
dec(CurrentLevel);
LiveMenu := Nest[CurrentLevel].TheMenu^;
end else
Finished := true;
end;
ClearAll : begin
while CurrentLevel > 0 do
begin
RestoreScreen;
dec(CurrentLevel);
LiveMenu := Nest[CurrentLevel].TheMenu^;
end;
Finished := true;
end;
end; {case}
end;
end; { ExecuteCommand }
procedure DisplayMore;
{}
var A: byte;
begin
if LiveMenu.VisibleLines < Livemenu.TotalTopics then
with Nest[CurrentLevel] do
begin
A := Cattr(NTTT.CapFCol,NTTT.BoxBCol);
if TopPick > 1 then
WriteAT(X2,Succ(Y1),A,chr(24))
else
VertLine(X2,Succ(Y1),Succ(Y1),Cattr(NTTT.BoxFcol,NTTT.BoxBCol),Nttt.Boxtype);
if TopPick + Pred(LiveMenu.VisibleLines) < LiveMenu.TotalTopics then
WriteAT(X2,Pred(Y2),A,chr(25))
else
VertLine(X2,Pred(Y2),Pred(Y2),Cattr(NTTT.BoxFcol,NTTT.BoxBCol),Nttt.Boxtype);
end;
end; { DisplayMore }
begin
Currentlevel := 0;
{$IFNDEF VER40}
if not DespatcherAssigned then
NestTTTError(7);
{$ELSE}
if NestDespatcher = nil then
NestTTTError(7);
{$ENDIF}
LoadMenu(Menu);
Finished := False;
repeat
DisplayMore;
ChL := GetKey;
{$IFNDEF VER40}
NTTT.Hook(ChL,TopicPointer(Nest[CurrentLevel].HiPick)^.RetCode);
{$ELSE}
if NestUserHook <> Nil then
CallFromNestUserHook(ChL,TopicPointer(Nest[CurrentLevel].HiPick)^.RetCode);
{$ENDIF}
if ChL <> #0 then
case upcase(ChL) of
#132, {right button}
#027 : if CurrentLevel = 1 then
begin
if NTTT.AllowEsc then
begin
RestoreScreen;
Finished := true;
end;
end else
begin
RestoreScreen;
dec(CurrentLevel);
LiveMenu := Nest[CurrentLevel].TheMenu^;
end;
#133, {Mouse left button}
#13 : begin {Enter}
ExecuteCommand;
end;
' ',
#129, {Mouse down}
#208 : with Nest[CurrentLevel] do {Down arrow}
begin
WriteTopic(HiPick,False);
HiPick := NextPickDown(ChL = #208);
if HiPick >= TopPick + LiveMenu.VisibleLines then
begin
TopPick := HiPick - pred(LiveMenu.VisibleLines);
DisplayAllTopics;
end;
WriteTopic(HiPick,True);
end;
#128, {Mouse up}
#200 : with Nest[CurrentLevel] do {Up arrow}
begin
WriteTopic(HiPick,False);
HiPick := NextPickUp(ChL = #200);
if HiPick < TopPick then
begin
TopPick := HiPick;
DisplayAllTopics;
end;
WriteTopic(HiPick,True);
end;
#199 : if Nest[CurrentLevel].HiPick <> 1 then {Home}
begin
ComputeFirstActivePick;
DisplayAllTopics;
end;
#207 : With Nest[CurrentLevel] do
begin
WriteTopic(HiPick,False);
HiPick := LiveMenu.TotalTopics;
while (HiPick > 0)
and (TopicPointer(HiPick)^.Active =false) do
dec(HiPick);
if HiPick >= TopPick + LiveMenu.VisibleLines then
begin
TopPick := HiPick - pred(LiveMenu.VisibleLines);
DisplayAllTopics;
end;
WriteTopic(HiPick,True);
end;
'A'..'Z': with Nest[CurrentLevel] do
begin
Found := false;
I := HiPick;
repeat
TempPtr := TopicPointer(I);
if (FirstCapital(TempPtr^.Name) = upcase(ChL))
and (TempPtr^.Active) then
begin
Found := true;
WriteTopic(HiPick,false);
HiPick := I;
if HiPick >= TopPick + LiveMenu.VisibleLines then
begin
TopPick := HiPick - pred(LiveMenu.VisibleLines);
DisplayAllTopics;
end else
if HiPick < TopPick then
begin
TopPick := HiPick;
DisplayAllTopics;
end;
WriteTopic(HiPick,true);
end else
if I = LiveMenu.TotalTopics then
I := 1
else
inc(I);
until Found or (I = HiPick);
if Found then
ExecuteCommand;
end;
else {see if the user pressed a special key}
with Nest[CurrentLevel] do
begin
Found := false;
I := HiPick;
repeat
TempPtr := TopicPointer(I);
if ((TempPtr^.Hotkey) = ChL)
and (TempPtr^.Active) then
begin
Found := true;
WriteTopic(HiPick,false);
HiPick := I;
if HiPick >= TopPick + LiveMenu.VisibleLines then
begin
TopPick := HiPick - pred(LiveMenu.VisibleLines);
DisplayAllTopics;
end else
if HiPick < TopPick then
begin
TopPick := HiPick;
DisplayAllTopics;
end;
WriteTopic(HiPick,true);
end else
if I = LiveMenu.TotalTopics then
I := 1
else
inc(I);
until Found or (I = HiPick);
if Found then
ExecuteCommand;
end;
end; {case}
until Finished;
end; { ShowNest }
begin
DefaultSettings;
NFatal := true;
end.