home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-01-27 | 30.7 KB | 1,087 lines |
- Path: sparky!uunet!comp.vuw.ac.nz!waikato.ac.nz!aukuni.ac.nz!cs18.cs.aukuni.ac.nz!jwil1
- Newsgroups: comp.sources.acorn
- Subject: Source [C, Desklib]: Menu functions for DeskLib
- Message-ID: <1993Jan26.225014.19529@cs.aukuni.ac.nz>
- From: jwil1@cs.aukuni.ac.nz (TMOTA)
- Date: Tue, 26 Jan 1993 22:50:14 GMT
- Sender: jwil1@cs.aukuni.ac.nz (TMOTA)
- Organization: Computer Science Dept. University of Auckland
- Approved: cba@acorn.co.nz
- Lines: 1075
-
- The following is additional C code which adds a menu creation/handling
- functionality to DeskLib. It works in much the same way as RISC OS Lib's
- "menu" code (same interface, etc).
-
- I haven't had time to thoroughly test it or anything, but it should be OK.
- You will have to alter a couple of things (like the #includes of "Wimp_DL.h"
- instead of the DeskLib distribution name "Wimp", etc)
-
- It comes in 4 files:
- IconLib.c
- IconLib.h
- Menus.c
- Menus.h
- which you will have to cut out of this file by hand.
-
- --->8---cut here: IconLib.c
-
- /*
- IconLib.c - routines over and above RISC_OSLib and DeskLib.
- */
-
- /* ANSI includes */
- #include "stdlib.h"
-
- /* DeskLib includes */
- #include "DeskLib.Wimp.h"
-
- #include "IconLib.h"
-
- void IconLib_DisposeIndData(icon_data *data, icon_flags flags)
- {
- /* make sure this icon is indirected - exit quietly if not */
- if ((data == NULL) || (!flags.data.indirected))
- return;
-
- /* it's indirected - free the data */
- switch (ICON_TYPE(flags.value))
- {
- case TXT_ONLY:
- case TXT_AND_SPR:
-
- /* Free text buffer */
- free(data->indirecttext.buffer);
-
- /* Free validation string, if there is one */
- if ((data->indirecttext.validstring != NULL) &&
- (data->indirecttext.validstring != (char *) 0xffffffff))
- free(data->indirecttext.validstring);
- break;
-
- case SPR_ONLY:
- if (data->indirectsprite.nameisname)
- free((void *) data->indirectsprite.name);
- break;
- }
- }
-
-
- --->8---cut here: IconLib.h
-
-
- /*
- IconLib.h - routines over and above RISC_OSLib and DeskLib.
- */
-
- /* DeskLib includes */
- #include "DeskLib.Wimp.h"
-
- /* The following are used when examining icon flags/data. A simple macro is
- provide to find the type of an icon. */
-
- #define NO_ICON_DATA 0
- #define TXT_ONLY 1
- #define SPR_ONLY 2
- #define TXT_AND_SPR 3
-
- #define ICON_TYPE(flags) ((flags) & 3)
-
- void IconLib_DisposeIndData(icon_data *data, icon_flags flags);
- /*
- This will free any indirected data for this icon. It uses free(), so
- obviously expects that malloc() was used to get the memory in the first
- place, so make sure this is the case if you use this function.
- */
-
-
-
- --->8---cut here: Menus.c
-
-
-
- /*
- Menus.c
- */
-
- /* ANSI includes */
- #include "stdlib.h"
- #include "string.h"
-
- /* DeskLib includes */
- #include "Core.h"
- #include "DeskLib.Wimp.h"
- #include "DeskLib.Event.h"
- #include "WimpSWIs.h"
- #include "Error.h"
- #include "LinkList.h"
-
- /* TimsLib includes */
- #include "lib.h"
- #include "IconLib.h"
-
- #include "Menus.h"
-
- /*
- General Note:
-
- The typedef 'menu' is actually a wimp_menuptr, but cannot be used with
- free, as the word before the wimp_menublock points to the parent of this
- menu (if any), and the memory is allocated in one go (see typedef below).
- Therefore to free storage you need:
- free(((char *) menu) - 4);
- i.e. don't bother, it's easier to use Menus_Dispose().
-
- This is so that I when I add routine to extend menus, it can be used to
- extend submenus too.
- */
-
- typedef struct
- {
- menu_ptr parent;
- menu_block menublock;
- } menu_info;
-
- static void Menus__InitItem(menu_item *item)
- {
- static menu_item default_item;
-
- static BOOL first_time = TRUE;
-
- if (first_time)
- {
- first_time = FALSE;
-
- /* Initialise the menu flags */
- default_item.menuflags.value = 0;
-
- /* Initialise the menu item to have no sub-menu */
- default_item.submenu.value = -1;
-
- /* Initialise the icon flags */
- default_item.iconflags.value = icon_TEXT | icon_FILLED;
- default_item.iconflags.data.foreground = colour_BLACK;
- default_item.iconflags.data.background = colour_WHITE;
-
- /* Initialise the icon data */
- default_item.icondata.text[0] = '\0';
- }
-
- memcpy(item, &default_item, sizeof(menu_item));
- }
-
-
- static void Menus__SetOption(menu_item *item, char opt)
- {
- switch (opt)
- {
- case '!': /* Tick this entry */
- item->menuflags.data.ticked = TRUE;
- break;
-
- case '~': /* Fade this entry */
- item->iconflags.data.shaded = TRUE;
- break;
-
- case '=': /* Add dotted line after this entry */
- item->menuflags.data.dotted = TRUE;
- break;
-
- case '>': /* This entry has a dialogue box as a sub-menu */
- item->menuflags.data.notifysub = TRUE;
-
- /* Set submenu flag - use a legal window handle, but not likely to be in use */
- item->submenu.window = (window_handle) 0x7FFF;
- break;
-
- /* Ignore space */
- }
- }
-
- #define is_sep(c) (((c) == ',') || ((c) == '|'))
- #define is_opt(c) (((c) == '!') || ((c) == '>') || ((c) == '~') || ((c) == '=') || ((c) == ' '))
-
- static int Menus__ReadItemName(char *item_name, char *src)
- {
- int i = 0;
-
- /* A name can start with any character other than a 'sep' or an 'opt', and can
- then contain any character other than a 'sep'.
- */
- if (!is_sep(src[0]) && !is_opt(src[0]))
- {
- do
- {
- /* Copy this character and move on */
- item_name[i] = src[i];
- i++;
- } while (!is_sep(src[i]) && (src[i] != '\0'));
- }
-
- /* Terminate the item name */
- item_name[i] = '\0';
-
- /* Tell the caller how many characters we used */
- return i;
- }
-
-
- #define Menus__FirstEntry(menu) ((menu_item *) (((menu_ptr) (menu) + 1)))
-
- menu Menus_New(char *name, char *desc)
- {
- int entries = 1,
- i = 0,
- name_len,
- max_name_len = 0;
-
- char item_name[80];
-
- menu_info *the_menu;
- menu_item *item;
-
- /* Exit quietly if no description string */
- if (desc == NULL)
- return NULL;
-
- /* Find out how many entries are needed */
- while (desc[i] != '\0')
- {
- if ((desc[i] == ',') || (desc[i] == '|'))
- entries++;
- i++;
- }
-
- /* Get the memory for these entries */
- the_menu = (menu_info *) malloc(sizeof(menu_info) + (entries * sizeof(menu_item)));
-
- /* Get pointer to first item, using some obscure pointer arithmetic */
- item = Menus__FirstEntry(&the_menu->menublock);
-
- i = 0;
-
- /* Construct the menu entries */
- while (desc[i] != '\0')
- {
- /* Initialise this menu item */
- Menus__InitItem(item);
-
- /* Look for an option */
- if (is_opt(desc[i]))
- {
- Menus__SetOption(item, desc[i]);
- i++;
- }
-
- /* Read the item name */
- name_len = Menus__ReadItemName(item_name, desc + i);
-
- /* Copy the item name into the menu icon */
-
- if (name_len <= wimp_MAXNAME)
- {
- /* normal non-indirected icon */
- strncpy(item->icondata.text, item_name, wimp_MAXNAME);
- }
- else
- {
- /* Too long - make into indirected icon */
-
- item->iconflags.data.indirected = TRUE;
- item->icondata.indirecttext.buffer = save_str(item_name, 0);
-
- item->icondata.indirecttext.bufflen = name_len + 1; /* for terminator */
-
- item->icondata.indirecttext.validstring = (char *) -1; /* no validation */
- }
-
- /* Check if this is the longest item so far */
- if (name_len > max_name_len)
- max_name_len = name_len;
-
- /* Move to next menu item */
- i += name_len;
-
- /* Skip the separator, if there is one */
- if (is_sep(desc[i]))
- i++;
-
- item++;
- }
-
- /* Set the 'last' flag on the last menu item */
- item--;
- item->menuflags.data.last = TRUE;
-
- /* Set up menu block */
- strncpy(the_menu->menublock.title, name, wimp_MAXNAME);
-
- /* These attributes taken from Wimp Application notes (RO2 PRMS p1314) */
- the_menu->menublock.titlefore = colour_BLACK;
- the_menu->menublock.titleback = colour_GREY2;
- the_menu->menublock.workfore = colour_BLACK;
- the_menu->menublock.workback = colour_WHITE;
- the_menu->menublock.width = (max_name_len + 1) * 16; /* !!!Find a legal way!!! */
- the_menu->menublock.height = 44;
- the_menu->menublock.gap = 0;
-
- return (menu) &(the_menu->menublock);
- }
-
- void Menus__Dispose(menu_ptr the_menu, BOOL recursive)
- {
- menu_info *info;
-
- /* Get pointer to the first item */
- menu_item *item = (menu_item *) (the_menu + 1);
-
- /* De-allocate any indirect data / sub-menus */
- do
- {
- /* Does this item have a sub-menu (but not a dialogue box sub-menu) */
- if (recursive && item->submenu.value >= 0x8000)
- Menus__Dispose(item->submenu.menu, recursive);
-
- /* Free up any indirected data */
- IconLib_DisposeIndData(&item->icondata, item->iconflags);
-
- /* Move to next item */
- item++;
- } while (item->menuflags.data.last == FALSE);
-
- /* Free the data for the menu block - this includes all the menu items, and
- also the word preceeding the menu_block, as it points to the parent menu.
- */
- info = (menu_info *) (((char *) the_menu) - 4);
- free(info);
- }
-
- void Menus_Dispose(menu the_menu, BOOL recursive)
- {
- /* Just a veneer for the slightly lower-level Menus__Dispose() */
-
- Menus__Dispose(&(((menu_info *) the_menu)->menublock), recursive);
- }
-
- void Menus_SubMenu(menu parent, int entry, menu submenu)
- {
- /* Get a pointer to the menu info block of the submenu */
- menu_info *submenu_info = (menu_info *) (((int *) submenu) - 1);
-
- /* Get a pointer to the first entry */
- menu_item *item = Menus__FirstEntry(parent);
-
- /* Plug the submenu into the specified menu entry */
- item[entry-1].submenu.menu = (menu_ptr) submenu;
-
- /* Link the submenu to the parent */
- submenu_info->parent = (menu_ptr) parent;
- }
-
- void Menus_AddDialogBox(menu the_menu, int entry, window_handle window)
- {
- /* Get a pointer to the first entry */
- menu_item *item = Menus__FirstEntry(the_menu);
-
- /* Plug the submenu into the specified menu entry */
- item[entry-1].submenu.window = window;
- }
-
- void Menus_SetFlags(menu the_menu, int entry, BOOL tick, BOOL fade)
- {
- /* Get a pointer to the first item */
- menu_item *item = Menus__FirstEntry(the_menu);
-
- /* Set the flags as required */
- item[entry-1].menuflags.data.ticked = tick;
- item[entry-1].iconflags.data.shaded = fade;
- }
-
- void Menus_MakeWritable(menu the_menu, int entry,
- char *buffer, int bufflen, char *validstring)
- {
- char *the_text = NULL; /* Used to keep a copy of the current text of the entry */
-
- /* Get a pointer to the first item */
- menu_item *item = Menus__FirstEntry(the_menu);
-
- /* Move to the entry we want */
- item += (entry - 1);
-
- /* If it's currently a text (or text & sprite) icon, save the text string */
-
- switch (ICON_TYPE(item->iconflags.value))
- {
- case TXT_ONLY:
- case TXT_AND_SPR:
- if (item->iconflags.data.indirected)
- {
- the_text = save_str(item->icondata.indirecttext.buffer, 0);
- }
- else
- {
- the_text = (char *) malloc(wimp_MAXNAME + 1);
- strncpy(the_text, item->icondata.text, wimp_MAXNAME);
- the_text[wimp_MAXNAME] = '\0';
- }
- }
-
- /* Free any indirected data */
- IconLib_DisposeIndData(&item->icondata, item->iconflags);
-
- /* Make the entry into a writable, indirected, text-only icon */
- item->menuflags.data.writable = TRUE;
- item->iconflags.data.text = TRUE;
- item->iconflags.data.sprite = FALSE; /* just to be safe */
- item->iconflags.data.indirected = TRUE;
-
- /* Plug in the buffer and validation string */
- item->icondata.indirecttext.buffer = buffer;
- item->icondata.indirecttext.bufflen = bufflen;
- item->icondata.indirecttext.validstring = validstring;
-
- /* Copy the old text back in and free the buffer, if necessary */
- if (the_text != NULL)
- {
- strncpy(buffer, the_text, bufflen - 1);
- free(the_text);
- }
- }
-
- void Menus_Show(menu the_menu, wimp_point mouse_pos, BOOL iconbar)
- {
- /* If an iconbar menu, position bottom of menu 96 OS units above bottom
- of screen.
- */
- if (iconbar)
- {
- /* Title bar is not included in the positioning of menu windows */
-
- int menu_height = 0;
-
- menu_ptr menu = (menu_ptr) the_menu;
- /* Get a pointer to the first item */
- menu_item *item = Menus__FirstEntry(the_menu);
-
- BOOL not_finished = TRUE;
-
- /* Process each menu entry */
-
- while (not_finished)
- {
- /* Add height of menu item for each item */
- menu_height += menu->height;
-
- /* Add extra height for a separator */
- if (item->menuflags.value & 2)
- /* NB this value may be wrong for non-standard item heights/inter-item gaps */
- menu_height += (6 * 4);
-
- /* If not the last item, add the inter-item gap */
- if (item->menuflags.data.last)
- {
- menu_height += menu->gap;
- not_finished = FALSE;
- }
-
- /* Process the next item */
- item++;
- }
-
- /* Position menu */
- mouse_pos.y = 96 + menu_height;
- }
-
- /* Open the menu 64 OS units to the left of the mouse click, as recommended
- by the RO2 PRMS, p1314.
- */
- Error_Check(Wimp_CreateMenu((menu_block *) the_menu, mouse_pos.x - 64, mouse_pos.y));
- }
-
-
- /* Menu attachment routines */
-
- typedef struct handler_str
- {
- union
- {
- int value;
- struct
- {
- unsigned int menu_maker : 1; /* 1 => data union contains a menu_maker */
- unsigned int icon_handler : 1; /* 1 => Menu should be shown if select pressed */
- unsigned int iconbar : 1; /* 1 => Menu is attached to icon bar icon */
- } data;
- } flags;
-
- union
- {
- menu menu;
- menu_maker maker;
- } data;
-
- menu_handler handler_proc;
- void *reference;
- } handler_str;
-
- typedef struct icon_node
- {
- linklist_header header;
- icon_handle icon;
- handler_str handler;
- } icon_node;
-
- typedef struct window_node
- {
- linklist_header header;
- window_handle window; /* event_ANY means catch all menu events */
- linklist_header icons_anchor;
- handler_str handler;
- } window_node;
-
-
- /* Contains tree of menu handlers */
- linklist_header handlers = {NULL, NULL};
-
- /*
- 'submenu_handle' is used to store the window handle passed to
- Menus_AddDynamicDialogBox, which should be called in response to receiving a
- menu warning (requested by using the '>' option in the menu description string).
-
- Sequence of events is:
- Message menu warning arrives.
- Menus__MessageHandler calls appropriate user menu handler
- User's menu handler calls Menus_AddDynamicDialogBox with handle to add.
- Menus_AddDynamicDialogBox stores window handle and returns.
- User's menu handler returns.
- Menus__MessageHandler calls SWI Wimp_CreateSubmenu with the saved window handle,
- and returns.
-
- i.e., a bit neater than all that dbox malarkey with Risc OS Lib.
- (and much simpler for user).
- */
-
- static window_handle submenu_handle;
-
-
- void Menus_AddDynamicDialogBox(window_handle window)
- {
- /* A bit simple - provide a macro instead? */
- submenu_handle = window;
- }
-
- /* BOOL Menus__MessageHandler()
-
- This handles menu warning messages, and calls the appropriate user menu
- handler to get the window handle to use as a sub-menu.
-
- It passes on the selection array to the user's handler, just like a normal
- menu selection.
- */
-
- static BOOL Menus__MessageHandler(event_pollblock *event, void *reference)
- {
- /* If this is a menu warning message, process it */
- if (event->data.message.header.action == message_MENUWARNING)
- {
- handler_str *handler = (handler_str *) reference;
-
- /* Get the window handle for the submenu */
- handler->handler_proc(reference, event->data.message.data.words+3);
-
- /* Call Wimp_CreateSubMenu to show the submenu */
- Error_Check(Wimp_CreateSubMenu((menu_block *) submenu_handle,
- event->data.message.data.words[1],
- event->data.message.data.words[2]));
- return TRUE;
- }
- else
- /* Pass on to next handler */
- return FALSE;
- }
-
- /* BOOL Menus__SelectionHandler()
-
- This will pass on a selection array to the relevant handler.
- If adjust is pressed, the menu is re-opened.
-
- NB. Menu selection events are released, unless adjust is pressed.
- This is in case the user wants to use them at other times.
- */
- static BOOL Menus__SelectionHandler(event_pollblock *event, void *reference)
- {
- handler_str *handler = (handler_str *) reference;
-
- /* Get pointer info */
- mouse_block mouse;
- Error_Check(Wimp_GetPointerInfo(&mouse));
-
- /* Deal with selection */
- handler->handler_proc(reference, event->data.selection);
-
- /* If adjust pressed, re-open the menu.
- The position doesn't matter - the Wimp knows it's being re-opened and so it
- works out the position for itself.
- */
- if (mouse.button.data.adjust)
- {
- wimp_point pos;
- menu m;
-
- /* Call the menu maker, if necessary */
- if (handler->flags.data.menu_maker)
- m = (handler->data.maker)(reference);
- else
- m = handler->data.menu;
-
- pos.x = 0; pos.y = 0;
-
- Menus_Show(m, pos, FALSE);
- }
- else
- {
- /* Menu to be closed - release menu selection events... */
- Event_Release(event_MENU, event_ANY, event_ANY,
- Menus__SelectionHandler, reference);
- Event_Release(event_USERMESSAGE, event_ANY, event_ANY,
- Menus__MessageHandler, reference);
- }
-
- /* We always handle menu selection events */
- return TRUE;
- }
-
-
- /* BOOL Menus__EventHandler()
-
- This is called when a menu might be requested (ie a mouse click on a window
- or icon user has registered a menu for.
- If a menu is needed, it is created if necessary, and then shown.
- Menu selection events are also claimed for passing to Menus__SelectionHandler().
- */
-
- static BOOL Menus__EventHandler(event_pollblock *poll_block, void *reference)
- {
- handler_str *handler = (handler_str *) reference;
- mouse_block *mouse = &poll_block->data.mouse;
-
- /* If menu was pressed, or if select was pressed and this menu is attached to
- an icon, we should deal with this event, otherwise pass back to Event
- module.
- */
- if ((mouse->button.data.menu) ||
- ((handler->flags.data.icon_handler) && (mouse->button.data.select)))
- {
- /* Menu requested - call menu maker if necessary */
- menu m;
-
- if (handler->flags.data.menu_maker)
- m = (handler->data.maker)(reference);
- else
- m = handler->data.menu;
-
- /* Request menu selections and warning messages to be delivered to us... */
- Event_Claim(event_MENU, event_ANY, event_ANY,
- Menus__SelectionHandler, (void *) handler);
- Event_Claim(event_USERMESSAGE, event_ANY, event_ANY,
- Menus__MessageHandler, (void *) handler);
-
- /* And show the menu */
- Menus_Show(m, mouse->pos, handler->flags.data.iconbar);
-
- return TRUE;
- }
- return FALSE;
-
- }
-
- static window_node *find_window_node(window_handle window)
- {
- /* Looks through the handlers to see if one is registered for this
- window handle already. Returns pointer to it if it is, NULL otherwise.
- */
- window_node *windownode = LinkList_FirstItem(&handlers);
-
- /* Search for specified window handle */
- while ((windownode != NULL) && (windownode->window != window))
- windownode = (window_node *) LinkList_NextItem(&windownode->header);
-
- /* Return what we found (possibly NULL => no window node found */
- return windownode;
- }
-
- static icon_node *find_icon_node(linklist_header *anchor, icon_handle icon)
- {
- /* Looks through the given icon handlers to see if one is registered for this
- icon handle already. Returns pointer to it if it is, NULL otherwise.
- */
- icon_node *iconnode = LinkList_FirstItem(anchor);
-
- /* Search for specified icon handle */
- while ((iconnode != NULL) && (iconnode->icon != icon))
- iconnode = (icon_node *) LinkList_NextItem(&iconnode->header);
-
- /* Return what we found (possibly NULL => no icon node found */
- return iconnode;
- }
-
- static handler_str *find_menu_handler(window_handle window, icon_handle icon)
- {
- window_node *windownode;
- icon_node *iconnode;
-
- /* This returns a pointer to a handler_str for the caller to fill in.
- It searches for an existing handler to overwrite, or failing that, creates
- a new node in the tree for the specified window/icon handle pair, and returns
- a pointer to the handler_str of that.
- i.e. it's a 'constructive' find - if it can't find the entity it's looking for,
- it makes it.
- */
-
- /* Is there already a handler for this window? */
-
- windownode = find_window_node(window);
-
- if (windownode == NULL)
- {
- /* There isn't - so add one */
-
- windownode = (window_node *) malloc(sizeof(window_node));
- windownode->window = window;
- LinkList_InitItem(&windownode->icons_anchor); /* No icon specifics (yet) */
-
- /* If icon-specific, we should null the window-specific handler... */
- if (icon != event_ANY)
- {
- /* The handler_proc is the flag - if it's NULL, there's no menu or
- menu maker installed either.
- */
- windownode->handler.handler_proc = NULL;
- }
-
- /* Add to head of list - except event_ANY, which should always be last */
-
- if (window == event_ANY)
- LinkList_AddToTail(&handlers, &(windownode->header));
- else
- LinkList_AddToHead(&handlers, &(windownode->header));
- }
- else if (icon == event_ANY)
- {
- /* There is a window-specific handler already - remove it */
- Event_Release(event_CLICK, window, event_ANY, Menus__EventHandler,
- (void *) &windownode->handler);
- }
-
- /* If not interested in icon-specific handler, just return pointer to
- window-specific handler */
- if ((window == event_ANY) || (icon == event_ANY))
- return &windownode->handler;
-
- /* Is there already a handler for this icon? */
- iconnode = find_icon_node(&windownode->icons_anchor, icon);
-
- if (iconnode == NULL)
- {
- /* No icon handler for this icon, so add one */
-
- iconnode = (icon_node *) malloc(sizeof(icon_node));
- iconnode->icon = icon;
-
- /* Add to the icon handler list */
- LinkList_AddToTail(&windownode->icons_anchor, &(iconnode->header));
- }
- else
- {
- /* Remove the handler which is already present */
- Event_Release(event_CLICK, window, icon, Menus__EventHandler,
- (void *) &iconnode->handler);
- }
-
- return &iconnode->handler;
- }
-
-
- /* This is used to set the flag in the handler_str. */
- static BOOL Menus__menu_maker = FALSE;
-
- void Menus_AttachMenu(menu the_menu, window_handle window, icon_handle icon,
- menu_handler handler_proc, void *reference)
- {
- handler_str *handler = find_menu_handler(window, icon);
-
- handler->flags.data.menu_maker = Menus__menu_maker;
- handler->flags.data.icon_handler = (icon != event_ANY);
- handler->flags.data.iconbar = (window == window_ICONBAR);
- handler->data.menu = the_menu;
- handler->handler_proc = handler_proc;
- handler->reference = reference;
-
- /* Claim mouse click events for given window/icon handle pair */
- Event_Claim(event_CLICK, window, icon, Menus__EventHandler, (void *) handler);
- }
-
-
- void Menus_AttachMenuMaker(menu_maker maker_proc,
- window_handle window, icon_handle icon,
- menu_handler handler_proc, void *reference)
- {
- /* Bit of a cheat this - relies on union structure of handler_str, but why
- duplicate code in a library?
- */
- Menus__menu_maker = TRUE;
- Menus_AttachMenu((menu) maker_proc, window, icon, handler_proc, reference);
- Menus__menu_maker = FALSE;
- }
-
- void Menus_DetachMenu(window_handle window, icon_handle icon)
- /*
- Detaches any menus or menu makers from the given window/icon.
- If called for a window, detaches *all* handlers for it, including
- icon specific ones.
- If the window is event_ANY, it ONLY removes the 'catch-all' handler - it
- does NOT remove all menu handlers.
-
- It is legal to call this even if no menus/makers are attached to the
- specified window/icon.
-
- window should be event_ANY - if not window specific, or
- a window handle - to detach only from that window
- icon should be event_ANY - if not icon-specific, or
- an icon handle - to detach ONLY from that icon
- (NOTE: if icon != event_ANY, window MUST be defined)
- */
- {
- window_node *windownode = find_window_node(window);
- icon_node *iconnode;
-
- if (windownode == NULL)
- /* Couldn't find any handlers for specified window */
- return;
-
- if (icon == event_ANY)
- {
- icon_node *tmp;
-
- /* Release the events claimed by this window-specific handler */
- Event_Release(event_CLICK, window, event_ANY, Menus__EventHandler,
- (void *) &windownode->handler);
-
- /* Remove this window's node */
- LinkList_Unlink(&handlers, &(windownode->header));
-
- /* Free the icon handler nodes for this window (if any exist) */
-
- iconnode = LinkList_FirstItem(&windownode->icons_anchor);
-
- /* Don't need to unlink each node as we're deleting the whole list
- including the anchor anyway.
- */
- while (iconnode != NULL)
- {
- tmp = iconnode;
- iconnode = LinkList_NextItem(&iconnode->header);
- free(tmp);
- }
-
- /* Free the window node itself */
- free(windownode);
- }
- else
- {
- /* Remove handler for this icon */
- iconnode = find_icon_node(&windownode->icons_anchor, icon);
-
- /* If no handler for this window/icon handle pair, exit quietly */
- if (iconnode == NULL)
- return;
-
- /* Release the events claimed by this icon-specific handler */
- Event_Release(event_CLICK, window, icon, Menus__EventHandler,
- (void *) &iconnode->handler);
-
- /* Remove the icon node from the window's list of icon handlers */
- LinkList_Unlink(&(windownode->icons_anchor), &(iconnode->header));
-
- /* Free the memory used for this node */
- free(iconnode);
-
- /* If this was the last icon handler for this window, and there is no
- window-specific handler, delete the window node as well.
- */
- if ((LinkList_FirstItem(&windownode->icons_anchor) == NULL) &&
- (windownode->handler.handler_proc == NULL))
- {
- LinkList_Unlink(&handlers, &(windownode->header));
- free(windownode);
- }
- }
- }
-
-
-
- --->8---cut here: Menus.h
-
-
-
- /*
- Menus.h - a replacement for RISC_OSLib's menu module.
-
- A bit tacky at the mo as menu entries are numbered from 1 when specifying
- but the handlers receive offset numbered from 0. Will fix when I start using
- this seriously.
-
- Why does Risc OS Lib offset convert a 0-based int array to a 1-based char array???
-
- */
-
- /* DeskLib includes */
- #include "Core.h"
- #include "Wimp_DL.h"
-
- typedef int menu;
-
- extern menu Menus_New(char *name, char *desc);
- /*
- Creates a menu with the given name and description. The description syntax
- is the same as for RISC_OSLib's menu module.
- */
-
- extern void Menus_Dispose(menu the_menu, BOOL recursive);
- /*
- De-allocates memory associated with this menu. If recursive is TRUE, also
- recursively de-allocates all sub-menus of the_menu.
- */
-
- extern void Menus_SubMenu(menu parent, int entry, menu submenu);
- /*
- Attaches 'submenu' as a sub-menu onto the menu 'parent' at position 'entry'.
- */
-
- extern void Menus_AddDialogBox(menu the_menu, int entry, window_handle window);
- /*
- Attaches a window (dialogue box) as a submenu onto 'the_menu' at position
- 'entry'. Usually called for a menu warning event, just before dbox is
- shown.
- */
-
- extern void Menus_SetFlags(menu the_menu, int entry, BOOL tick, BOOL fade);
- /*
- This sets the flags on the given menu entry.
- */
-
- #define Menus_TickEntry(the_menu, entry, tick) ((((menu_item *) (Menus_SysHandle(the_menu) + 1))[(entry)-1].menuflags.data.ticked) = (tick))
-
- #define Menus_FadeEntry(the_menu, entry, fade) ((((menu_item *) (Menus_SysHandle(the_menu) + 1))[(entry)-1].iconflags.data.shaded) = (fade))
- /*
- void Menus_TickEntry(menu the_menu, int entry, BOOL tick)
- void Menus_FadeEntry(menu the_menu, int entry, BOOL fade)
-
- These are simple(!) macros for when you want to set the tick or fade flags on
- their own.
- */
-
-
- extern void Menus_MakeWritable(menu the_menu, int entry,
- char *buffer, int bufferlength, char *validation);
- /*
- This makes the specified menu entry writable.
- */
-
- extern void Menus_Show(menu the_menu, wimp_point mouse_pos, BOOL iconbar);
- /*
- This is used in response to a mouse button event with buttons = 4 (MENU
- pressed). The mouse_pos is used to position the menu - just pass the wimp_point
- from the mouse button event straight through.
- If iconbar is TRUE, it sets the vertical position correctly for an icon
- bar menu as per the Acorn guideline in RO2 PRMs p1315 - 96 OS units above the
- bottom of the screen.
- */
-
- /*
-
- extern menu_ptr Menus_SysHandle(menu the_menu);
-
- Returns a low-level handle to the menu, for manipulations not supported by
- this module.
-
- NB. Do NOT use free() on this pointer - it won't work!
- */
- #define Menus_SysHandle(menu) ((menu_ptr) (menu))
-
- /* Attaching menus for automatic handling */
-
- typedef void (*menu_handler)(void *reference, int *hit);
- typedef menu (*menu_maker)(void *reference);
-
- extern void Menus_AttachMenu(menu the_menu, window_handle window, icon_handle icon,
- menu_handler handler, void *reference);
- /*
- the_menu the menu to attach
- window should be event_ANY - if not window specific, or
- a window handle - to attach only to that window
- icon should be event_ANY - if not icon-specific, or
- an icon handle - to attach ONLY to that icon
- (NOTE: if icon != event_ANY, window MUST be defined)
-
- handler is the address of your menu handler function
- reference is a handle for any user-data you want passed to the
- function whenever it is called.
-
- Note that menus attached to icons will be invoked by SELECT clicks as well
- as MENU clicks.
- */
-
-
- extern void Menus_AttachMenuMaker(menu_maker maker_proc,
- window_handle window, icon_handle icon,
- menu_handler handler, void *reference);
- /*
- the_menu the menu to attach
- window should be event_ANY - if not window specific, or
- a window handle - to attach only to that window
- icon should be event_ANY - if not icon-specific, or
- an icon handle - to attach ONLY to that icon
- (NOTE: if icon != event_ANY, window MUST be defined)
-
- handler is the address of your menu handler function
- reference is a handle for any user-data you want passed to the
- function whenever it is called.
-
- Note that menus attached to icons will be invoked by SELECT clicks as well
- as MENU clicks.
- */
-
- extern void Menus_AddDynamicDialogBox(window_handle window);
- /*
- This is used for sub-menu dialog boxes that are created on demand.
-
- This should be called from within the menu selection handler when
- a submenu is traversed that has been marked with a '>' option in the
- menu string. The handler should create the window to show as a submenu
- (but not open it) and pass the handle to this function, then return.
- The rest is automagic!
- */
-
-
- extern void Menus_DetachMenu(window_handle window, icon_handle icon);
- /*
- Detaches any menus or menu makers from the given window/icon.
- If called for a window, detaches *all* handlers for it, including
- icon specific ones.
- If the window is event_ANY, only removes the 'catch-all' handler - it
- does NOT remove all menu handlers.
-
- It is legal to call this even if no menus/makers are attached to the
- specified window/icon.
-
- window should be event_ANY - if not window specific, or
- a window handle - to detach only from that window
- icon should be event_ANY - if not icon-specific, or
- an icon handle - to detach ONLY from that icon
- (NOTE: if icon != event_ANY, window MUST be defined)
- */
-
- --
- themasterofthearcanejwil1@cs.aukuni.ac.nzthismessagewassentonrecycledelectrons
-