<> <> <> <<>> DIRECTORY PopUpMenu USING [RequestSelection], Rope USING [Cat, Equal, Substr], SymTab USING [Create, Fetch, Insert, Ref], TajoMenus ; TajoMenusImpl: CEDAR PROGRAM IMPORTS PopUpMenu, Rope, SymTab EXPORTS TajoMenus = BEGIN OPEN TajoMenus; TajoSystem: TYPE ~ REF TajoSystemRec; TajoSystemRec: PUBLIC TYPE ~ RECORD [ x: SymTab.Ref _ SymTab.Create[] ]; PopUp: TYPE ~ REF PopUpRec; PopUpRec: TYPE ~ RECORD [ list: LIST OF ROPE _ NIL, action: SEQUENCE len:NAT OF REF ]; DuplicateName: PUBLIC ERROR ~ CODE; filler: ROPE ~ " "; --Lots of spaces CreateTajoSystem: PUBLIC PROC [menus: LIST OF TajoMenu] RETURNS [ts: TajoSystem] ~ { ring: LIST OF ROPE _ LIST[menus.first.title]; ringTail: LIST OF ROPE _ ring; nMenus: CARDINAL _ 0; --Number of menus ts _ NEW[TajoSystemRec]; <> defaultTitle _ menus.first.title; <> FOR each: LIST OF TajoMenu _ menus, each.rest UNTIL each=NIL DO nMenus _ nMenus + 1; ENDLOOP; <> FOR each: LIST OF TajoMenu _ menus.rest, each.rest UNTIL each=NIL DO ringTail _ ringTail.rest _ LIST[each.first.title]; ENDLOOP; ringTail.rest _ ring; --Close the ring <> FOR eachMenu: LIST OF TajoMenu _ menus, eachMenu.rest UNTIL eachMenu=NIL DO AppendToPopUp: PROC [r: ROPE] ~ { tail _ tail.rest _ LIST[r]; }; optionList: LIST OF ROPE _ LIST["Dummy"]; --The actual list of rope for this menu tail: LIST OF ROPE _ optionList; --Always points to tail of optionList popUp: PopUp; nEntries: CARDINAL _ 0; --Will contain the number of entries exclusive to this menu tempEntry: LIST OF TajoEntry _ eachMenu.first.options; <> FOR eachEntry: LIST OF TajoEntry _ eachMenu.first.options, eachEntry.rest UNTIL eachEntry=NIL DO nEntries _ nEntries+1; ENDLOOP; <> popUp _ NEW[PopUpRec[nMenus+nEntries+1]]; popUp.action[0] _ NIL; <> UNTIL Rope.Equal[ringTail.first, eachMenu.first.title] DO --Point ringTail at our title ringTail _ ringTail.rest; ENDLOOP; FOR index: CARDINAL IN [1..nMenus] DO rope: ROPE; ringTail _ ringTail.rest; --Set up title name rope _ Rope.Cat[Rope.Substr[base: filler, len: (nMenus-index)*2], ringTail.first]; IF index=nMenus THEN rope _ Rope.Cat[rope, "-----------"]; popUp.action[index] _ ringTail.first; AppendToPopUp[rope]; ENDLOOP; <> FOR index: CARDINAL IN [1..nEntries] DO ref: REF _ IF tempEntry.first.action=NIL THEN tempEntry.first.rope ELSE tempEntry.first.action; AppendToPopUp[tempEntry.first.rope]; popUp.action[nMenus+index] _ ref; tempEntry _ tempEntry.rest; ENDLOOP; <> popUp.list _ optionList.rest; IF ~SymTab.Insert[ts.x, eachMenu.first.title, popUp] THEN ERROR DuplicateName[]; ENDLOOP; }; defaultTitle: ROPE _ NIL; --Remembers last title brought up Select: PUBLIC PROC [ts: TajoSystem, title: ROPE _ NIL] RETURNS [action: REF] ~ { IF title=NIL THEN title _ defaultTitle; DO --This is an iterative process popUp: PopUp; found: BOOLEAN; ref: REF; choice: CARDINAL; [found, ref] _ SymTab.Fetch[ts.x, title]; IF ~found THEN RETURN [title]; --This is where ROPEs are returned from <> defaultTitle _ title; --Remember this menu as the new default popUp _ NARROW[ref]; choice _ PopUpMenu.RequestSelection[choice: popUp.list]; action _ popUp.action[choice]; WITH action SELECT FROM r: ROPE => title _ r; ENDCASE => RETURN [action]; ENDLOOP; }; END.