home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / PASCAL / TTT5-1.ZIP / PULLTTT5.PAS < prev    next >
Pascal/Delphi Source File  |  1989-01-31  |  28KB  |  739 lines

  1. {--------------------------------------------------------------------------}
  2. {                         TechnoJock's Turbo Toolkit                       }
  3. {                                                                          }
  4. {                              Version   5.00                              }
  5. {                                                                          }
  6. {                                                                          }
  7. {              Copyright 1986, 1989 TechnoJock Software, Inc.              }
  8. {                           All Rights Reserved                            }
  9. {                          Restricted by License                           }
  10. {--------------------------------------------------------------------------}
  11.  
  12.                      {--------------------------------}                                       
  13.                      {       Unit:  PullTTT5          }
  14.                      {--------------------------------}
  15.  
  16.  
  17. {$S-,R-,V-,D-}       
  18.  
  19. unit PullTTT5;
  20.  
  21. Interface
  22.  
  23. Uses CRT, DOS, FastTTT5, WinTTT5, KeyTTT5;
  24.  
  25. Const
  26.     Max_Pull_Topics = 60;
  27.     Max_Pull_Width  = 30;
  28. type
  29.     Pull_Array = array [1..Max_Pull_Topics] of string[Max_Pull_Width];
  30.     {$IFDEF VER50}
  31.      Pull_Hook = Procedure(var Ch: char; Main, Sub :byte);
  32.     {$ENDIF}
  33.     MenuDisplay = record
  34.                      TopX:byte;
  35.                      TopY:byte;
  36.                      Style:byte;
  37.                      FCol: byte;       {normal option foreground color}
  38.                      BCol: byte;       {normal option background color}
  39.                      CCol: byte;       {color of first Character}
  40.                      MBCol: byte;      {highlight bgnd col for main pick when sub-menu displayed}
  41.                      HFCol: byte;      {highlighted option foreground}
  42.                      HBCol: byte;      {highlighted option background}
  43.                      BorCol: byte;     {border foreground color}
  44.                      Gap   : byte;     {Gap between Picks}
  45.                      LeftChar    : char;     {left-hand topic highlight character}
  46.                      RightChar   : char;     {right-hand topic highlight character}
  47.                      AllowEsc    : boolean; {is Escape key operative}
  48.                      RemoveMenu  : boolean;{clear screen on exit}
  49.                      AlwaysDown : boolean;
  50.                      {$IFDEF VER50}
  51.                      Hook         : Pull_hook;
  52.                      {$ENDIF}
  53.                   end;
  54. Const
  55.     Max_MainPicks = 8;
  56.     Max_Subpicks  = 10;
  57.     MainInd = '\';           {symbol that indicates main menu description}
  58.  
  59. Var
  60.   PTTT : MenuDisplay;
  61.  
  62.   {$IFNDEF VER50}
  63.   PM_UserHook : pointer;
  64.   {$ENDIF}
  65.  
  66. {$IFDEF VER50}
  67. Procedure No_Hook(var Ch: char; Main, Sub :byte);
  68. {$ENDIF}
  69.  
  70. Procedure Pull_Menu( Definition:Pull_Array; var PickM, PickS:byte);
  71.  
  72.  
  73. Implementation
  74.  
  75.   {$IFDEF VER50}
  76.   {$F+}
  77.   Procedure No_Hook(var Ch: char; Main, Sub :byte);
  78.   {}
  79.   begin
  80.   end; {of proc No_Hook}
  81.   {$F-}
  82.   {$ENDIF}
  83.  
  84.    {$IFNDEF VER50}
  85.    Procedure CallFromPM(var Ch: char; Main, Sub :byte);
  86.           Inline($FF/$1E/PM_UserHook);
  87.    {$ENDIF}
  88.  
  89.    Procedure Default_Settings;
  90.    begin
  91.        {$IFNDEF VER50}
  92.        PM_UserHook := nil;
  93.        {$ENDIF}
  94.        With PTTT do
  95.        begin
  96.            {$IFDEF VER50}
  97.            Hook := No_Hook;
  98.            {$ENDIF}
  99.            TopY := 1;
  100.            TopX := 1;
  101.            Style := 1;
  102.            Gap := 2;
  103.            LeftChar := #016;
  104.            RightChar := #017;
  105.            AllowEsc := true;
  106.            RemoveMenu := true;
  107.            AlwaysDown := true;
  108.            If BaseOfScreen = $b000 then {monochrome}
  109.            begin
  110.                FCol  := lightgray;
  111.                BCol  := black;
  112.                CCol  := white;
  113.                MBCol  := lightgray;
  114.                HFCol  := black;
  115.                HBCol  := lightgray;
  116.                BorCol := lightgray;
  117.            end
  118.            else                    {color}
  119.            begin
  120.                FCol  := yellow;
  121.                BCol  := blue;
  122.                CCol  := lightcyan;
  123.                MBCol  := red;
  124.                HFCol  := yellow;
  125.                HBCol  := red;
  126.                BorCol := cyan;
  127.            end;
  128.       end;
  129.   end; {Proc Default_Settings}
  130.  
  131.  
  132. Procedure Pull_Menu(Definition: Pull_Array; var PickM, PickS:byte);
  133. const
  134.     CursUp = #200  ;  CursDown = #208  ;  CursLeft = #203  ;   CursRight = #205;
  135.     HomeKey = #199 ;  Endkey   = #207  ;  Esc      = #027  ;   Enter     = #13;
  136.     F1      = #187 ;
  137.  
  138. type
  139.    Sub_details = record
  140.                     Text:  Array[0..Max_SubPicks] of string[30];
  141.                     Total: byte;
  142.                     Width: byte;
  143.                     LastPick: byte;
  144.                  end;
  145. var
  146.   Submenu  : array [1..Max_MainPicks] of Sub_Details;
  147.   Tot_main : byte;              {total number of main picks}
  148.   Main_Wid : byte;              {width of main menu box}
  149.   Finished,                     {has user selected menu option}
  150.   Down     : boolean;           {indicates if sub-menu displayed}
  151.   ChM,ChT      : char;          {keypressed character}
  152.   X1, Y1, X2, Y2 : byte;        {lower menu borders}
  153.   Cap,Count      : byte;        {used to check if letter pressed = first char}
  154.   Saved_Screen : Pointer;
  155.   I                 : integer;
  156.   TLchar,           {border submenu upper left char}
  157.   TRchar,           {border submenu upper right char}
  158.   BLchar,           {border submenu bottom left char}
  159.   BRchar,           {border submenu bottom right char}
  160.   Joinchar,         {border joining character}
  161.   Joindownchar,     {border joining character}
  162.   JoinleftChar,     {border joining character}
  163.   VertChar,         {border vert character}
  164.   Horizchar:char;   {border horiz char}
  165.  
  166.  
  167.     Procedure PullError(No : byte);
  168.     var M : string;
  169.     begin
  170.         Case No of
  171.         1 : M := 'Menu definiton must start with a Main ("\") description';
  172.         2 : M := 'Main menu definition must be at least 1 character';
  173.         3 : M := 'Too many main menu picks.';
  174.         4 : M := 'Too many sub-menu picks.';
  175.         5 : M := 'No end of menu indicator found';
  176.         6 : M := 'Must be at least two sub-menus';
  177.         7 : M := 'Main menu will not fit in 80 characters';
  178.         8 : M := 'No memory to save screen';
  179.         end; {case}
  180.         Writeln;
  181.         Writeln(M);
  182.         Halt;
  183.     end; {Abort}
  184.  
  185.     Procedure Set_Style;
  186.     {Sets variables for the box characters based on defined style}
  187.     begin
  188.         Case PTTT.Style of
  189.         1  :  begin
  190.                   TLchar := #218;
  191.                   TRchar := #191;
  192.                   BLchar := #192;
  193.                   BRchar := #217;
  194.                   Joinchar := #194;
  195.                   Joindownchar := #193;
  196.                   JoinleftChar := #180;
  197.                   VertChar := #179;
  198.                   Horizchar := #196;
  199.               end;
  200.         2  :  begin
  201.                   TLchar := #201;
  202.                   TRchar := #187;
  203.                   BLchar := #200;
  204.                   BRchar := #188;
  205.                   Joinchar := #203;
  206.                   Joindownchar := #202;
  207.                   JoinleftChar := #185;
  208.                   VertChar := #186;
  209.                   Horizchar := #205;
  210.               end;
  211.         else
  212.              begin
  213.                   TLchar := ' ';
  214.                   TRchar := ' ';
  215.                   BLchar := ' ';
  216.                   BRchar := ' ';
  217.                   Joinchar := ' ';
  218.                   Joindownchar := ' ';
  219.                   JoinleftChar := ' ';
  220.                   VertChar := ' ';
  221.                   Horizchar := ' ';
  222.               end;
  223.         end; {Case}
  224.     end;  {Proc Set_Style}
  225.  
  226.     Procedure Save_Screen;
  227.     {saved part of screen overlayed by menu}
  228.     begin
  229.         If MaxAvail < DisplayLines*160 then
  230.            PullError(8)
  231.         else
  232.         begin
  233.             GetMem(Saved_Screen,DisplayLines*160);
  234.             PartSave(1,1,80,DisplayLines,Saved_Screen^);
  235.         end;
  236.     end; {of proc Save_Screen}
  237.  
  238.     Procedure PartRestoreScreen(X1,Y1,X2,Y2:byte);
  239.     {Move from heap to screen, part of saved screen}
  240.     Var
  241.        I,width     : byte;
  242.        ScreenAdr   : integer;
  243.     begin
  244.         Width := succ(X2- X1);
  245.         For I :=  Y1 to Y2 do
  246.         begin
  247.             ScreenAdr   := Pred(I)*160 + Pred(X1)*2;
  248.             MoveToScreen(Mem[Seg(Saved_Screen^):ofs(Saved_Screen^)+SCreenAdr],
  249.                          Mem[BaseOfScreen:ScreenAdr],
  250.                          width);
  251.         end;
  252.     end;
  253.  
  254.       Procedure Restore_Screen;
  255.       {saved part of screen overlayed by menu}
  256.       begin
  257.           PartRestore(1,1,80,DisplayLines,Saved_Screen^);
  258.       end;
  259.  
  260.       Procedure Dispose_Screen;
  261.       {}
  262.       begin
  263.           FreeMem(Saved_Screen,DisplayLines*160);
  264.       end;
  265.  
  266.     Procedure Load_Menu_Parameters;
  267.     { converts the MenuDesc array into the Sub_menu array, and
  268.       determines Tot_main
  269.     }
  270.     var
  271.       I, Maj, Min, Widest : integer;
  272.       Instr : string[30];
  273.       Finished : Boolean;
  274.     begin
  275.         FillChar(Submenu,sizeof(Submenu),#0);
  276.         Tot_main := 0;
  277.         If Definition[1][1] <> '\' then PullError(1);
  278.         Maj := 0;
  279.         Widest := 0;
  280.         I := 0;
  281.         Finished := false;
  282.         While (I < Max_Pull_Topics) and (Finished=false) do
  283.         begin
  284.             Inc(I);
  285.             If Definition[I] <> '' then
  286.             begin
  287.                 Instr := Definition[I];
  288.                 If Instr[1] = MainInd then
  289.                 begin
  290.                     If Maj <> 0 then           {update values for last sub menu}
  291.                     begin
  292.                         SubMenu[Maj].Total := Min;
  293.                         SubMenu[Maj].Width := widest;
  294.                     end;
  295.                     If length(Instr) < 2 then PullError(2);
  296.                     If Instr = Mainind + mainind then   {must have loaded all data}
  297.                     begin                               {note number of main menu }
  298.                         Tot_main := Maj;                   {picks and exit}
  299.                         Finished := true;
  300.                     end;
  301.                     Maj := succ(Maj);
  302.                     If Maj > Max_mainpicks then PullError(3);
  303.                     delete(Instr,1,1);
  304.                     SubMenu[Maj].text[0] := Instr;
  305.                     Min := 0;                      {reset values for next sub heading}
  306.                     Widest := 0;
  307.                 end
  308.                 else         {not a main menu heading}
  309.                 begin
  310.                     Min := succ(Min);
  311.                     If Min > Max_SubPicks then PullError(4);
  312.                     SubMenu[Maj].text[Min] := Instr;
  313.                     If length(Instr) > widest then
  314.                        widest := length(Instr);
  315.                 end;   {if main heading}
  316.             end;
  317.         end; {while}
  318.         If Tot_main = 0 then PullError(5);
  319.         If Tot_main < 2 then PullError(6);
  320.    end; {sub-proc Load_Menu_Parameters}
  321.  
  322.    Function First_Capital(InStr:string; Var StrPos:byte):char;
  323.    {returns the first capital letter in a string and Character position}
  324.    begin
  325.        StrPos := 1;
  326.        While (StrPos <= length(InStr))  and ((InStr[StrPos] in [#65..#90]) = false) do
  327.               StrPos := Succ(StrPos);
  328.        If StrPos > length(InStr) then
  329.        begin
  330.            StrPos := 0;
  331.            First_Capital := ' ';
  332.        end
  333.        else
  334.           First_Capital := InStr[StrPos];
  335.    end;   {First_Capital}
  336.  
  337.    Procedure Display_Main_Picks(No : byte; Col : byte);
  338.    { displays main heading for menu pick 'No', if Col = 1 then
  339.      PTTT.HFCol and PTTT.MBCol cols are used without arrows, else PTTT.FCol and PTTT.BCol
  340.      colors are used}
  341.    var
  342.      ChT : Char;
  343.      X, I, B : byte;
  344.    begin
  345.        X := 1;
  346.        If No = 1 then
  347.           X := X + PTTT.TopX + PTTT.Gap
  348.        else
  349.        begin
  350.            For I := 1 to No - 1 do
  351.                X := X + length(Submenu[I].Text[0]) + PTTT.Gap;
  352.            X := X + PTTT.TopX  + PTTT.Gap ;
  353.        end;
  354.        If Col > 0 then
  355.           Fastwrite(X,PTTT.TopY+ord(PTTT.Style>0),attr(PTTT.HFCol,PTTT.MBCol),
  356.                     Submenu[No].Text[0])
  357.        else
  358.        begin
  359.            Fastwrite(X,PTTT.TopY+ord(PTTT.Style>0),attr(PTTT.FCol,PTTT.BCol),
  360.                      +Submenu[No].Text[0]);
  361.            ChT := First_Capital(Submenu[No].Text[0],B);
  362.            If B <> 0 then
  363.               FastWrite(pred(X)+B,PTTT.TopY+ord(PTTT.Style>0),
  364.                         attr(PTTT.CCol,PTTT.BCol),ChT);
  365.        end;
  366.        GotoXY(X,PTTT.TopY+Ord(PTTT.Style>0));
  367.    end; {Display Main Header}
  368.  
  369.    Procedure Display_Main_Menu;
  370.    {draws boxes, main menu picks and draws border}
  371.    var I : byte;
  372.    begin
  373.        {draw the box}
  374.        Main_Wid := succ(PTTT.Gap) ;           {determine the width of the main menu}
  375.        For I := 1 to Tot_Main do
  376.            Main_Wid := Main_Wid + PTTT.Gap + length(Submenu[I].text[0]);
  377.        If Main_Wid + PTTT.TopX - 1 > 80 then PullError(7);
  378.        If PTTT.Style = 0 then
  379.           ClearText(PTTT.TopX,PTTT.TopY,PTTT.TopX + Main_Wid,PTTT.TopY,PTTT.BorCol,PTTT.BCol)
  380.        else
  381.           Fbox(PTTT.TopX,PTTT.TopY,PTTT.TopX + Main_Wid,PTTT.TopY + 2,PTTT.BorCol,PTTT.BCol,PTTT.Style);
  382.        For I := 1 to ToT_Main do
  383.            Display_Main_Picks(I,0);
  384.        Display_Main_Picks(PickM,1);
  385.    end;  {Display_Main_Menu}
  386.  
  387.    Procedure Remove_Sub_Menu;
  388.    var a : integer;
  389.    begin
  390.        Fastwrite(X1,PTTT.TopY+2,attr(PTTT.BorCol,PTTT.BCol),horizchar);
  391.        Fastwrite(X2,PTTT.TopY+2,attr(PTTT.BorCol,PTTT.BCol),horizchar);
  392.        PartRestoreSCreen(PTTT.TopX, succ(PTTT.TopY)+2*ord(PTTT.Style>0), 80, DisplayLines);
  393.        If (PTTT.Style > 0 ) and (X2 >= PTTT.TopX + Main_wid) then
  394.        begin
  395.            A := PTTT.TopX +Main_Wid + 1;
  396.            PartRestoreScreen(A, PTTT.TopY + 2, 80, PTTT.TopY + 2);
  397.            Fastwrite(A - 1, PTTT.TopY+2, attr(PTTT.BorCol,PTTT.BCol),BRchar);
  398.        end;
  399.        SubMenu[PickM].LastPick := PickS;
  400.    end;
  401.  
  402.    Procedure Display_Sub_Picks(No : byte; Col : byte);
  403.    { displays sub  menu pick 'No', if Col = 1 then
  404.      PTTT.HFCol and PTTT.HBCol cols are used and arrows, else PTTT.FCol and PTTT.BCol
  405.      colors are used}
  406.    var
  407.      ChT : Char;
  408.      B : Byte;
  409.    begin
  410.        If Col = 1 then
  411.           Fastwrite(X1 + 1, succ(PTTT.TopY)+ord(PTTT.Style>0) + No ,
  412.                     attr(PTTT.HFCol,PTTT.HBCol),
  413.                     PTTT.LeftChar + Submenu[PickM].Text[No] + PTTT.Rightchar)
  414.        else
  415.        begin
  416.           Fastwrite(X1 + 1, succ(PTTT.TopY)+Ord(PTTT.Style>0) + No ,
  417.                     attr(PTTT.FCol,PTTT.BCol),
  418.                     ' '+Submenu[PickM].Text[No]+' ');
  419.           ChT := First_Capital(SubMenu[PickM].Text[No],B);
  420.           If B <> 0 then
  421.              FastWrite(X1+1+B,succ(PTTT.TopY)+Ord(PTTT.Style>0) + No ,
  422.                        attr(PTTT.CCol,PTTT.BCol),ChT);
  423.        end;
  424.        GotoXY(X1+1,succ(PTTT.TopY)+ord(PTTT.Style>0)+ No);
  425.    end;
  426.  
  427.  
  428.    Procedure Display_Sub_Menu(No :byte);
  429.    var
  430.      BotLine : string;
  431.      I : byte;
  432.    begin
  433.        If (Submenu[pickM].Total = 0) then
  434.            exit
  435.        else
  436.            Down := true;
  437.        X1 := pred(PTTT.TopX);                    {determine box coords of sub menu}
  438.        If No <> 1 then
  439.        begin
  440.            For I := 1 to pred(No) do
  441.                X1 := X1 + PTTT.Gap + length(Submenu[I].text[0]);
  442.            X1 := pred(X1) + PTTT.Gap ;
  443.        end
  444.        else
  445.           X1 := X1 + 2;
  446.        X2 := X1 + Submenu[No].width + 3;
  447.        If X2 > 80 then
  448.        begin
  449.            X1 := 80 - (X2 - X1) ;
  450.            X2 := 80;
  451.        end;
  452.        Y1 := succ(PTTT.TopY) + ord(PTTT.Style>0);
  453.        Y2 := Y1 + 1 + Submenu[No].total;
  454.        Fbox(X1,Y1,X2,Y2,PTTT.BorCol,PTTT.BCol,PTTT.Style);
  455.        Fastwrite(X1,succ(PTTT.TopY)+ord(PTTT.Style>0),attr(PTTT.BorCol,PTTT.BCol),Joinchar);
  456.        If X2 < PTTT.TopX + Main_wid then
  457.           Fastwrite(X2,succ(PTTT.TopY)+ord(PTTT.Style>0),attr(PTTT.BorCol,PTTT.BCol),Joinchar)
  458.        else
  459.        If X2 = PTTT.TopX + Main_wid then
  460.           Fastwrite(X2,succ(PTTT.TopY)+ord(PTTT.Style>0),attr(PTTT.BorCol,PTTT.BCol),Joinleftchar)
  461.        else
  462.        begin
  463.            Fastwrite(X2,PTTT.TopY+2,attr(PTTT.BorCol,PTTT.BCol),TRchar);
  464.            Fastwrite(PTTT.TopX+Main_wid,succ(PTTT.TopY)+ord(PTTT.Style>0),attr(PTTT.BorCol,PTTT.BCol),Joindownchar);
  465.        end;
  466.        For I := 1 to Submenu[PickM].total do
  467.            Display_Sub_Picks(I,2);
  468.        PickS := SubMenu[PickM].LastPick;
  469.        If not (PickS in [1..Submenu[PickM].Total]) then
  470.           PickS := 1;
  471.        Display_Sub_Picks(PickS,1);
  472.    end;  {proc Display_Sub_Menu}
  473.  
  474. begin     {Main Procedure Display_menu}
  475.     Set_Style;
  476.     Load_Menu_Parameters;
  477.     Save_Screen;
  478.     Finished := false;
  479.     If (PickM < 1) then
  480.        PickM := 1;
  481.     Display_Main_Menu;
  482.     For I := 1 to Tot_main do
  483.         Submenu[I].lastPick := 1;
  484.     SubMenu[PickM].LastPick := PickS;
  485.     If PickS <> 0 then
  486.     begin
  487.         Display_Sub_Menu(PickM);
  488.         Down := true;
  489.     end
  490.     else
  491.         Down := false;
  492.     Repeat
  493.           ChM := GetKey;
  494.           {$IFNDEF VER50}
  495.           If PM_UserHook <> nil then
  496.              If Down then
  497.                 CallFromPM(ChM,PickM,PickS)
  498.              else
  499.                 CallFromPM(ChM,PickM,0);
  500.           {$ENDIF}
  501.           {$IFDEF VER50}
  502.              If Down then
  503.                 PTTT.Hook(ChM,PickM,PickS)
  504.              else
  505.                 PTTT.Hook(ChM,PickM,0);
  506.           {$ENDIF}
  507.           Case upcase(ChM) of
  508.           'A'..'Z'   : If down then    {check if letter is first letter of menu option}
  509.                        begin
  510.                            Count := 0;
  511.                            Repeat
  512.                                 Count := succ(count);
  513.                                 ChT := First_Capital(Submenu[PickM].Text[count],Cap);
  514.                                 If ChT  = upcase(ChM) then
  515.                                 begin
  516.                                     Finished := true;
  517.                                     Display_Sub_Picks(PickS,0);
  518.                                     PickS := Count;
  519.                                     Display_Sub_Picks(PickS,1);
  520.                                 end;
  521.                            Until (Finished) or (count = submenu[PickM].Total);
  522.                        end
  523.                        else      {down false}
  524.                        begin
  525.                            Count := 0;
  526.                            Repeat
  527.                                 Count := succ(count);
  528.                                 ChT := First_Capital(Submenu[Count].Text[0],Cap);
  529.                                 If ChT = upcase(ChM) then
  530.                                 begin
  531.                                     Display_Main_Picks(PickM,0);
  532.                                     PickM := Count;
  533.                                     Down := true;
  534.                                     Display_Main_Picks(PickM,2);
  535.                                     If not (PickS in [1..Submenu[PickM].Total]) then
  536.                                        PickS := 1;
  537.                                     Display_Sub_Menu(PickM);
  538.                                 end;
  539.                            Until (Down) or (count = Tot_Main);
  540.                        end;
  541.           #133,          {Mouse Enter}
  542.           Enter      : If Down or (Submenu[PickM].Total = 0) then
  543.                        begin
  544.                           Finished := true;
  545.                           If Submenu[PickM].Total = 0 then PickS := 0;
  546.                        end
  547.                        else
  548.                        begin
  549.                            Down := true;
  550.                            Display_Main_Picks(PickM,2);
  551.                            Display_Sub_Menu(PickM);
  552.                        end;
  553.           #132,        {Mouse Esc}
  554.           Esc       :  If Down then
  555.                        begin
  556.                            IF not PTTT.AlwaysDown then
  557.                            begin
  558.                                Down := false;
  559.                                Remove_sub_menu;
  560.                                Display_Main_menu;
  561.                            end
  562.                            else
  563.                            begin
  564.                               If PTTT.AllowEsc then
  565.                               begin
  566.                                   Finished := true;
  567.                                   PickM := 0;
  568.                               end;
  569.                            end;
  570.                        end
  571.                        else
  572.                            If PTTT.AllowEsc then
  573.                            begin
  574.                                Finished := true;
  575.                                PickM := 0;
  576.                            end;
  577.           #0        :      begin
  578.                            end;
  579.           #131      :  If PickM < ToT_main then
  580.                        begin
  581.                            Display_main_picks(PickM,0);  {clear highlight}
  582.                            If Down then
  583.                               Remove_Sub_Menu;
  584.                            PickM := succ(PickM);
  585.                            Display_Main_Picks(PickM,1);
  586.                            If down then
  587.                               Display_Sub_Menu(PickM);
  588.                        end;
  589.           CursRight :  begin
  590.                            Display_main_picks(PickM,0);  {clear highlight}
  591.                            If Down then
  592.                               Remove_Sub_Menu;
  593.                            If PickM < ToT_main then
  594.                               PickM := PickM + 1
  595.                            else
  596.                               PickM := 1;
  597.                            Display_Main_Picks(PickM,1);
  598.                            If down then
  599.                                Display_Sub_Menu(PickM);
  600.                        end;
  601.           #130      :  If PickM > 1 then    {MouseLeft}
  602.                        begin
  603.                            Display_main_picks(PickM,0);  {clear highlight}
  604.                            If Down then
  605.                               Remove_Sub_Menu;
  606.                            PickM := pred(PickM);
  607.                            Display_Main_Picks(PickM,1);
  608.                            If down then
  609.                                Display_Sub_Menu(PickM);
  610.                        end;
  611.  
  612.           CursLeft  :  begin
  613.                            Display_main_picks(PickM,0);  {clear highlight}
  614.                            If Down then
  615.                               Remove_Sub_Menu;
  616.                            If PickM > 1 then
  617.                               PickM := pred(PickM)
  618.                            else
  619.                               PickM := Tot_Main;
  620.                            Display_Main_Picks(PickM,1);
  621.                            If down then
  622.                                Display_Sub_Menu(PickM);
  623.                        end;
  624.           #129       : If (Submenu[PickM].Total <> 0) then
  625.                        begin
  626.                            If Not Down then    {Mouse Down}
  627.                            begin
  628.                                Down := true;
  629.                                Display_Main_Picks(PickM,2);
  630.                                Display_Sub_Menu(PickM);
  631.                            end
  632.                            else
  633.                               If PickS < Submenu[PickM].Total then
  634.                               begin
  635.                                   Display_Sub_Picks(PickS,0);
  636.                                   PickS := succ(PickS);
  637.                                   Display_Sub_Picks(PickS,1);
  638.                               end;
  639.                        end;
  640.           CursDown   : If (Submenu[PickM].Total <> 0) then
  641.                        begin
  642.                            If Not Down then
  643.                            begin
  644.                                Down := true;
  645.                                Display_Main_Picks(PickM,2);
  646.                                Display_Sub_Menu(PickM);
  647.                            end
  648.                            else
  649.                            begin
  650.                                Display_Sub_Picks(PickS,0);
  651.                                If PickS < Submenu[PickM].Total then
  652.                                   PickS := succ(PickS)
  653.                                else
  654.                                   PickS := 1;
  655.                                Display_Sub_Picks(PickS,1);
  656.                            end;
  657.                        end;
  658.           #128       : If down and (Picks > 1) and (Submenu[PickM].Total <> 0) then  {fix 4.01}
  659.                        begin
  660.                            Display_Sub_Picks(PickS,0);
  661.                            PickS := pred(PickS);
  662.                            Display_Sub_Picks(PickS,1);
  663.                        end;
  664.           CursUp     : If (Submenu[PickM].Total <> 0) then
  665.                        begin
  666.                            If down then
  667.                            begin
  668.                                Display_Sub_Picks(PickS,0);
  669.                                If PickS <> 1  then
  670.                                   PickS := pred(PickS)
  671.                                else
  672.                                   PickS := Submenu[PickM].Total;
  673.                                Display_Sub_Picks(PickS,1);
  674.                            end;
  675.                        end;
  676.           EndKey    :  If (Submenu[PickM].Total <> 0) then
  677.                        begin
  678.                            If Down then
  679.                            begin
  680.                                Display_Sub_Picks(PickS,0);
  681.                                PickS := Submenu[PickM].Total;
  682.                                Display_Sub_Picks(PickS,1);
  683.                            end
  684.                            else
  685.                            begin
  686.                                Display_main_picks(PickM,0);  {clear highlight}
  687.                                PickM := ToT_Main;
  688.                                Display_main_picks(PickM,1);
  689.                            end;
  690.                        end
  691.                        else
  692.                        begin
  693.                            Display_main_picks(PickM,0);  {clear highlight}
  694.                            PickM := ToT_Main;
  695.                            Display_main_picks(PickM,1);
  696.                            If Down then
  697.                            begin
  698.                                Display_Main_Picks(PickM,2);
  699.                                Display_Sub_Menu(PickM);
  700.                            end;
  701.                        end;
  702.           HomeKey   :  If (Submenu[PickM].Total <> 0) then
  703.                        begin
  704.                            If Down then
  705.                            begin
  706.                                Display_Sub_Picks(PickS,0);
  707.                                PickS := 1;
  708.                                Display_Sub_Picks(PickS,1);
  709.                            end
  710.                            else
  711.                            begin
  712.                                Display_main_picks(PickM,0);  {clear highlight}
  713.                                PickM := 1;
  714.                                Display_main_picks(PickM,1);
  715.                            end;
  716.                        end
  717.                        else
  718.                        begin
  719.                            Display_main_picks(PickM,0);  {clear highlight}
  720.                            PickM := 1;
  721.                            Display_main_picks(PickM,1);
  722.                            If Down then
  723.                            begin
  724.                                Display_Main_Picks(PickM,2);
  725.                                Display_Sub_Menu(PickM);
  726.                            end;
  727.                        end;
  728.           end; {endcase}
  729.  Until Finished;
  730.  If PTTT.RemoveMenu Then
  731.     Restore_Screen;
  732.  Dispose_Screen;
  733.  end;  {end of main procedure Display_Menu}
  734.  
  735. begin
  736.     Horiz_Sensitivity := 4;   {cursors left and right before mouse returns}
  737.     Default_Settings;
  738. end.
  739.