home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / PJ8_3.ZIP / UMENU.PAS < prev    next >
Pascal/Delphi Source File  |  1990-02-15  |  6KB  |  225 lines

  1. (* umenu.pas -- (c) 1989 by Tom Swan *)
  2.  
  3. unit umenu;
  4.  
  5. interface 
  6.  
  7. uses crt, ukeys, uitem, ucmds, ulist;
  8.  
  9. type
  10.  
  11.    menuPtr = ^menu;
  12.    menu = object( list )
  13.       menuRow, menuCol : word;   { Menu command-line location }
  14.       menuTitle : ^string;       { Menu name string }
  15.       menuDisplay : ^string;     { Menu commands string }
  16.       menuAttr : word;           { Display attribute }
  17.  
  18.       constructor init( col, row : word; title : string; attr : word );
  19.       destructor done; virtual;
  20.       function menuStr : string;
  21.       function getMenuAttr : Word;
  22.       function getMenuRow : Word;
  23.       function getMenuCol : Word;
  24.  
  25.       procedure displayMenu; virtual;
  26.       procedure beforeCommand; virtual;
  27.       procedure afterCommand; virtual;
  28.       procedure performCommands; virtual;
  29.  
  30. { ----- Replacement methods inherited from list object. }
  31.  
  32.       procedure insertItem( ip : ItemPtr ); virtual;
  33.       procedure removeItem( ip : ItemPtr ); virtual;
  34.  
  35.    end;
  36.  
  37. implementation
  38.  
  39. const
  40.  
  41.    ESC = #27;     { ASCII escape char }
  42.  
  43. { ----- Initialize a new menu command list. }
  44.  
  45. constructor menu.init( col, row : word; title : string; attr : word );
  46. begin
  47.    menuRow := row;
  48.    menuCol := col;
  49.    menuAttr := attr;
  50.    menuDisplay := nil;  { Created by menu.menuStr }
  51.    getMem( menuTitle, length( title ) + 1 );
  52.    if menuTitle = nil then
  53.    begin
  54.       fail;
  55.       done;
  56.    end else
  57.       menuTitle^ := title;
  58.    list.init;
  59. end;
  60.  
  61. { ----- Dispose of a menu command list. }
  62.  
  63. destructor menu.done;
  64. begin
  65.    if menuTitle <> nil then
  66.    begin
  67.       freeMem( menuTitle, length( menuTitle^ ) + 1 );
  68.       menuTitle := nil;
  69.    end;
  70.    if menuDisplay <> nil then
  71.    begin
  72.       freeMem( menuDisplay, length( menuDisplay^ ) + 1 );
  73.       menuDisplay := nil;
  74.    end;
  75.    list.done;
  76. end;
  77.  
  78. { ----- Create and/or return current menu string. }
  79.  
  80. function menu.menuStr : string;
  81. var
  82.    s1, s2 : string[80];
  83. begin
  84.    if menuDisplay = nil then
  85.    begin
  86.       s1 := '';          { Null string }
  87.       if not listEmpty then
  88.       begin
  89.          resetList;
  90.          repeat
  91.             s2 := commandPtr( currentItem )^.getstring;
  92.             if length( s2 ) > 0
  93.                then s1 := s1 + ' ' + s2;  { Add command to s1 }
  94.             nextItem;
  95.          until atHeadOfList;
  96.       end;
  97.       getMem( menuDisplay, length( s1 ) + 1 );
  98.       if menuDisplay <> nil
  99.          then menuDisplay^ := s1;
  100.    end else
  101.       s1 := menuDisplay^;
  102.    if menuTitle <> nil
  103.       then s1 := menuTitle^ + s1;
  104.    menuStr := s1;
  105. end;
  106.  
  107. { ----- Return menu attribute word. }
  108.  
  109. function menu.getMenuAttr : Word;
  110. begin
  111.    getMenuAttr := menuAttr;
  112. end;
  113.  
  114. { ----- Return menu row. }
  115.  
  116. function menu.getMenuRow : Word;
  117. begin
  118.    getMenuRow := menuRow;
  119. end;
  120.  
  121. { ----- Return menu column. }
  122.  
  123. function menu.getMenuCol : Word;
  124. begin
  125.    getMenuCol := menuCol;
  126. end;
  127.  
  128. { ----- Display the menu name and command strings. }
  129.  
  130. procedure menu.displayMenu;
  131. var
  132.    oldAttr : word;   { For saving current attribute }
  133. begin
  134.    oldAttr := textAttr;
  135.    textAttr := menuAttr;
  136.    gotoxy( menuCol, menuRow );
  137.    write( menuStr );
  138.    clreol;
  139.    textAttr := oldAttr;
  140. end;
  141.  
  142. { ----- Called at the top of the menu.performCommands repeat loop,
  143. providing host programs a way to hook into the keyboard polling loop.
  144. Optionally replaced by host program's menu object. }
  145.  
  146. procedure menu.beforeCommand;
  147. begin
  148. end;
  149.  
  150. { ----- Called after menu.duringCommand. Optionally replaced by host
  151. program's menu object. Note: you may use this procedure to modify the
  152. menu list, allowing one command to alter the availability of other
  153. commands. }
  154.  
  155. procedure menu.afterCommand;
  156. begin
  157.    displayMenu;   { Usually a good idea }
  158. end;
  159.  
  160. { ----- Process commands in menu list. Guaranteed to return upon
  161. pressing <Esc>. Repeatedly calls beforeCommand while polling keyboard
  162. for input. Calls afterCommand after processing a selected command in
  163. the menu list. }
  164.  
  165. procedure menu.performCommands;
  166. var
  167.    ch : char;
  168. begin
  169.    displayMenu;         { Display menu name and commands }
  170.    ch := chr( 0 );      { Initialize ch to null }
  171.    repeat
  172.       beforeCommand;       { Activate host polling hook }
  173.       if keyWaiting then
  174.       begin
  175.          ch := upcase( getKey );
  176.          if ch <> ESC then
  177.          begin
  178.             resetList;
  179.             if not listEmpty then
  180.             repeat
  181.                if ch = commandPtr( currentItem )^.getcmdCh then
  182.                begin
  183.                   currentItem^.processItem;  { Perform command }
  184.                   resetList;                 { Force loop to end }
  185.                   afterCommand;              { Host post-cmd hook }
  186.                end else
  187.                   nextItem;
  188.             until atHeadOfList;
  189.          end;
  190.       end;
  191.    until ch = ESC;      { Until <Esc> pressed or forced }
  192. end;
  193.  
  194. { ----- Insert a new command into menu. Parameter ip must address a
  195. command object as defined in ucmds.pas. Also dispose of the current
  196. menu display string if neccessary, as these are invalid after new
  197. commands are added to the list. }
  198.  
  199. procedure menu.insertItem( ip : ItemPtr );
  200. begin
  201.    if menuDisplay <> nil then
  202.    begin
  203.       freeMem( menuDisplay, length( menuDisplay^ ) + 1 );
  204.       menuDisplay := nil;
  205.    end;
  206.    list.insertItem( ip );
  207. end;
  208.  
  209. { ----- Delete a single command from the menu.  Parameter ip should
  210. address a command object (or a descendant). Also dispose the current
  211. menu display string. }
  212.  
  213. procedure menu.removeItem( ip : ItemPtr );
  214. begin
  215.    if menuDisplay <> nil then
  216.    begin
  217.       freeMem( menuDisplay, length( menuDisplay^ ) + 1 );
  218.       menuDisplay := nil;
  219.    end;
  220.    list.removeItem( ip );
  221. end;
  222.  
  223. end.
  224.  
  225.