<> <> <> <<>> DIRECTORY MenuSystem, PopUpMenu USING [RequestSelection], SymTab USING [Create, Delete, Fetch, Ref, Store] ; MenuSystemImpl: CEDAR MONITOR IMPORTS PopUpMenu, SymTab EXPORTS MenuSystem = BEGIN OPEN MenuSystem; MenuSystem: TYPE ~ REF MenuSystemRec; MenuSystemRec: PUBLIC TYPE ~ RECORD [ x: SymTab.Ref _ SymTab.Create[], defaultTitle: ROPE _ NIL ]; CreateMenuSystem: PUBLIC PROC RETURNS [ms: MenuSystem] ~ { RETURN [NEW[MenuSystemRec]] }; InstallMenu: PUBLIC PROC [ms: MenuSystem, menu: Menu] ~ { InstallRefMenu[ms, NEW[Menu _ menu]]; }; InstallRefMenu: PUBLIC ENTRY PROC [ms: MenuSystem, menu: REF Menu] ~ { ENABLE UNWIND => NULL; [] _ SymTab.Store[ms.x, menu.title, menu]; ms.defaultTitle _ menu.title; }; RemoveMenu: PUBLIC ENTRY PROC [ms: MenuSystem, title: ROPE] ~ { ENABLE UNWIND => NULL; [] _ SymTab.Delete[ms.x, title]; }; InstallAction: PUBLIC ENTRY PROC [ms: MenuSystem, title: ROPE, action: REF] ~ { ENABLE UNWIND => NULL; [] _ SymTab.Store[ms.x, title, action]; }; Select: PUBLIC ENTRY PROC [ms: MenuSystem, title: ROPE _ NIL] RETURNS [action: REF] ~ { ENABLE UNWIND => NULL; IF title=NIL THEN title _ ms.defaultTitle; --Left by sticky menus DO ref: REF; found: BOOLEAN; [found, ref] _ SymTab.Fetch[ms.x, title]; IF ~found THEN RETURN [title]; --Thus, if at some end node, no action has been placed in the table, we'll return the ROPE itself WITH ref SELECT FROM menu: REF Menu => { options: LIST OF ROPE _ menu.options; choice: CARDINAL _ PopUpMenu.RequestSelection[ label: menu.title, choice: options, default: 0 --Until PopUpMenu.RequestSelection fixed <> ]; IF menu.sticky THEN ms.defaultTitle _ title; IF choice=0 THEN RETURN [NIL]; --After all this, the user did nothing <> THROUGH [1..choice) DO options _ options.rest; ENDLOOP; title _ options.first; }; ENDCASE => RETURN [ref]; --Return the REF which was associated with title, but which was not a REF Menu ENDLOOP; }; CallUnderLock: PUBLIC ENTRY PROC [proc: PROC] ~ { ENABLE UNWIND => NULL; proc[]; }; END.