DEFINITION MODULE Menus; (****************************************************************) (* *) (* Displays menus on screen, allows terminal user to *) (* select from them. *) (* *) (* Programmer: P. Moylan *) (* Last edited: 14 December 1994 *) (* Status: OK *) (* *) (****************************************************************) (************************************************************************) (* *) (* NOTE: This module gives you the choice of specifying your own *) (* window in which to display the menu, or using a window which is *) (* created for you when SelectFromMenu is called. In either case, *) (* you use CreateMenu to define the menu initially, SelectFromMenu *) (* to prompt the user to choose from the menu, and DestroyMenu when *) (* you have finished using the menu. You can also control some *) (* aspects of menu behaviour by calling the optional procedures *) (* MenuColours, SetOptions, and OffEdge after calling CreateMenu. *) (* *) (* In most applications, you will want to let this module look after *) (* the screen window for you. You need to call PositionMenu to *) (* define where on the screen the menu will be displayed, but you *) (* don't need to open a window explicitly. The menu does not appear *) (* on the screen until SelectFromMenu is called, and - unless you *) (* have specified the MNoClose option - it disappears from the *) (* screen as soon as the keyboard user has made a selection. *) (* You may, if you wish, use a new call to PositionMenu before each *) (* call to SelectFromMenu, although the more common case would be to *) (* call PositionMenu just once, after the call to CreateMenu. *) (* *) (* The alternative is to open your own screen window, and to call *) (* DisplayMenu to show the menu on the screen. (This also means *) (* that DisplayMenu defines the location of the menu on the screen, *) (* so in this case PositionMenu should not be called.) After that, *) (* you call SelectFromMenu to prompt the user to choose an item. *) (* This possibility is provided for applications where, for example, *) (* you want multiple menus within the same screen window. *) (* *) (* Note for users of earlier versions of this module: the earlier *) (* distinction between Normal Mode and Special Mode is now obsolete. *) (* *) (************************************************************************) FROM Windows IMPORT (* type *) Window, Colour, RowRange, ColumnRange; TYPE Menu; (* is private *) ItemText = ARRAY ColumnRange OF CHAR; MenuColumn = CARDINAL; (* Note the dual use of the word "column". A variable of type *) (* ColumnRange refers to a horizontal screen position. But in *) (* menus we use "column" to a column of character strings, which *) (* is why we have the separate type MenuColumn. The type *) (* MenuColumn is defined primarily to make it clear which type of *) (* column is being referred to in every case. *) MenuOption = (MTitle, MNoTitle, MBorder, MNoBorder, MClose, MNoClose, MKeyBack, MNoKeyBack, MFastSelect, MNoFastSelect, MMouse, MNoMouse); MO = SET OF MenuOption; (* The options have the following meanings: *) (* MTitle Messages[0], as specified in the CreateMenu *) (* call, is used as a menu title to be displayed. *) (* MNoTitle No title is displayed, Messages[0] is ignored. *) (* MBorder The menu has a border. *) (* MNoBorder The menu has no border. *) (* MClose The window containing the menu is closed after *) (* a selection has been made. *) (* MNoClose The window containing the menu is kept open on *) (* return from SelectFromMenu (and the same window *) (* will be re-used on the next call). *) (* MKeyBack The keystroke that caused an exit from *) (* SelectFromMenu remains available to the caller, *) (* via InKey() or equivalent. *) (* MNoKeyBack On return from SelectFromMenu, the keystroke *) (* that caused the exit has been consumed. *) (* MFastSelect A menu item reached by selection key or mouse *) (* click is selected immediately. *) (* MNoFastSelect The user has to type Space or Return to select *) (* the highlighted menu item. *) (* MMouse The user may move and hide the menu with the *) (* mouse, if a mouse driver is present. *) (* MNoMouse User may click on the menu but may not move it *) (* with the mouse. *) (* Note that some of the options are mutually contradictory. This *) (* way of specifying options was chosen to make it easy to specify *) (* "no change to previously set option", e.g. if you specify *) (* neither MTitle nor MNoTitle then the behaviour of the menu with *) (* respect to the title display remains at what was already in *) (* force. If you specify contradictory options (e.g. MTitle and *) (* MNoTitle) at the same time then the result is not guaranteed to *) (* be consistent between versions of this module. *) OffEdgeOption = (stick, wrap, escape, return); (* An OffEdgeOption specifies what is to be done when the user *) (* tries to run the menu cursor off the edge of the menu. The *) (* possibilities are: *) (* stick The cursor refuses to move in that direction. *) (* wrap The cursor wraps to the opposite edge. *) (* escape Return to caller with a result of 0. *) (* return Return to caller with a result that reflects *) (* the currently highlighted item. *) (************************************************************************) PROCEDURE CreateMenu (VAR (*OUT*) M: Menu; columns: MenuColumn; VAR (*IN*) Messages: ARRAY OF ItemText; NumberOfItems: CARDINAL); (* Introduces a menu into the system, but does not display it yet. *) (* For a simple vertical menu, columns = 1. Use columns > 1 for *) (* shorter and wider menus. Messages[0] is the label to put into *) (* the menu header, if present. The remaining entries in Messages *) (* are the items displayed when the menu is put on the screen. *) (* Special case: if you specify NumberOfItems = 0 then the whole of *) (* array Messages is used. *) (* For each entry of Messages, the selection character is the *) (* character following a "\". If there is no "\", the selection *) (* character is the first character. The selection character must *) (* be alphanumeric. To disable the selection character feature, *) (* put the "\" in front of a non-alphanumeric character or put it *) (* at the end of the string. *) PROCEDURE PositionMenu (M: Menu; startline, endline: RowRange; leftcol, rightcol: ColumnRange); (* Sets the screen position and size to be used when this menu is *) (* displayed by a call to SelectFromMenu. This procedure does not *) (* actually display the menu - that doesn't happen until *) (* SelectFromMenu is called. *) PROCEDURE MenuColours (M: Menu; fore, back, hfore, hback, select: Colour); (* Set the colours for the screen display of the menu. The colours *) (* fore and back are used as the normal foreground and background *) (* colours, and the highlighted menu item is displayed in colours *) (* hfore, hback. The "select" colour is for highlighting the *) (* selection character. This procedure is optional. *) PROCEDURE SetOptions (M: Menu; options: MO); (* See the MenuOptions declaration for the possible options. This *) (* procedure is optional. If it is not called, the default options *) (* are {MTitle,MBorder,MClose,MNoKeyBack,MNoFastSelect,MMouse}. *) PROCEDURE OffEdge (M: Menu; top, bottom, left, right: OffEdgeOption); (* Sets the menu behaviour when the user runs the cursor off the *) (* edge of the menu. There is one parameter for each edge of the *) (* menu. *) (* See the OffEdgeOption type declaration for the possible options. *) PROCEDURE SelectFromMenu (M: Menu): CARDINAL; (* Displays menu M on the screen, allows terminal user to use *) (* cursor keys to move about the menu and the ENTER key to select *) (* an item. (The space bar is also accepted, as an alternative to *) (* the ENTER key, to select an item.) An item may also be selected *) (* by typing its initial letter, followed by space or ENTER. *) (* Returns the number of the item which was selected. *) (* (Item numbers start from 1). An answer of 0 indicates that the *) (* user typed the ESC key to return without selecting anything. *) PROCEDURE DestroyMenu (M: Menu); (* Removes a menu from the system, freeing up the space it used. *) (************************************************************************) (* ALTERNATIVE DISPLAY PROCEDURE *) (************************************************************************) PROCEDURE DisplayMenu (w: Window; M: Menu; rows, columns, initialvalue: CARDINAL); (* Displays menu M at the current cursor position in window w, *) (* with initialvalue specifying a field to highlight. The space *) (* reserved on the screen is "rows" screen rows in height and *) (* "columns" character positions wide. (The remainder of window w *) (* may of course be used for other purposes, including other *) (* menus.) When SelectFromMenu is called, it will use window w. *) END Menus.