tips:revmedia:r92

Questions about Menus

Published ByDateVersionKnowledge LevelKeywords
Revelation Technologies19 SEP 19912.1XEXPERTPULLDOWN, MENUS, SEARCH, HELP, SECURITY, MENU, LAYOUT, OPTIONS

This technical bulletin consolidates the answers to a variety of questions concerning menus that have arisen on the technical support lines.

When you press [F1] at a menu, the menu processors for both AREV and PULLDOWN style menus look for a help record with a key of:

MW*menu_name

In Version 2.1, the system will look for this record first in the HELP file, then in SYS.HELP. In earlier versions, the menu processor will look only in SYS.HELP for a help record. For example, the help for a menu called MYAPP_MAIN would be in the HELP or SYS.HELP file under the name MW*MYAPP_MAIN. If there is no such record, the menu processor formats the existing menu choices into a help message and displays that as the default.

The menu processor takes no heed of any information stored in the menu template record itself regarding where help is available. If you working with Version 2.03 or earlier, you should moreover take note that the menu processors do not look in HELP, only in SYS.HELP, forcing you to store application-level information in a system file.

It is possible to modify a menu on the fly as part of an application. For example, a user may elect as part of your application to change some sort of configuration parameters. This in turn might mean that certain menu options in your applications may no longer apply and should disappear from that menu.

It is easy enough to change a menu template using an R/BASIC program (see Figure 1 for the layout of menu templates). However, if the menu has already been displayed during this session, your change will not take immediate effect because menus are buffered in memory.

You should therefore call the subroutine TEMPLATE.FLUSH after modifying a menu. This will empty the menu (and window) buffer, so that the next time the menu is called it will be re-read from disk. The subroutine takes no arguments, so the syntax is simple:

CALL TEMPLATE.FLUSH()

If the menu you are modifying is actually being displayed at the time you make the modification, it will not be altered until there is some reason to exit and then re-enter the menu.

The subroutine TEMPLATE.FLUSH also does not alter the information stored in memory about the last selection made from a menu. However, you can change this yourself (see "'Stickum' Information" below).

The current menu style is stored in two places: the environment (@ENVIRON.SET<E.MSTYLE>) and in a labelled common area called /%MENUSTYLE%/ STYLE. In the latter example the label is %MENUSTYLE%; you can call the common variable anything you like.

Note: The label names and configurations of labelled common areas are liable to change in subsequent releases. The information provided here is current as of Version 2.10 of Advanced Revelation.

The Environment array stores the menu style name in its "pure" form. For example, if you are using AREV-style menus, teh environment will simply contain the word "AREV". The labelled common variable, on the other hand, will contain the name of the menu style with the suffix "_WINUS".

To change menu styles you must change the style in both locations. Pimacy is given to the current environment setting, and WINUS will resynchronize the labelled common variable to match the environment. However, it won't do this Ä in fact, it will ignore the change Ä if any menus are currently active.

A sample program to change menu styles on-the-fly is illustrated in Figure 2. The program changes the style in both locations. In order to make sure the change is reflected in all menus yet to be displayed, it also flushes the templates buffer so that these are recalculated before display.

There are a few limitations. First, any menu already on the screen will not change, because it is currently active and WINUS will not attempt to recalculate its style when returning to it. Second, dynamic changes do not work for menus dependent on the current anchored menu. That is, if the current menu is anchored, a change in menu style won't affect any non-anchored menus called directly from that menu.

The system maintains two labelled common variables that contain information about the last selection made from all menus that have displayed. This gives menus their "stickum", i.e. their ability to "remember" that last selection you made.

Note: The label names and configurations of labelled common areas are liable to change in subsequent releases. The information provided here is current as of Version 2.10 of Advanced Revelation.

You can alter the contents of these variables. For example, you might set values in these variables in order to pre-select options on a menu. You might also alter the variables to clear the stickum. This is useful, for instance, if you are running captured keystroke sequences using first-letter selections and need to guarantee that menus always appear with the same options highlighted.

The labelled common area is called /LCMENUS/. There are two variables:

COMMON /LCMENUS/ MENUS, POINTERS

Both variables are dynamic arrays (@FM-delimited). MENUS is a list of all menus that you have displayed during this session. POINTERS is an associated array of position information for each of these menus.

