/* Copyright 1997 Acorn Computers Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /***************************************************/ /* File : Global.h */ /* */ /* Purpose: Holds all of the browser's globals. */ /* */ /* Author : A.D.Hodgkinson */ /* */ /* History: 18-Oct-96: Created. */ /***************************************************/ #include "stdio.h" #include "struct.h" /* From the HTML library */ #include "tablestruc.h" /* From the HTML library */ #include "imagetrans.h" /* Image library API */ #include "setjmp.h" #include "window.h" #include "Bitfields.h" #include "Limits.h" #ifndef SINGLE_USER #include "Multiuser.h" #endif /* For comments on what these actually are, see Global.c */ #ifdef TRACE extern unsigned int tl; extern int malloccount; extern int flexcount; #endif extern jmp_buf env; extern int quit; extern int modechanged; extern int printing; extern int drag_in_progress; extern int authorising; extern void * dialler_pollword_address; extern int wimp_version; extern int nested_wimp; extern int task_handle; extern int sprite_block; extern int taskmodule_ds_registered; extern int uri_module_present; extern MessagesFD meb; extern MessagesFD * chb; extern MessagesFD * cob; extern char tokens[Limits_Message]; extern char lasttokn[Limits_Token]; extern char * task_dir; extern int messages_list[]; extern IdBlock idb; extern int event_code_list[]; extern WimpPollBlock b; extern char program_name[Limits_TaskName]; extern int null_counter; extern int bullets; extern unsigned int animation_frames; /* Fetch status */ typedef enum bs_fetch { BS_IDLE = 0, /* Nothing happening */ BS_START, /* A fetch has just started */ BS_STARTED, /* Some data has been fetched */ BS_IDENTIFY, /* Identifying a stream */ BS_FETCHING, /* Stream identified, HTML being fetched */ BS_DATAFETCH, /* Stream being spooled to a file */ BS_PROCESS /* Fetched stream still being processed by fetcher */ } bs_fetch; /* Defined elsewhere... (easy to work out from naming convention) */ struct reformat_line; struct reformat_line_chunk; struct object_info; struct plugin_stream; /* For tables, holds information required to format a specific table cell */ typedef struct reformat_cell { struct reformat_line * ldata; int nlines; struct reformat_line_chunk * cdata; int x; /* Offsets for positioning the contents */ int y; int minwid; /* Remembered when reformatting to avoid having to format over and over */ int maxwid; /* Similarly, remembered when reformatting */ int width; /* Size of content of this 'subwindow' (should help more formatting or */ int height; /* clipping); width is maxlen of lines, height from last line's y coord */ int cellwidth; int cellheight; /* Full size of subwindow */ table_stream * table; /* Main table definition structure */ } reformat_cell; /* These two structures represent lines for display in the browser */ /* window. A series of reformat_line structures exist as an array */ /* pointed to in the browser_data structure (see below). These */ /* each have a series of line chunks, as reformat_line_chunk */ /* structures, which they point to. The chunks themselves are in */ /* a separate block of memory. */ typedef struct reformat_line { int x; /* x coord of left of this line, in window coords */ int y; /* y coord of bottom of this line, in window coords */ int h; /* Height of this line in OS units */ int b; /* y offset of the font base line from the bottom */ int n; /* Number of line chunks on this line */ int chunks; /* Starting array offset into chunks for this line */ } reformat_line; typedef struct reformat_line_chunk { HStream * t; /* The token number the line represents */ int o; /* Offset into the token this chunk starts at */ int l; /* The number of bytes from the token in this chunk */ /* (0 = all the rest) */ int w; /* Width of this chunk in font coords */ } reformat_line_chunk; /* Bistate / tristate button types */ typedef enum bistate_type { BiState_None, /* No bistate button present */ BiState_Cancel_Back /* A Cancel / Back bistate */ } bistate_type; typedef enum tristate_type { TriState_None, /* No tristate button present */ TriState_Go_GoTo_Stop /* A go / go to / stop tristate */ } tristate_type; /* Displayed information */ typedef enum display_type { Display_Fetched_Page, /* A blank page or HTML / text file (externally fetched) is shown in the window */ Display_External_Image, /* An internally generated HTML file to show an external image is being shown */ Display_Scrap_File, /* A scrap file is to be loaded in one go, no need to use fetcher modules */ Display_Previous_Page, /* Return to the previous page in the history list */ Display_Recovered_Page, /* Go to the page in Browse$CurrentPage */ Display_Home_Page, /* Go to the home page */ Display_About_Page /* Display 'About' page listing Plug-Ins and so-on */ } display_type; /* Reformat request queueing */ typedef struct reformat_queue { int line; /* Start reformatting on the next line after this one */ int image; /* The image number, if it resized and prompted the reformat */ struct reformat_queue * next; } reformat_queue; /* One of these is allocated for each browser window, */ /* and holds lots of essential information connected */ /* with that window and the page it contains. */ typedef struct browser_data { struct browser_data * previous; /* Points to previous browser_data structure, or NULL for none. */ struct browser_data * next; /* Points to next browser_data structure, or NULL for no more. */ ObjectId self_id; /* The object ID of the browser window the structure is associated with. */ int window_handle; /* The Wimp window handle of the browser window. */ /* */ WindowShowObjectBlock small_size; /* Window details when not toggled to full screen size. */ int min_height; /* The minimum vertical extent of the browser window. */ int display_width; /* Visible area width, used for reformatting etc. */ int display_extent; /* Visible area extent normally=width but may be forced up by reformatter. */ int display_height; /* Visible area height, used for % specified height items etc. */ /* */ bs_fetch fetch_status; /* To keep track of the current fetch status (see bs_fetch definition). */ int fetch_handle; /* The html-lib handle of the document being fetched. */ int display_handle; /* The html-lib handle of the displayed document. */ /* */ unsigned int current_frame; /* The currently displayed animation frame. */ unsigned int current_time; /* The time at which the currently displayed animation frame was shown. */ int current_fetches; /* For frames, counts total still active fetches (so animation continues). */ /* */ FILE * save_file; /* File handle for data saves. */ int save_type; /* Filetype for data saves. */ int save_transferred; /* Number of bytes done so far for in-memory transfers. */ ObjectId save_dbox; /* Object ID of the save dialogue being used. */ int save_oldstore; /* Size of the old fetched store before saving trashed it (if applicable). */ int data_size; /* Size of main page data being fetched, or 0 if unknown. */ int progress_updated; /* Monotonic time at which the fetch progress counter was last updated. */ /* */ int dialler_last; /* Time that the dialler online time was last updated. */ int meta_refresh_at; /* For META tags leading to a refresh, the time to start the fetch. */ char * meta_refresh_url; /* For META tags leading to a refresh, the URL to fetch. */ /* Frames fields (though some other */ /* frame-related bits and pieces are */ /* scattered around elsewhere). */ char * window_name; /* Name of this frame / browser window. */ struct browser_data * ancestor; /* The base browser containing the frames (NULL for the base itself). */ struct browser_data * real_parent; /* For any frame pane, this points to the pane below. */ struct browser_data * parent; /* If this is a nested frame in one document, this points to parent. */ /* */ int nchildren; /* Number of children if this window / frame has other children frames. */ struct browser_data ** children; /* Pointer to array of pointers to the children's browser_data structs. */ /* */ HStream * frameset; /* For a parent with children, pointer to token that defines the frameset. */ HStream * frame; /* For a child, pointer to a token that defines its characteristics. */ int nesting_level; /* For an ancestor, this tracks nesting levels as frames are defined. */ int filling_frame; /* For a parent, as it fills in children info it updates this counter. */ int * frame_widths; /* The width of the frames, in OS units. */ int * frame_heights; /* The height of the frames, in OS units. */ struct browser_data * selected_frame; /* For ancestors and keyboard control, the currently selected frame. */ /* */ int nstatus; /* Number of entries in status_contents array. */ void * status_contents; /* Information maintained by toolbars_update_status about frame statuses. */ char * status_help; /* If non-NULL, points to a string of help text for the status line. */ /* Memory allocation and management */ void * source; /* Pointer to the page source. */ HStream * stream; /* Pointer to linked HStream list, malloced and owned by the HTML library. */ /* */ HStream * final_token; /* Address of the token last dealt with by the reformatter. */ HStream * display_request; /* Token to display at top of the window as soon as possible. */ int display_offset; /* Offset into token data to display. */ int display_vscroll; /* Last vertical scroll position when a requested token was displayed. */ /* */ void * fdata; /* Pointer to pointer to forms data. */ void * post_data; /* Pointer to pointer to extra data for forms. */ int nforms; /* Counter for forms. */ /* */ struct object_info * odata; /* Object data (for OBJECT, EMBED and APPLET). */ int nobjects; /* Saves time on working out size of odata divided by structure size. */ /* */ reformat_cell * cell; /* Pointer to malloced reformat_cell holding redraw information. */ /* */ void * history_current; /* A priavte word used by the History to record the history position. */ /* */ char * urlfdata; /* URL being fetched. */ char * urlddata; /* URL being displayed. */ /* Special states */ tristate_type tristate; /* Type of a tristate button, if one is present. */ int tristate_state; /* Current state of the tristate button. */ bistate_type bistate; /* Type of a bistate button, if one is present. */ int bistate_state; /* Current state of the bistate button. */ WimpMessage * pending_data_load; /* For saving link contents (Shift+Click), if going app-to-app. */ /* JavaScript support */ const char * onload; /* The onLoad attribute specified in the BODY start tag. */ const char * onunload; /* The onUnload attribute specified in the BODY start tag. */ /* Plug-In support, for fetching items */ struct plugin_stream * pstream; /* For fetching data on behalf of a Plug-In in another browser window. */ char * plugin_status; /* May hold a status message the Plug-In asked the browser to show. */ /* General page display information */ int background_colour; /* Background colour. */ int background_image; /* The image number of the background image (0..nimages - 1, -1 = none). */ int text_colour; /* Body text default colour. */ int link_colour; /* Unfollowed link colour. */ int used_colour; /* Followed link colour. */ int followed_colour; /* Following link colour. */ int selected_colour; /* Selected (highlighted) object colour. */ int antialias_colour; /* Colour to anti-alias text to, -1=don't anti-alias. */ /* */ int refo_time; /* Records time that a pending reformat has been waiting. */ int refo_line; /* The lowest line number pending for a reformat. */ /* */ int left_margin; /* Left hand basic page margin, millipoints. */ int right_margin; /* Right hand basic page margin, millipoints. */ int quote_margin; /* Extra page margin for blockquote chunks, millipoints. */ int leading; /* Line spacing, OS units. */ int left_indent; /* Multiplier on list etc. indents, millipoints. */ /* */ HStream * highlight; /* Token address of highlighted token (e.g. a pressed button), NULL=none. */ HStream * pointer_over; /* Token address that the pointer is over, for tokens representing links. */ int map_x; /* If pointer_over is an image map, the x coordinate offset (pixels). */ int map_y; /* Similarly, the y coordinate. */ HStream * last_token; /* Last token for which reformatting was definitely completed. */ HStream * selected; /* Token currently selected (for keyboard navigation). */ struct browser_data * selected_owner; /* Owner of the currently selected token (for frames control). */ /* */ display_type displayed; /* Type of information displayed in the window (see above). */ /* */ int encoding; /* Text encoding. */ encoding_priority encoding_priority; /* The priority of the encoding (eg user selected / meta specified). */ /* Font manager related information */ bitfield_set handles; /* Used font handles (bit set if handle is used). */ /* Other small data items which may */ /* pack in above the bitfield */ unsigned char last_char; /* Used for smart quotes and other text alteration handling. */ unsigned char progress_colour; /* Wimp foreground colour of the status bar progress indicator. */ /* Flags; generally, local config info */ unsigned button_bar :1; /* Button bar flag (0 = not present, 1 = present). */ unsigned url_bar :1; /* URL writable bar flag (0 = not present, 1 = present). */ unsigned status_bar :1; /* Status bar flag (0 = not present, 1 = present). */ unsigned all_in_top :1; /* There is only the top toolbar available. */ unsigned all_in_bottom :1; /* There is only the bottom toolbar available. */ unsigned merged_url :1; /* If 1, the URL writable and status display are to be merged. */ /* */ unsigned anim_handler :1; /* Set to 1 if the animation null event handler is registered. */ unsigned anim_drift :1; /* Set to 1 if the animation drift nulll event handler is registered. */ unsigned plugin_active :1; /* Set to 1 if a Plug-In is active for this browser. */ unsigned fetch_handler :1; /* Set to 1 if the fetch_a_page null event handler is registered. */ unsigned dialler_status :1; /* Set to 1 if the dialler status change message handler is registered. */ unsigned status_handler :1; /* Set to 1 if a handler for timeout on the status messages is registered. */ unsigned watching_resize :1; /* Zero if there is null events are not being claimed to watch the size of */ /* the window, or 1 if they are. */ /* */ unsigned dragging :1; /* 1 if a drag on the page is in progress, else 0. */ unsigned save_link :1; /* 1: Save next fetch as data even if parsable, else parse it if possible. */ unsigned page_is_text :1; /* 1: Page source is plain text, else it is HTML. */ unsigned small_fetch :1; /* 1: Browser is a 'small' fetch window, else 0. */ /* */ unsigned reloading :1; /* 1: This fetch is a reload (so don't use a proxy), else 0: it isn't. */ unsigned from_history :1; /* 1: This fetch is from a forwards/back action; else 0 (normal fetch). */ unsigned suspend_format :1; /* 1: Reformatting suspended due to error, else 0: Reformatting OK. */ unsigned clear_images :1; /* 1: Images have not been garbage collected from the last fetch yet. */ /* */ unsigned underline_links :1; /* Underline text links (0 = no, 1 = yes). */ unsigned show_foreground :1; /* Display images (0 = no, 1 = yes). */ unsigned show_background :1; /* 1: Don't draw background images 0: Draw them if present in document. */ unsigned use_source_cols :1; /* 1: Use source document's colours 0: Ignore them (use default colours). */ /* */ unsigned full_screen :1; /* 1: Browser window fills the screen, 0: window has border tools. */ unsigned full_size :1; /* 1: Browser window toggled Full Size, 0: window is smaller. */ /* */ unsigned frame_selected :1; /* 1: Browser window is selected (for frames), else is not selected. */ unsigned frame_hscroll :2; /* 0: No horiz scroll bar; 1: auto horiz bar; 2: bar always present. */ unsigned frame_vscroll :2; /* As frame_hscroll but for vertical scroll bar. */ /* */ unsigned in_image_map :1; /* 1: Image map selected for keyboard control, else 0: can move freely. */ unsigned allow_cancel :1; /* 1 if the fetch functions may cancel a previous fetch before proceeding. */ } browser_data; extern browser_data * last_browser; extern browser_data * highlight_frame; /* Global choices/preferences structure - user-configurable choices */ typedef struct global_choices { char * home_page; /* Default home page. */ /* */ unsigned int background_colour; /* Default background colour. */ unsigned int text_colour; /* Default text colour. */ unsigned int link_colour; /* Default link colour. */ unsigned int used_colour; /* Default used link colour. */ unsigned int followed_colour; /* Default following link colour. */ unsigned int selected_colour; /* Default selected (highlighted) link colour. */ /* */ int font_size; /* Default font size, 16ths of a point. */ int tt_aspect; /* Aspect ratio for teletype-style (fixed width) text. */ int encoding; /* Default text encoding (in absence of any specification in page) */ /* */ int left_margin; /* Left hand basic page margin, millipoints. */ int right_margin; /* Right hand basic page margin, millipoints. */ int quote_margin; /* Extra page margin for blockquote chunks, millipoints. */ int leading; /* Line spacing, OS units. */ int left_indent; /* Multiplier on list etc. indents, millipoints. */ /* */ char * hotlist_path; /* Pathname for saving/loading the hotlist. */ int auto_open_delay; /* Auto open delay time (centiseconds) for hotlist dirs, or 0 not to. */ int auto_scroll_delay; /* Auto scroll delay time (centiseconds) for hotlist window. */ int auto_scroll_margin; /* Auto scroll margin size (OS units) for hotlist (0 = no scrolling). */ /* */ char * history_path; /* Pathname for saving/loading the global history. */ int max_size; /* Maximum total size of history, in bytes (0 = unlimited). */ int expiry_age; /* Maximum age of history entries, in seconds (0 = unlimited). */ /* */ char * image_history_path; /* Pathname for saving/loading the image history. */ int image_max_size; /* Maximum total size of image history, in bytes (0 = unlimited). */ int image_expiry_age; /* Maximum age of image history entries, in seconds (0 = unlimited). */ /* */ int width; /* Default browser window width. */ int height; /* Default browser window height. */ int override_x; /* Possible X opening coordinate. */ int override_y; /* Possible Y opening coordinate. */ /* */ int refo_time; /* Time to queue up reformats in centiseconds, if 'refo_wait' is set. */ /* */ char * proxy_address; /* The base URL of the proxy server to use, including the protocol. */ #ifndef SINGLE_USER char * post_in; /* Path of !Post-in for multiuser operation. */ char * post_out; /* Path of !Post-out for multiuser operation. */ /* */ char * username; /* User name for multiuser operation. */ char * password; /* Password name for multiuser operation. */ #endif unsigned char maximages; /* Maximum number of images to fetch simultaneously. */ /* */ unsigned system_font :1; /* 1: Use system font for everything, 0: use outline fonts. */ /* */ unsigned underline_links :1; /* 1: Underline link text, 0: don't. */ unsigned use_source_cols :1; /* 1: Use document specified colours, 0: use defaults. */ unsigned show_foreground :1; /* 1: Delay image loading, 0: Load them immediately. */ unsigned show_background :1; /* 1: Display background images, 0: don't. */ /* */ unsigned table_outer :2; /* 0: 2D outer table borders, 1: Auto, 2: always 3D, 3: never plot. */ unsigned table_inner :2; /* 0: 2D inner table borders, 1: Auto, 2: always 3D, 3: never plot. */ /* */ unsigned client_pull :1; /* If 1, client pull is enabled, else disabled. */ unsigned support_frames :1; /* 0 - don't support frames in documents; 1 - do. */ unsigned support_object :1; /* 0 - don't support OBJECT, EMBED and APPLET; 1 - do. */ unsigned support_tables :1; /* 0 - don't support TABLE and related tags; 1 - do. */ unsigned plugin_control :2; /* 0 - never start them, 1 - start on redraw, 2 - start ASAP. */ unsigned see_fetches :1; /* 0 - don't see fetches for Plug-Ins, 1 - see small fetch window. */ /* */ unsigned save_hotlist :2; /* 0 - never save hotlist, 1 - save on quit, 2 - save for new URLs. */ unsigned add_hotlist :1; /* 0 - new items added to top, 1 - items added to bottom of the list. */ unsigned hotlist_show :1; /* 0 - show descriptions, 1 - show URLs in the hotlist. */ /* */ unsigned show_urls :1; /* 0 - show titles in History menu, else always show URLs. */ unsigned save_history :2; /* 0 - don't save, 1 - save on exit, 2 - save on global history add. */ unsigned save_image_history :2; /* 0 - don't save, 1 - save on exit, 2 - save on image history add. */ /* */ unsigned url_bar :1; /* Attach a URL bar to a window upon creation (1 = yes, 0 = no). */ unsigned button_bar :1; /* Attach a button bar to a window upon creation (1 = yes, 0 = no). */ unsigned status_bar :1; /* Attach a status bar to a window upon creation (1 = yes, 0 = no). */ unsigned move_gadgets :2; /* 0 - don't move, 1 - move after resize, 2 = move during resize. */ /* */ unsigned solid_resize :2; /* Frame resizes; 0 - dashed, 2 - solid, 1 - check CMOS resize bit. */ unsigned full_screen :1; /* 0 - don't start up Full Screen, else 1. */ unsigned h_scroll :2; /* 0 - no hscroll in Full Screen, 1 - auto add/remove, 2 - always. */ unsigned v_scroll :2; /* 0 - no vscroll in Full Screen, 1 - auto add/remove, 2 - always. */ /* */ unsigned refo_wait :1; /* 1: Reformat requests are queued for 'refo_time' centiseconds. */ unsigned refo_hang :1; /* 1: Reformatter will wait to know image sizes before continuing. */ /* */ unsigned fixed_pointer :1; /* 1: Pointer must not change shape over page, 1: it can change. */ unsigned highlight_links :1; /* 1: Objects are highlighted as the pointer moves over them. */ unsigned keyboard_ctrl :1; /* 1: Keyboard control of link selection enabled, else disabled. */ /* */ unsigned clone :1; /* 0 - use default user agent string, 1 = say Netscape compatible. */ unsigned use_proxy :1; /* 0 - don't use a proxy, 1 = use one at URL in Messages file entry. */ unsigned start_proxy :1; /* 0 - don't start proxy server, 1 = start it if not running already. */ } global_choices; extern global_choices choices; /* Global choices/preferences structure - non user-configurable controls */ typedef struct global_controls { int anim_delay; /* Minimum number of centiseconds between being called on nulls. */ /* */ int minimum_convergence; /* See Messages file non user-configurable options section. */ /* */ int show_help_for; /* For the status line, show help messages for this long (cs). */ int show_dstat_for; /* For the dialler display, show unusual status for this long (cs). */ int show_links_for; /* For the status line, show link contents for this long (cs). */ int show_misc_for; /* For the status line, show misc messages for this long (cs). */ int quantise; /* Quantise online time display to this many seconds. */ int progress_update_delay; /* Centisecond time between updates of the fetch progress counter. */ /* */ int minimum_frame_height; /* Minimum frame height, in OS units. */ int minimum_frame_width; /* Minimum frame width, in OS units. */ /* */ int back_off_at; /* Back off image fetches when this much memory, or less, is free. */ /* */ char ptrlnkactvx; /* Active point offsets in pixels from top left (exclusive): */ char ptrlnkactvy; /* Link. */ char ptrmapactvx; /* Map. */ char ptrmapactvy; /* */ char ptrudactvx; /* Up/down frame resize. */ char ptrudactvy; /* */ char ptrlractvx; /* Left/right frame resize. */ char ptrlractvy; /* */ char ptrudlractvx; /* Up/down/left/right frame resize. */ char ptrudlractvy; /* */ char ptrnoractvx; /* Can't resize this frame edge/corner. */ char ptrnoractvy; /* */ char ptrtosactvx; /* Hotlist window about to scroll. */ char ptrtosactvy; /* */ char ptrscractvx; /* Hotlist window scrolling. */ char ptrscractvy; /* */ /* */ unsigned char colour_progress; /* Either Controls_ColourProgress_NotAColour (CtrlDefs.h) to not */ /* colour the progress display when spooling data through the fetcher */ /* to a file, else a wimp colour. */ /* */ unsigned anim_drift :1; /* 0 - stop animation as soon as idle, 1 = drift over to 1st frame. */ unsigned dbox_anims :1; /* If set, appropriate components in dialogues will be animated. */ /* */ unsigned dont_grey :2; /* Controls greying of buttons and the history menu pop. */ unsigned swap_bars :1; /* Swap top and bottom toolbars around. */ unsigned back_window :1; /* If full screen, be a Back window to stop others going behind. */ unsigned use_small :1; /* If 1, small fetch windows will be used for object saves. */ /* */ unsigned claim_help :1; /* Claim Interactive Help messages and display text in status bar. */ /* */ unsigned append_status :1; /* In the absence of a byte counter append this info to status field. */ unsigned use_brackets :1; /* If appending, enclose the value in brackets. */ /* */ unsigned keep_highlight :1; /* 1: Frames will keep (re)highlighting as keyboard navigated. */ /* */ unsigned keep_caret :1; /* Grab the caret if it is lost (*use with caution!*). */ unsigned clear_first :1; /* 1: If popping up URL writable with key, clear first; else append. */ unsigned lock_to_line :1; /* Lock left/right arrows to only select items on the same line. */ unsigned ignore_adjust :1; /* Ignore adjust (treat as select) if it would open a second window. */ /* */ unsigned append_urls :1; /* Append the current page URL before visiting special locations. */ /* */ unsigned stop_proxy :1; /* Broadcast an AppControl Stop reason to web proxy when 'Stop' used. */ unsigned brick_wall :1; /* 1: Following links halts other fetches on page else they continue. */ unsigned refo_single :1; /* 1: Hold reformatter for up to 300cs or until page fully formatted. */ } global_controls; extern global_controls controls; /* Global error block to allow functions to hand back filled in */ /* custom error blocks, when necessary. */ extern _kernel_oserror erb; /* For keeping track of where dynamically created menus came from */ typedef enum menu_source { Menu_None, /* No menu opened / none recorded as being opened. */ Menu_Form, /* The menu was from a form. */ Menu_LocalHist, /* Local history menu. */ Menu_GlobalHist, /* Global history menu. */ Menu_Authorise /* The 'menu' was an authorisation dialogue. */ } menu_source; extern menu_source menusrc; extern void * menuhdl;