/* 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 : Menus.c */ /* */ /* Purpose: Handle browser menus. */ /* */ /* Author : A.D.Hodgkinson */ /* */ /* History: 20-Nov-96: Created */ /***************************************************/ #include <stdlib.h> #include <string.h> #include "swis.h" #include "wimp.h" #include "wimplib.h" #include "event.h" #include "toolbox.h" #include "window.h" #include "menu.h" #include "svcprint.h" #include "Global.h" #include "FromROSLib.h" #include "TBEvents.h" #include "Utils.h" #include "Browser.h" #include "Frames.h" #include "Images.h" #include "Reformat.h" #include "Save.h" /* (For menu component IDs) */ #include "Toolbars.h" #include "Windows.h" #include "Menus.h" /* Local statics */ static browser_data * main_menu_browser = NULL; static HStream * main_menu_opened_over = NULL; /* Static function prototypes */ static void menus_toggle_bars (IdBlock * idb); static void menus_toggle_look (IdBlock * idb); static void menus_choices_bars (IdBlock * idb); static void menus_choices_other (IdBlock * idb); /*************************************************/ /* menus_item_selected() */ /* */ /* Following a Menu_Selection event from the */ /* toolbox, work out what to do with it. */ /* */ /* Parameters are as for a standard Toolbox */ /* event handler. */ /*************************************************/ int menus_item_selected(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { #ifdef TRACE if (tl & (1u<<4)) Printf("menus_item_selected: Called\n"); #endif switch (idb->self_component) { case URLbar: case ButtonBar: case StatusBar: menus_toggle_bars(idb); break; case FullScreen: case Underline: case DocumentCols: case ShowImages: case ShowBackgrds: menus_toggle_look(idb); break; case CURLbar: case CButtonBar: case CStatusBar: menus_choices_bars(idb); break; case DelayImages: case Backgrounds: case UnderlineLks: case OverrideCols: case CFullScreen: menus_choices_other(idb); break; default: return 0; } #ifdef TRACE if (tl & (1u<<4)) Printf("menus_item_selected: Successful\n"); #endif return 1; } /*************************************************/ /* menus_toggle_tick() */ /* */ /* Toggles the state of a given tick in a menu. */ /* */ /* Parameters: The object ID of the menu; */ /* */ /* The component ID to alter. */ /* */ /* Returns: 1 if item is now ticked, else 0. */ /*************************************************/ int menus_toggle_tick(ObjectId o, ComponentId c) { int t = 0; #ifdef TRACE if (tl & (1u<<4)) Printf("menus_toggle_tick: Called\n"); #endif menu_get_tick(0,o,c,&t); t ? (t = 0) : (t = 1); menu_set_tick(0,o,c,t); #ifdef TRACE if (tl & (1u<<4)) Printf("menus_toggle_tick: Successful\n"); #endif return t; } /*************************************************/ /* menus_show_utils() */ /* */ /* Called when the utils menu is about to be */ /* opened from a main menu in a browser window. */ /* Handles turning ticks on and off in items. */ /* Parameters are as standard for a Toolbox */ /* event handler */ /*************************************************/ int menus_show_utils(int eventcode, ToolboxEvent * event, IdBlock * idb, void *handle) { browser_data * b; #ifdef TRACE if (tl & (1u<<4)) Printf("menus_show_utils: Called\n"); #endif /* Find the browser_data structure for the browser (ancestor) window */ ChkError(toolbox_get_client_handle(0,idb->ancestor_id,(void *) &b)); #ifdef TRACE if (tl & (1u<<4)) Printf("menus_show_utils: For ancestor client handle %p\n",(void *) b); #endif /* Set ticks according to the current toolbar status. */ /* This should be for an ancestor window, and not for */ /* any child frames. Similarly, the Full Screen */ /* state comes from the ancestor browser. */ { browser_data * ancestor = utils_ancestor(b); menu_set_tick(0, idb->self_id, URLbar, ancestor->url_bar); menu_set_tick(0, idb->self_id, ButtonBar, ancestor->button_bar); menu_set_tick(0, idb->self_id, StatusBar, ancestor->status_bar); menu_set_tick(0, idb->self_id, FullScreen, ancestor->full_screen); } /* Set ticks according to general options. These are specific */ /* to each window. */ menu_set_tick(0, idb->self_id, Underline, b->underlinelks); menu_set_tick(0, idb->self_id, DocumentCols, b->sourcecolours); menu_set_tick(0, idb->self_id, ShowImages, b->displayimages); menu_set_tick(0, idb->self_id, ShowBackgrds, !b->plainback); #ifdef TRACE if (tl & (1u<<4)) Printf("menus_show_utils: Successful\n"); #endif return 1; } /*************************************************/ /* menus_show_file() */ /* */ /* Called when the file submenu is about to be */ /* opened from a browser window's main menu. */ /* Deals with greying of entries as appropriate. */ /*************************************************/ int menus_show_file(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { browser_data * b; #ifdef TRACE if (tl & (1u<<4)) Printf("menus_show_file: Called\n"); #endif /* Find the browser_data structure for the browser (ancestor) window */ ChkError(toolbox_get_client_handle(0,idb->ancestor_id,(void *) &b)); #ifdef TRACE if (tl & (1u<<4)) Printf("menus_show_file: For ancestor client handle %p\n",(void *) b); #endif /* If there is HTML source present, unfade the Save entry - else fade it out */ if (b->source) menu_set_fade(0, idb->self_id, SaveAsHTML, 0); else menu_set_fade(0, idb->self_id, SaveAsHTML, 1); /* If there is a parent with HTML source, unfade the Save frames entry; else */ /* fade it out. */ if (b->ancestor) menu_set_fade(0, idb->self_id, SaveSetAsHTML, 0); else menu_set_fade(0, idb->self_id, SaveSetAsHTML, 1); /* If the browser has children, you can't print from it */ if (b->nchildren) menu_set_fade(0, idb->self_id, FilePrint, 1); else menu_set_fade(0, idb->self_id, FilePrint, 0); #ifdef TRACE if (tl & (1u<<4)) Printf("menus_show_file: Successful\n"); #endif return 1; } /*************************************************/ /* menus_show_choices() */ /* */ /* Called when the choices menu is about to be */ /* opened from the icon bar menu. Handles */ /* turning ticks on and off depending on the */ /* Messages file's choices entries. */ /* */ /* Parameters are as standard for a Toolbox */ /* event handler. */ /*************************************************/ int menus_show_choices(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { #ifdef TRACE if (tl & (1u<<4)) Printf("menus_show_choices: Called\n"); #endif menu_set_tick(0,idb->self_id,CURLbar,choices.url_bar); menu_set_tick(0,idb->self_id,CButtonBar,choices.button_bar); menu_set_tick(0,idb->self_id,CStatusBar,choices.status_bar); menu_set_tick(0,idb->self_id,UnderlineLks,choices.underlinelks); menu_set_tick(0,idb->self_id,OverrideCols,choices.overridecols); menu_set_tick(0,idb->self_id,DelayImages,choices.delayimages); menu_set_tick(0,idb->self_id,Backgrounds,choices.displaybgs); menu_set_tick(0,idb->self_id,CFullScreen,choices.full_screen); #ifdef TRACE if (tl & (1u<<4)) Printf("menus_show_choices: Successful\n"); #endif return 1; } /*************************************************/ /* menus_show_main() */ /* */ /* Called before the main menu is showed from a */ /* document window. */ /* */ /* Parameters are as standard for a Toolbox */ /* event handler. */ /*************************************************/ int menus_show_main(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { WimpGetPointerInfoBlock info; browser_data * b; ChkError(wimp_get_pointer_info(&info)); ChkError(toolbox_get_client_handle(0, idb->ancestor_id, (void *) &b)); if (!is_known_browser(b)) return 0; main_menu_browser = b; main_menu_opened_over = browser_get_pointer_token(b, &info, NULL, NULL); return 1; } /*************************************************/ /* menus_hide_main() */ /* */ /* Called before the main menu is hidden. */ /* */ /* Parameters are as standard for a Toolbox */ /* event handler. */ /*************************************************/ int menus_hide_main(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { main_menu_opened_over = NULL; main_menu_browser = NULL; return 1; } /*************************************************/ /* menus_close_main_if_mine() */ /* */ /* If a main menu is open and its origin was the */ /* given browser, close it. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the menu. */ /* */ /* Returns: 1 if the menu was closed, else 0. */ /*************************************************/ int menus_close_main_if_mine(browser_data * b) { if (b && b == main_menu_browser) { _swix(Wimp_CreateMenu, _IN(1), -1); return 1; } return 0; } /*************************************************/ /* menus_toggle_bars() */ /* */ /* Called when one of the Utils menu items that */ /* turns info/toolbars on and off is selected. */ /* */ /* The item is ticked or unticked as necessary */ /* and the relevant toolbar turned on or off. */ /* */ /* Parameters: Pointer to an ID block, as given */ /* by the Toolbox when it raises an */ /* event. */ /*************************************************/ static void menus_toggle_bars(IdBlock * idb) { int t = 0, height; browser_data * b; #ifdef TRACE if (tl & (1u<<4)) Printf("menus_toggle_bars: Called\n"); #endif /* Find the browser_data structure for the browser (ancestor) window */ ChkError(toolbox_get_client_handle(0, idb->ancestor_id, (void *) &b)); /* Bars are only attached to the ancestor browser_data struct, */ /* not to any child frames. So want to point b to this. */ b = utils_ancestor(b); #ifdef TRACE if (tl & (1u<<4)) Printf("menus_toggle_bars: For ancestor client handle %p\n",(void *) b); #endif /* Swap the menu's tick state */ t = menus_toggle_tick(idb->self_id, idb->self_component); /* Remember height of top toolbar */ if (!fixed.swapbars) height = toolbars_button_height(b) + toolbars_url_height(b); else height = toolbars_status_height(b); /* For URL and Button bars, need to move the page contents up and down, */ /* so remember the total bar height before removing or adding one of */ /* those bars. For the status bar it doesn't matter. */ switch (idb->self_component) { case URLbar: b->url_bar = t, toolbars_set_presence(b, InternalTopLeft); break; case ButtonBar: b->button_bar = t, toolbars_set_presence(b, InternalTopLeft); break; case StatusBar: b->status_bar = t, toolbars_set_presence(b, InternalBottomLeft); break; #ifdef TRACE default: { _kernel_oserror e; e.errnum = Utils_Error_Custom_Normal; strncpy(e.errmess,"Toolbar toggle handle not understood in menus_toggle_bars.",252); show_error_cont(&e); } #endif } /* Move any data inside the page as necessary */ if (!fixed.swapbars) { ChkError(reformat_shift_vertically(b, 0, b->cell->nlines - 1, height - toolbars_url_height(b) - toolbars_button_height(b))); } else { ChkError(reformat_shift_vertically(b, 0, b->cell->nlines - 1, height - toolbars_status_height(b))); } ChkError(reformat_check_extent(b)); /* If there are any frames on the page, resize them */ if (b->nchildren) { WimpGetWindowStateBlock state; state.window_handle = b->window_handle; ChkError(wimp_get_window_state(&state)); frames_resize_frameset(b, &state.visible_area); } #ifdef TRACE if (tl & (1u<<4)) Printf("menus_toggle_bars: Successful\n"); #endif } /*************************************************/ /* menus_toggle_look() */ /* */ /* Called when one of the Utils menu items not */ /* related to toolbars is selected. */ /* */ /* The item is ticked or unticked as necessary */ /* and the relevant visual aspect of the browser */ /* window turned on or off. */ /* */ /* Any child frames at this frame level or */ /* higher will inherit the new characteristics. */ /* */ /* Parameters: Pointer to an ID block, as given */ /* by the Toolbox when it raises an */ /* event. */ /*************************************************/ static void menus_toggle_look(IdBlock * idb) { int t = 0; ObjectId browser; browser_data * b; browser_data * ancestor; #ifdef TRACE if (tl & (1u<<4)) Printf("menus_toggle_look: Called\n"); #endif /* Find the browser_data structure for the browser (ancestor) window */ browser = idb->ancestor_id; ChkError(toolbox_get_client_handle(0, browser, (void *) &b)); #ifdef TRACE if (tl & (1u<<4)) Printf("menus_toggle_look: For ancestor client handle %p\n",(void *) b); #endif ancestor = utils_ancestor(b); /* Swap the menu's tick state */ t = menus_toggle_tick(idb->self_id, idb->self_component); /* Reflect changes in ancestor and children */ /* (Un)Set the relevant flag inside the browser_data structure */ switch (idb->self_component) { case Underline: { ChkError(browser_set_look(b, idb->self_id, t, -1, -1, -1)); } break; case DocumentCols: { ChkError(browser_set_look(b, idb->self_id, -1, t, -1, -1)); } break; case ShowImages: { ChkError(browser_set_look(b, idb->self_id, -1, -1, t, -1)); } break; case ShowBackgrds: { ChkError(browser_set_look(b, idb->self_id, -1, -1, -1, !t)); } break; case FullScreen: { browser_data * ancestor = utils_ancestor(b); /* Can only go Full Screen for ancestor objects */ ancestor->full_screen = t; /* This opens full screen, remembering the previous window size */ ChkError(windows_open_full_screen(ancestor, t, !t, choices.v_scroll, choices.h_scroll)); /* Reformat the page */ ChkError(reformat_format_from(ancestor, -1, 1, -1)); } break; /* Report error for default case in TRACE builds as a warning */ /* to the programmer only. */ #ifdef TRACE default: { _kernel_oserror e; if (b->ancestor) return; /* Avoid giving error for all the child windows */ e.errnum = Utils_Error_Custom_Normal; strncpy(e.errmess,"Menu selection not understood in menus_toggle_look.",252); show_error_cont(&e); } #endif } /* Update the ancestor buttons */ ChkError(toolbars_set_button_states(ancestor)); #ifdef TRACE if (tl & (1u<<4)) Printf("menus_toggle_look: Successful\n"); #endif } /*************************************************/ /* menus_choices_bars() */ /* */ /* Called when one of the Choices menu items */ /* relating to toolbars is selected. Toggles the */ /* menu item's tick and (un)sets the relevant */ /* bit in the global Choices. */ /* */ /* Parameters: Pointer to an ID block, as given */ /* by the Toolbox when it raises an */ /* event. */ /*************************************************/ static void menus_choices_bars(IdBlock * idb) { int t; #ifdef TRACE if (tl & (1u<<4)) Printf("menus_choices_bars: Called\n"); #endif t = menus_toggle_tick(idb->self_id,idb->self_component); switch (idb->self_component) { case CURLbar:choices.url_bar = t; break; case CButtonBar:choices.button_bar = t; break; case CStatusBar:choices.status_bar = t; break; #ifdef TRACE default: { _kernel_oserror e; e.errnum = Utils_Error_Custom_Normal; strncpy(e.errmess,"Toolbar toggle handle not understood in menus_choices_bars.",252); show_error_cont(&e); } #endif } #ifdef TRACE if (tl & (1u<<4)) Printf("menus_choices_bars: Successful\n"); #endif } /*************************************************/ /* menus_choices_other() */ /* */ /* Called when one of the Choices menu items */ /* relating to something other than toolbars is */ /* selected. Toggles the menu item's tick and */ /* (un)sets the relevant bit in the global */ /* Choices. */ /* */ /* Parameters: Pointer to an ID block, as given */ /* by the Toolbox when it raises an */ /* event. */ /*************************************************/ static void menus_choices_other(IdBlock * idb) { int t; #ifdef TRACE if (tl & (1u<<4)) Printf("menus_choices_other: Called\n"); #endif t = menus_toggle_tick(idb->self_id,idb->self_component); switch (idb->self_component) { case OverrideCols: choices.overridecols = t; break; case UnderlineLks: choices.underlinelks = t; break; case Backgrounds: choices.displaybgs = t; break; case DelayImages: choices.delayimages = t; break; case CFullScreen: choices.full_screen = t; break; #ifdef TRACE default: { _kernel_oserror e; e.errnum = Utils_Error_Custom_Normal; strncpy(e.errmess,"Menu selection item not understood in menus_choices_other.",252); show_error_cont(&e); } #endif } toolbars_set_all_button_states(); #ifdef TRACE if (tl & (1u<<4)) Printf("menus_choices_other: Successful\n"); #endif } /*************************************************/ /* menus_main_opened_over() */ /* */ /* When the main menu is opened, it tries to see */ /* if the pointer was over a specific token. */ /* If so, it records this information for */ /* future use (see menus_show_main). This */ /* function returns that token address, or NULL */ /* if the menu isn't open / no token could be */ /* determined. */ /* */ /* Returns: Pointer to the token the pointer */ /* was over when the main menu was */ /* opened, or NULL if the menu is no */ /* longer open / no token could be */ /* determined when it was opened. */ /*************************************************/ HStream * menus_main_opened_over(void) { return main_menu_opened_over; } /*************************************************/ /* menus_main_over_browser() */ /* */ /* Companion function to menus_main_opened_over, */ /* so see that for details. */ /* */ /* Returns: Pointer to the browser_data */ /* struct representing the browser */ /* the main menu was opened from, if */ /* any (NULL if not). */ /*************************************************/ browser_data * menus_main_over_browser(void) { return main_menu_browser; }