Each field in POINTERS is a three-value array. The first two elements of the pointer array are only relevant for the AREV menu style, but are maintained by the PULLDOWN style for consistency. The layout is:

<1,1>Column selected, beginning with 0.
<1,2>Row, beginning with 1.
<1,3>Absolute option number.

For example, if you had chosen the sequence Tools-Files-Indexing, the pointer array for the FILES menu would contain 2, 2, 8 (value-mark delimited) meaning respectively 3rd column (starting at 0), 2nd row, and 8th selection on the menu.

To alter the contents of the pointer array, you should first locate the appropriate menu name in the MENUS variable, and then alter the corresponding POINTER values. Here is a brief example that shows you might choose the first selection of the MAIN menu:

COMMON /LCMENUS/ MENUS,POINTERS

LOCATE 'MAIN' IN MENUS USING --> @FM SETTING POS THEN
  PTR = POINTERS<POS>
  PTR<1,1> = 0 ; col 0
  PTR<1,2> = 1 ; row 1
  PTR<1,3> = 1 ; selection 1
  POINTERS<POS> = PTR
END ELSE
  MENUS<-1> = "MAIN"
  PTR = 0:@VM:1:@VM:1
  POINTERS<-1> = PTR
END

If you pre-select a menu option, it will be your responsibility to synchronize the position (column and row) with the absolute selection value; if you introduce a mismatch between the two, the menu selection will display, but at the wrong location in the menu.

If you find that your application uses up memory as it proceeds, you might be able to resolve this problem at the menu level. As a rule, you should not hang 'S' codes from your application's main menu.

The main menu acts as a main program, and if you call subroutines from it using the 'S' code and command, these subroutines will remain loaded until the main program that called them – your application's main menu – terminates with a STOP statement. This may never happen during any given session, with the result that every subroutine you've called remains loaded, using up memory and variable space.

