home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / menu / pulldwn / pulldown.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1988-09-07  |  10.4 KB  |  585 lines

  1. {$R-}    {Range checking off}
  2. {$B+}    {Boolean complete evaluation on}
  3. {$S+}    {Stack checking on}
  4. {$I+}    {I/O checking on}
  5. {$N-}    {No numeric coprocessor}
  6. {$M 65500,16384,655360} {Turbo 3 default stack and heap}
  7.  
  8.  
  9. Program PullDownMenus;
  10. uses dos,crt,turbo3;
  11. {
  12.  
  13.  
  14. Pull Down Menus in Turbo Pascal
  15.  
  16.       by
  17.  
  18.   Kurt M. Gutzmann            UPDATED TO TURBO PASCAL VERSION 4.0
  19.  
  20.                               BY  MARK K. MATHEWS
  21.  
  22. This is a set of routines for constructing a Xerox style
  23. cum Macintosh user interface for Turbo Pascal programs.
  24.  
  25. Menus are loaded from a menu data file at start up.
  26.  
  27. The procedure RunMenus is a skeleton with a CASE statement
  28. filled by the programmer to drive his particular menu
  29. tree.
  30.  
  31. A sample menu data file and a fleshing out of the RunMenus
  32. procedure is done here as an example of how to use PullDowns.
  33.  
  34. }
  35.  
  36.  
  37.  
  38. const
  39.  
  40.        MaxItems=10; {Max Items on a Menu Bar}
  41.        MaxMenus=10; {Max Menus}
  42.        Width=11;    {Width of Pull Down Fields}
  43.  
  44. Type
  45.  
  46.    VideoMode =(Norm,Rev,Hi,Und,RevHi,Blink,BlinkHi,RevBlink,RevBlinkHi);
  47.    MaxString = String[255];
  48.    stringW = string[Width];
  49.  
  50.  
  51.    ProtoMenu = record
  52.            NumEntry :array[0..MaxItems] of integer;
  53.            Menu:array[0..MaxItems] of array[0..MaxItems] of stringW;
  54.            MenuName:stringW;
  55.            NoItems:integer;
  56.            end;
  57.  
  58.    MenuPtr = ^ProtoMenu;
  59.  
  60.    MenuAry =  array[1..MaxMenus] of MenuPtr;
  61.  
  62. var
  63.  
  64. NumMenus:integer;
  65. Menus:MenuAry;
  66. exit:boolean;
  67. VideoSeg:word;{points to $B000 or $B800  for color or mono}
  68. botbox:maxstring;
  69.  
  70.  
  71. function ColorMonitor:boolean;
  72. {returns TRUE if a Color monitor is installed}
  73. var regs:registers;
  74.    al:integer;
  75. begin
  76. regs.ax:=15 shl 8;
  77. intr($10,regs);
  78. al:=Lo(regs.ax);
  79. if al=$7 then ColorMonitor:=false else ColorMonitor:=true;
  80. end;
  81.  
  82.  
  83. Procedure SetVideoSeg;
  84. begin
  85. if colormonitor then VideoSeg:=$B800 else VideoSeg:=$B000
  86. end;
  87.  
  88.  
  89. Procedure SetCursor(HiScan,LowScan:byte);
  90. var regs:registers;
  91. begin
  92. regs.ax:=1 shl 8;
  93. regs.cx:=HiScan shl 8 + LowScan;
  94. intr($10,regs);
  95. end;
  96.  
  97.  
  98. Procedure CursorNormal;
  99. begin
  100. if ColorMonitor then SetCursor(6,7) else  SetCursor(10,11);
  101. end;
  102.  
  103.  
  104. Procedure CursorBlock;
  105. begin
  106. if ColorMonitor then SetCursor(1,7) else  SetCursor(1,14);
  107. end;
  108.  
  109.  
  110. Procedure CursorOff;
  111. begin
  112. SetCursor(31,0);
  113. end;
  114.  
  115.  
  116.  
  117.  
  118. procedure GetKb(var chcode,extcode:integer);
  119.  
  120. (*Obtains the character and extended codes of a struck key. The codes are
  121.  removed from the buffer. This procedure will wait for a keystrike if the
  122.  buffer is empty.*)
  123.  
  124. var
  125.   regs:Registers;
  126.  
  127. begin
  128.   regs.ax := $0000;
  129.   intr($16,regs);
  130.   extcode := regs.ax shr 8;   ; (*extended code is AH*)
  131.   chcode := regs.ax and $00FF;    (*character code is AL*)
  132. end;
  133.  
  134.  
  135. function inchar(var ch:char;var ex:integer):boolean;{true if ASCII char}
  136. {Returns char and extended code from keyboard}
  137. var chcode,excode:integer;
  138. begin
  139. getkb(chcode,ex);
  140. if chcode=0 then
  141.     begin
  142.     inchar:=false;
  143.     ch:=chr(ex);
  144.     end
  145. else
  146.     begin
  147.     ch:=chr(chcode);
  148.     inchar:=true;
  149.     if ex<>0 then
  150.       if chcode in [8,13,9,27] then
  151.      begin
  152.      ex:=chcode;
  153.      inchar:=false;
  154.      end;
  155.     end;
  156. end;{inchar}
  157.  
  158.  
  159. procedure ReadAt(x,y,nchars:integer;var TheString:maxstring);
  160. {Not Used here, but may be useful to other programs,
  161.  performs read from video buffer}
  162. Var
  163.   i,j:integer;
  164.   Attribute:Byte;
  165.  
  166. Begin{1}
  167. TheString:='';
  168.    j := 2*((y-1)*80+(x-1));{offset in video buffer}
  169.    i:=1;
  170.    While (i<=nchars) do
  171.        begin{3}
  172.        TheString:=TheString+chr(ord(Mem[VideoSeg:j]));
  173.        i:=i+1;
  174.        j:=j+2;
  175.        end;{3}
  176. end;{1 of ReadAt}
  177.  
  178.  
  179. procedure WriteAt(x,y:integer;WriteMode:VideoMode;TheString:maxstring);
  180. {Memory Mapped write}
  181. Var
  182.   i,j,k:integer;
  183.   Attribute:Byte;
  184.  
  185. Begin{1}
  186.   case WriteMode of {change these for color terminals}
  187.    Norm:       Attribute := $07;
  188.    Rev:        Attribute := $70;
  189.    Hi:           Attribute := $0F;
  190.    Und:        Attribute := $01;
  191.    RevHi:      Attribute := $78;
  192.    Blink:      Attribute := $87;
  193.    BlinkHi:    Attribute := $8F;
  194.    RevBlink:   Attribute := $F0;
  195.    RevBlinkHi: Attribute := $F8;
  196.    ELSE        Attribute := $07;{Normal}
  197.    end;
  198.  
  199.  
  200.    j := 2*((y-1)*80+(x-1));{offset in video buffer}
  201.    i:=1;
  202.    k:=length(thestring);
  203.    While i<=k do
  204.        begin
  205.        Mem[VideoSeg : j] := Byte(TheString[i]);
  206.        Mem[VideoSeg : (j+1)] := Attribute;
  207.        i:=i+1;
  208.        j:=j+2;
  209.        end;
  210. end;{1 of WriteAt}
  211.  
  212.  
  213.  
  214. Procedure LoadMenus(var MenuList:MenuAry);
  215. {loads the menu data file}
  216. var i,j,k:integer;
  217.     f:text;
  218.     s:maxstring;
  219.  
  220. Procedure GetAMenu(var M:MenuPtr);
  221. label 99;
  222. var i,j,k:integer;
  223. begin
  224. i:=-1;
  225. j:=0;
  226. { s has been primed }
  227. M^.MenuName:=s;
  228. readln(f,s);
  229. s:=s+'            ';
  230. while (s[1]<>'*') and (not eof(f)) do
  231.    begin
  232.  
  233.    if s[1]<>' ' then
  234.      begin
  235.      if i>=0 then M^.NumEntry[i]:=j;
  236.      i:=i+1;
  237.      M^.Menu[i,0]:=s;
  238.      j:=0;
  239.      end
  240.  
  241.    else
  242.      if s[1]<>'*' then
  243.        begin
  244.        j:=j+1;
  245.        delete(s,1,1);
  246.        M^.Menu[i,j]:=s;
  247.        end
  248.      else goto 99;
  249.  
  250.  
  251.   readln(f,s);
  252.   s:=s+'            ';
  253.  
  254.   end;
  255.  
  256. 99:
  257. M^.NumEntry[i]:=j;
  258. M^.NoItems:=i;
  259.  
  260. end;{GetAMenu}
  261.  
  262. begin{Load}
  263.  
  264. assign(f,'men2.dat'); {alter name for application}
  265. reset(f);
  266.  
  267. i:=0;
  268. readln(f,s);
  269.  
  270. while not eof(f) do
  271.    begin
  272.    i:=i+1;
  273.    New(Menus[i]);
  274.    GetAMenu(Menus[i]);
  275.    end;
  276. NumMenus:=i;
  277.  
  278. close(f);
  279.  
  280. {some other initialization here}
  281.  
  282. botbox:='╚';
  283. for i:=1 to Width do botbox:=botbox+'═';
  284. botbox:=botbox+'╝';
  285.  
  286. end;{LoadMenu}
  287.  
  288.  
  289.  
  290.  
  291. procedure DoMenu(var itemsel,entrysel:integer;M:MenuPtr);
  292.  
  293. {this runs a menu, reads keys etc,}
  294. {itemsel and entrysel are returned}
  295.  
  296.  
  297. type
  298.    setofkeys=set of 0..132;
  299.  
  300. var
  301.    chc,ex:integer;
  302.    ch:char;
  303.    validkeys:setofkeys;
  304.    asc,selection:boolean;
  305.    item,entry:integer;
  306.    s1,s2:maxstring;
  307.  
  308.  
  309. Procedure PaintMenuBar;
  310. var
  311. i,sx:integer;
  312. begin
  313.  
  314. clrscr;
  315.  
  316. writeat(1,1,rev,
  317. '                                                                                ');
  318. for i:=0 to M^.NoItems do
  319.    begin
  320.    sx:=2+i*Width;
  321.    writeat(sx,1,rev,M^.Menu[i,0]);
  322.    end;
  323. end;{PaintMenuBar}
  324.  
  325.  
  326. Procedure Bright(ix,ij:integer);
  327. var sx:integer;
  328.     s:maxstring;
  329. begin
  330. s:=M^.Menu[ix,ij];
  331. sx:=ix*Width+1;
  332. writeat(sx+1,ij+1,Rev,s)
  333. end;
  334.  
  335.  
  336.  
  337. Procedure UnderScore(ix,ij:integer);
  338. var sx:integer;
  339.     s:maxstring;
  340. begin
  341. sx:=ix*Width+1;
  342. s:=M^.Menu[ix,ij];
  343. writeat(sx+1,ij+1,Und,s)
  344. end;
  345.  
  346.  
  347. Procedure Normal(ix,ij:integer);
  348. var sx:integer;
  349.     s:maxstring;
  350. begin
  351. sx:=ix*Width+1;
  352. if ij=0 then if sx<1 then sx:=1;
  353. s:=M^.Menu[ix,ij];
  354. writeat(sx+1,ij+1,Norm,s);
  355. end;
  356.  
  357.  
  358.  
  359. Procedure PushUp(ix:integer);
  360. var sx,i:integer;
  361. begin
  362. sx:=ix*Width+1;
  363. if sx<1 then sx:=1;
  364. for i:=1 to M^.NumEntry[ix]+1 do
  365.    writeat(sx,i+1,Norm,'             ');
  366. end;
  367.  
  368. Procedure PullDown(ix:integer);
  369. const
  370.  
  371.     l:maxstring='║';
  372.     r:maxstring='║';
  373. var sx:integer;
  374.     s:maxstring;
  375.     j:integer;
  376. begin
  377. sx:=ix*Width+1;
  378. for j:=1 to M^.NumEntry[ix] do
  379.     begin
  380.     s:=l+M^.Menu[ix,j]+r;
  381.     writeat(sx,j+1,Norm,s);
  382.     end;
  383. if M^.NumEntry[ix]>0 then writeat(sx,M^.NumEntry[ix]+2,Norm,botbox);
  384. end;
  385.  
  386.  
  387. begin {DoMenu}
  388.  
  389. CursorOff;
  390.  
  391. validkeys:=[13,15,75,9,77,80,72,27];
  392.  
  393. entry:=1;
  394. item:=0;
  395. PaintMenuBar;
  396. PullDown(0);
  397. Bright(item,entry);
  398.  
  399. selection:=FALSE;
  400.  
  401. while not selection do
  402.    begin
  403.  
  404.    asc:= Inchar(ch,ex);
  405.  
  406.    if ex=0 then {Ctl-Brk hit}
  407.       begin
  408.       CursorNormal;
  409.       clrscr;
  410.       halt;
  411.       end;
  412.  
  413.    if not asc then
  414.    case ex{tended code} of
  415.  
  416.       13:{CR}
  417.          selection:=TRUE;
  418.  
  419.  
  420.       15, 75:{lefttab,left}
  421.          if item>0 then
  422.            begin
  423.            item:=item-1;
  424.            entry:=1;
  425.            pushup(item+1);
  426.            pulldown(item);
  427.            Bright(item,entry);
  428.            end;
  429.  
  430.        9, 77:{tab,right}
  431.          if item<M^.NoItems then
  432.            begin
  433.            item:=item+1;
  434.            entry:=1;
  435.            pushup(item-1);
  436.            pulldown(item);
  437.            entry:=1;
  438.            Bright(item,1);
  439.            end;
  440.  
  441.       80:{down}
  442.          begin
  443.          if entry<M^.NumEntry[item] then
  444.         begin
  445.         entry:=entry+1;
  446.         Normal(item,entry-1);
  447.         Bright(item,entry);
  448.         end
  449.          else
  450.            begin
  451.            entry:=1;
  452.            Normal(item,M^.NumEntry[item]);
  453.            Bright(item,entry);
  454.            end;
  455.          end;
  456.  
  457.       72:{up}
  458.          begin
  459.          if entry>1 then
  460.         begin
  461.         entry:=entry-1;
  462.         Normal(item,entry+1);
  463.         Bright(item,entry);
  464.         end
  465.          else
  466.            begin
  467.            entry:=M^.NumEntry[item];
  468.            Normal(item,1);
  469.            Bright(item,entry);
  470.            end;
  471.          end;
  472.       27:{Esc}
  473.            begin
  474.            selection:=TRUE;
  475.            item:=0;
  476.            entry:=0;
  477.            end;
  478.  
  479.       end;{case}
  480.  
  481.    end;{while not selection}
  482. itemsel:=item;
  483. entrysel:=entry;
  484.  
  485. CursorNormal;
  486.  
  487. end;{DoMenu}
  488.  
  489.  
  490.  
  491. Procedure RunMenus;
  492.  
  493. {  Skeleton Procedure that you flesh out to run your menu tree.
  494.  
  495.    DoMenu returns item=menu bar item  and entry=entry underneath the
  496.    item  as the selection. Zeros are returned for the escape key.
  497.  
  498.    Compose the CASE index by 100* Active + 10*Item + Entry .
  499.  
  500.     So Menu 2 Item 3 Entry 4 has an index of 234.
  501.  
  502.   Fill in the Case statement to accomodate the returned indices.
  503.  
  504. }
  505.  
  506. var
  507. exit:boolean;
  508. ch:char;
  509. Active,index,item,entry:integer;
  510.  
  511. begin {RunMenu}
  512.  
  513. exit:=FALSE;
  514. Active:=1;
  515.  
  516. while not exit do
  517.   begin
  518.  
  519.   DoMenu(item,entry,Menus[Active]);
  520.  
  521.   index:=Active*100+item*10+entry;
  522.  
  523.   case index of {fill this in appropriately with structure}
  524.  
  525.   100:exit:=TRUE;
  526.  
  527.   101..104,201..204,301..304: begin
  528.         gotoxy(10,10);
  529.         writeln(' This is for Information Only');
  530.         delay(5000);
  531.         end;
  532.  
  533.   111 : begin
  534.     Active:=2; {select next Menu}
  535.     end;
  536.  
  537.   112 : begin
  538.     Active:=3; {select next Menu}
  539.     end;
  540.  
  541.   121,122,211,212 : begin
  542.         gotoxy(10,10);
  543.         writeln(' These Entries Have No Function.');
  544.         delay(5000);
  545.         end;
  546.  
  547.  
  548.   131,222: begin
  549.        gotoxy(10,10);
  550.        write(' Do You Really Want to Quit? ');
  551.        readln(ch);
  552.        if ch in ['Y','y'] then exit:=TRUE;
  553.        end;
  554.  
  555.  
  556.   221,321,200,300:Active:=1;
  557.  
  558.  
  559.   311:begin
  560.        gotoxy(10,10);
  561.        write(' Caesar slowly sipped his snifter,');
  562.        writeln(' seized his knees and sneezed.');
  563.        delay(5000);
  564.        end;
  565.  
  566.    312:begin
  567.        gotoxy(10,10);
  568.        writeln(' Peter Piper picked a peck of pickled peppers.');
  569.        delay(5000);
  570.        end;
  571.    end;{case}
  572.  
  573.   end;
  574. end;{RunMenus}
  575.  
  576. begin{main}
  577.  
  578. CursorNormal;
  579.  
  580. SetVideoSeg;
  581. LoadMenus(Menus);
  582. RunMenus;
  583. clrscr;
  584. end.
  585.