© Cerilica 2022
A module that makes advanced Wimp menu functionality very much easier.
The MenuState module provides a SWI that performs the following valuable functions:
Detect whether a menu is open, and return its owner
Read the Wimp’s menu window handles
Read a corrected, enhanced MenuState structure that greatly improves RISC OS menu capability
A strange artefact of the Wimp’s functionality is that only the menu’s owner can call Wimp_GetMenuState – to all other tasks that SWI returns no result. This has made detecting the existence of a menu (or a dialog opened as a menu) very difficult indeed.
MenuState_Get returns the task handle of the menu owner, or zero if there is no menu.
Menu Window Handles
Although menus are created using Wimp_CreateMenu and Wimp_CreateSubMenu, the Wimp uses ordinary windows to represent the menus. These are strange windows in that they are owned by the WindowManager but access the menu definition in the menu owner’s application slot.
MenuState_Get can return these window handles so that many special effects can be performed (for example, see MenuBadges).
Enhanced Menu State
The Wimp_GetMenuState (and Wimp_Poll event 9) menu state structures are bugged in all versions of the Wimp, making it difficult to provide accurate Interactive Help if the pointer is over a menu separator, and almost (but not quite) impossible to open a submenu from a dialog that is part of a menu.
MenuState_Get returns an enhanced menu state structure that makes it easy to open a submenu out of a dialog that is part of a menu, such as a save dialog filetype menu:
It makes it easier to provide the correct interactive help when the pointer is over a separator or in a dialog submenu as above:
The zip file contains two example Basic programs that demonstrate the new capabilities:
xMenuMad is inspired by !Madness that shipped with RISC OS 2, but only affects the windows that make up the menu! MenuState_Get is used to return only those window handles.
xMenuHelp demonstrates how to open a filetype submenu out of a save dialog that is part of a menu (which has long been considered impossible), and how to output accurate interactive help when the menu contains separators. MenuState_Get is used in both cases.
There is extensive documentation in the above zip, but here are the SWIs:
=> R1 0 to return only the menu owner, or
aligned buffer to return Menu State (at least 40 bytes, typically 256), or
buffer+1 to return window handles instead
<= R0 full task handle of menu owner, or 0 if no menu
This can be called at any time, by any task or non-task to detect whether there is a menu open. If R0=0 on exit, there is no menu.
If R1 points to an aligned buffer on entry and the menu is open, an enhanced Menu State is returned. This is a series of indices into each open level of the menu, exactly as described in the PRMs for Wimp_GetMenuState. However, additional values are returned:
0+ A selected item in the menu, 0 is the top line, 1 the next
-1 The terminator of the list of items
-2 An additional terminator after -1 for compatibility
-3 An unselected menu, such as the pointer being over a menu
separator or outside the menu
-4 A menu dialog, such as a save window
If the R1 buffer has b0 set (i.e. buffer+1) then instead of a Menu State, the window handles of the menu are returned, whether they are submenus or dialogs. This allows advanced special effects to be performed.
<= R0 maximum menu depth (typically 8)
Although the maximum depth of menus has not changed since Arthur, the MenuState module adapts to the WindowManager in use, so use this call to avoid assuming anything about the size of the buffer required (though it can never be larger than 63 because of the size of buffer passed to Wimp_Poll).