If you must call subroutines from a menu, you have two options. The first is to make the subroutine EXPENDABLE so that it will be cleared from memory when it terminates. An alternative is to insert a main program between the menu and the subroutine, so that the subroutine will terminate when the intermediate main program terminates (see Technical Bulletin #1 for more details on managing subroutines).

When you use a menu, you can press individual letters to jump directly to the selection(s) that start with that letter. By default (i.e., as constructed by the MakeMenu window), these letters will always be the first letters of the selections.

You can create a custom list of active letters. For example, you might construct a menu with options such as these:

Define
deLete
deTach
diCtionary

In this example, the assumption is that the selections can be accessed using the letters D, L, T, and C.

To customize the list of active letters, modify the menu template using the editor. Change field 10 to modify the active letters, and field 3 to modify the selections (e.g. to signify the correct active keys).

Note: Your changes will be overridden if you use the MakeMenu window to make further changes to the menu.

Although it seems clear (based on DICT.MENUS) that places have been allocated within the menu template for security features, these have never been implemented. If you wish to have security in menus, therefore, you must implement it yourself. The range of strategies available is wide, including, at the extreme end, writing your own menu system.

If your requirements for security are relatively modest, you can easily add a simple security system. This consists of a master security program that checks for a password for each menu option, prompts for it, and returns to the menu if the password is not provided. Code for such a routine appears in Figure 2.

The code as illustrated requires that you maintain (manually) an associated multivalued field of passwords in field 15 of the menu template record to correspond to the selections. You also need to store the menu name in field 16 of the template, so that it is loaded into @TUTOR when the menu displays.

To activate the program, use stacked codes and commands – first call the menu security routine, then the actual code and command to execute. For example, if you wanted to add menu security to a window called from a menu, the code for that selection would be S;W (subroutine, then window), and the command would be MENU.SEC;MYWINDOW.

This type of security is relatively easy to circumvent because the passwords as well as the call to the security system are accessible right in the template. Nonetheless, it can afford a measure of protection in applications where users may not be sophisticated enough to get access to the menu templates.

If you press [F2] while in a menu, you will see a popup of all available menus. Developers often wish to disable this facility.

The [F2] key is automatically disabled if you disable TCL in the General environment window. If using this global environment setting is impractical, however, you can still disable the [F2] key using the techniques described in Technical Bulletin #59. Specifically, you can disable [F2] by adding it to @PRIORITY.INT without assigning it a corresponding definition in @MACRO.KEYS, and re-enable it by removing it again from @PRIORITY.INT:

SUBROUTINE F2( SWITCH )
F2$ = @INT.CONST< OPTIONS$ >
IF SWITCH EQ 'OFF' THEN
  @PRIORITY.INT<-1> = F2$
END ELSE
  LOCATE F2$ IN @PRIORITY.INT USING @FM ï SETTING POS THEN
    @PRIORITY.INT = ï DELETE(@PRIORITY.INT,POS,0,0)
  END
END
RETURN

You can call this routine at any time as a subroutine. For example, with some modification it can be called with a branch of OFF as the restart code and command (you have to modify the routine by including within it the call to the main menu). This disables [F2] for the main menu in the application. From that point you can selectively enable and disable the [F2] key at any point in the application.

A few minor pointers to keep in mind when designing and using menus:

  1. Make sure your main menus are always anchored, or they will behave strangely.
  2. To call one menu from another, be sure to use the M code; don't use the TCL command RUNMENU, or you will re-invoke the menu processor.
  3. Keep selection descriptions to 63 characters or less, or they will be truncated when they appear in cell 3 of the status line.

Figure 1

Layout of menu template records

1Title.
2(reserved)
3Columns across.
4Selection. The text that appears as the menu selection.
5Description. The text that appears at the bottom of the menu (AREV style) or in the status line (PULLDOWN style) for each selection.
6Command. The command portion of the code and command associated with a menu selection.
7Code. The code portion of the code and command associated with a menu selection.
8(reserved)
9(reserved)
10Search characters. List of characters (usually initial letters) that can be used to navigate the menu selections.
11Anchor. True if the menu is an anchored menu.
12Video attributes. List (@VM-delimited) of overrides for @MW.
13(reserved)
14(reserved)
15(reserved)
16Tutorial override. If a value appears here, it is loaded into @TUTOR when the menu is displayed.
17(reserved)
18Push session flag. If set, the menu will call PUSH.SESSION and POP.SESSION while displaying.

Fields 4, 5, 6, 7, and 10 are associated multivalues.

Figure 2

COMMON /%MENUSTYLE%/ STYLE

* prompt for menu style
TEXT = "1 = AREV, 2 = PULLDOWN"
NEW_STYLE = ""
CALL MSG(TEXT, "R", NEW_STYLE, "")
IF NEW_STYLE THEN
  BEGIN CASE
    CASE NEW_STYLE = 1
      STYLE = "AREV_WINUS"
      @ENVIRON.SET<82> = "AREV"
    CASE NEW_STYLE = 2
      STYLE = "PULLDOWN_WINUS"
      @ENVIRON.SET<82> = "PULLDOWN"
    END CASE
END
CALL TEMPLATE.FLUSH()
STOP

Figure 3

SUBROUTINE MENU.SEC

COMMON /LCMENUS/ MENUS, POINTERS

MENUNAME = @TUTOR ; * field 16 in the menu template
LOCATE MENUNAME IN MENUS USING @FM SETTING POS THEN
  OPTION = POINTERS< POS, 3 >
  GOSUB PROMPT_FOR_PASSWORD
END ELSE
  * unsecured menu
END
RETURN

PROMPT_FOR_PASSWORD:

* is there a password for this option? (passwords are stored in field
* 15 of the menu template record)

MENU_TEMPLATE = XLATE('MENUS',MENUNAME,'','X')

IF MENU_TEMPLATE ELSE
  * assumes that menu templates are in MENUS or SYS.MENUS only
  MENU_TEMPLATE = XLATE('SYS.MENUS',MENUNAME,'','X')
  IF MENU_TEMPLATE ELSE RETURN
END

PASSWORD = MENU_TEMPLATE<15,OPTION>
IF PASSWORD THEN
  TEXT = 'Password?'
  USER_RESP = ''
  ECHO OFF ; * use 'RI' type message to suppress echo during typing
  CALL MSG(TEXT,'RCI',USER_RESP,'')
  ECHO ON
  IF PASSWORD = USER_RESP ELSE
    @ANS = 1 ; * fail, abort following code/command sequences
  END
END
RETURN
  • tips/revmedia/r92.txt
  • Last modified: 2024/06/19 20:20
  • by 127.0.0.1