/* 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: Menu-related functions for the browser */ /* 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 "Frames.h" #include "Images.h" #include "Reformat.h" #include "Toolbars.h" #include "Windows.h" #include "Menus.h" /* Static function prototypes */ static void menus_toggle_bars (IdBlock * idb); static void menus_toggle_look (IdBlock * idb); static void menus_toggle_look_r (browser_data * b, ComponentId c, int t); 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 ChkTrace(menu_get_tick(0,o,c,&t)); t ? (t = 0) : (t = 1); ChkTrace(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; if (b->ancestor) ancestor = b->ancestor; else ancestor = b; ChkTrace(menu_set_tick(0, idb->self_id, URLbar, ancestor->url_bar)); ChkTrace(menu_set_tick(0, idb->self_id, ButtonBar, ancestor->button_bar)); ChkTrace(menu_set_tick(0, idb->self_id, StatusBar, ancestor->status_bar)); ChkTrace(menu_set_tick(0, idb->self_id, FullScreen, ancestor->full_screen)); } /* Set ticks according to general options. These are specific */ /* to each window. */ ChkTrace(menu_set_tick(0,idb->self_id,Underline,b->underlinelks)); ChkTrace(menu_set_tick(0,idb->self_id,DocumentCols,b->sourcecolours)); ChkTrace(menu_set_tick(0,idb->self_id,ShowImages,b->displayimages)); ChkTrace(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) ChkTrace(menu_set_fade(0, idb->self_id, SaveAsHTML, 0)); else ChkTrace(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) ChkTrace(menu_set_fade(0, idb->self_id, SaveSetAsHTML, 0)); else ChkTrace(menu_set_fade(0, idb->self_id, SaveSetAsHTML, 1)); #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. */ /*************************************************/ 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 ChkTrace(menu_set_tick(0,idb->self_id,CURLbar,choices.url_bar)); ChkTrace(menu_set_tick(0,idb->self_id,CButtonBar,choices.button_bar)); ChkTrace(menu_set_tick(0,idb->self_id,CStatusBar,choices.status_bar)); ChkTrace(menu_set_tick(0,idb->self_id,UnderlineLks,choices.underlinelks)); ChkTrace(menu_set_tick(0,idb->self_id,OverrideCols,choices.overridecols)); ChkTrace(menu_set_tick(0,idb->self_id,DelayImages,choices.delayimages)); ChkTrace(menu_set_tick(0,idb->self_id,Backgrounds,choices.displaybgs)); ChkTrace(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_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. */ if (b->ancestor) b = b->ancestor; #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 */ height = toolbars_url_height(b) + toolbars_button_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(idb->ancestor_id, InternalTopLeft); break; case ButtonBar: b->button_bar = t, toolbars_set_presence(idb->ancestor_id, InternalTopLeft); break; case StatusBar: b->status_bar = t, toolbars_set_presence(idb->ancestor_id, 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 } #ifdef TRACE if (tl & (1u<<4)) Printf("menus_toggle_bars: Successful, and exitting through reformat_shift_vertically()\n"); #endif /* Move any data inside the page as necessary */ ChkError(reformat_shift_vertically(b, 0, b->cell->nlines - 1, height - toolbars_url_height(b) - toolbars_button_height(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, (WimpOpenWindowBlock *) &state); } } /*************************************************/ /* 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 = b->ancestor; if (!ancestor) ancestor = b; /* Swap the menu's tick state */ t = menus_toggle_tick(idb->self_id,idb->self_component); /* Reflect changes in ancestor and children */ menus_toggle_look_r(ancestor, idb->self_component, t); /* Update the ancestor buttons */ toolbars_set_button_states(ancestor); #ifdef TRACE if (tl & (1u<<4)) Printf("menus_toggle_look: Successful\n"); #endif } /*************************************************/ /* menus_toggle_look_r() */ /* */ /* Recursive back-end to menus_toggle_took. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* which is the menu's ancestor for */ /* a top level call from */ /* menus_toggle_look, or else a */ /* child structure if calling itself */ /* recursively; */ /* */ /* Component ID selected in menu; */ /* */ /* 1 if the item is now on, 0 if it */ /* is now off. */ /*************************************************/ static void menus_toggle_look_r(browser_data * b, ComponentId c, int t) { int child; /* Scan the child tree */ if (b->nchildren) { for (child = 0; child < b->nchildren; child++) { menus_toggle_look_r(b->children[child], c, t); } } /* (Un)Set the relevant flag inside the browser_data structure */ switch (c) { case Underline: b->underlinelks = t; break; case DocumentCols: b->sourcecolours = t; break; case ShowImages: { b->displayimages = t; if (t) image_restart_fetches(b); } break; case ShowBackgrds: b->plainback = !t; break; case FullScreen: { /* Can only go Full Screen for ancestor objects */ if (b->ancestor) return; /* (So exit if this is a child) */ b->full_screen = t; /* This opens full screen, remembering the previous window size */ windows_open_full_screen(b, t, !t, find_behind(b->window_handle), choices.v_scroll, choices.h_scroll); /* Reformat the page */ reformat_format_from(b, -1, 1, -1); } break; #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 } /* Redraw the browser window to reflect the changes */ { WimpGetWindowStateBlock s; s.window_handle = b->window_handle; ChkError(wimp_get_window_state(&s)); ChkError(wimp_force_redraw(-1, s.visible_area.xmin, s.visible_area.ymin + toolbars_status_height(b), s.visible_area.xmax, s.visible_area.ymax - toolbars_button_height(b) - toolbars_url_height(b))); } } /*************************************************/ /* 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 } /*************************************************/