/* 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 : Encoding.c */ /* */ /* Purpose: Routines to handle the encoding menus. */ /* */ /* Author : K.J.Bracey */ /* */ /* History: 05-Sep-97: Created. */ /***************************************************/ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> #include <math.h> #include "swis.h" #include "wimp.h" #include "toolbox.h" #include "menu.h" #include "event.h" #include "Unicode/iso10646.h" #include "Global.h" #include "Utils.h" #include "Choices.h" #include "Encoding.h" /* Statics */ static ObjectId menu_id = NULL_ObjectId; static int ticked_encoding = 0xffffffff; static int entries_faded; static int encoding_get_encoding_item_r(ObjectId o, int encoding, ObjectId *encobjid, ComponentId *enccompid); /*************************************************/ /* encoding_fade_unusable_entries() */ /* */ /* Scan the Encoding menu, fading out encodings */ /* that aren't supported. */ /* */ /* Parameters: The object ID of the Encoding */ /* menu. */ /*************************************************/ static int encoding_fade_unusable_entries(ObjectId o) { /* How do we do this without an enumerate call? */ return 0; } /*************************************************/ /* encoding_tick_entry() */ /* */ /* Select or deselect the entry corresponding */ /* to a specified encoding. Parent menu items */ /* are also selected/deselected. */ /* */ /* Parameters: The object ID of the Encoding */ /* menu; */ /* */ /* The number of the encoding; */ /* */ /* 0 to untick, 1 to tick. */ /* */ /* Returns: 1 if entry found, 0 if not. */ /* */ /* Assumes: Parent menu items have */ /* consecutive component IDs */ /* starting at 0x11000 in each menu; */ /* */ /* The component ID of an encoding */ /* item is the number of the */ /* encoding it represents; */ /* */ /* A given encoding is only */ /* represented once in the menu */ /* tree. */ /*************************************************/ static int encoding_tick_entry(ObjectId o, int enc, int state) { ComponentId c; _kernel_oserror *e; e = menu_set_tick(0, o, enc, state); if (!e) return 1; /* The encoding isn't in this menu, so scan the submenus. */ for (c = 0x11000; ; c++) { ObjectId sub; e = menu_get_sub_menu_show(0, o, c, &sub); /* If an error - component not found - end of submenus */ if (e) return 0; if (sub == NULL_ObjectId) continue; if (encoding_tick_entry(sub, enc, state)) { ChkError(menu_set_tick(0, o, c, state)); return 1; } } } /*************************************************/ /* encoding_prepare_menu() */ /* */ /* Ensure that the state of the Encoding menu */ /* is correct for a supplied encoding_priority */ /* and encoding type. */ /* */ /* Parameters: Object ID of the Encoding menu; */ /* */ /* The encoding priority */ /* */ /* The encoding number */ /* */ /* Assumes: The "From document" item is */ /* component 0x11FFF in the top- */ /* level menu; */ /* */ /* The Encoding menu is a shared */ /* object. */ /*************************************************/ void encoding_prepare_menu(ObjectId o, encoding_priority encoding_priority, int encoding) { menu_set_tick(0, o, 0x11FFF, encoding_priority != priority_user); if (ticked_encoding != encoding) { if (ticked_encoding) encoding_tick_entry(o, ticked_encoding, 0); encoding_tick_entry(o, encoding, 1); ticked_encoding = encoding; } } /*************************************************/ /* encoding_select() */ /* */ /* Event handler for the selection of an */ /* encoding (EEncoding_Select). */ /* */ /* Parameters are as for a standard Toolbox */ /* event handler. */ /* */ /* Assumes: The top-level Encoding menu is an */ /* ancestor object; */ /* */ /* The component ID is the number of */ /* the encoding to select. */ /*************************************************/ int encoding_select(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { browser_data * b; _kernel_oserror *e; ChkError(toolbox_get_client_handle(0, idb->ancestor_id, (void *) &b)); if (!is_known_browser(b)) { ObjectId ancestor; e = toolbox_get_ancestor(0, menu_id, &ancestor, NULL); if (!e && ancestor == choices_windowid && new_choices) { new_choices->encoding = idb->self_component; choices_set_encoding_field(); encoding_prepare_menu(menu_id, priority_default, new_choices->encoding); return 1; } else { return 0; } } else { b->encoding = idb->self_component; b->encoding_priority = priority_user; encoding_prepare_menu(menu_id, b->encoding_priority, b->encoding); } return 1; } /*************************************************/ /* encoding_from_document_select() */ /* */ /* Handle the selection of the "From document" */ /* menu entry. */ /* */ /* Parameters are as for a standard Toolbox */ /* event handler. */ /*************************************************/ int encoding_from_document_select(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { browser_data * b; ChkError(toolbox_get_client_handle(0, idb->ancestor_id, (void *) &b)); if (!is_known_browser(b)) return 0; if (b->encoding_priority == priority_user) { b->encoding_priority = priority_default; } else { b->encoding_priority = priority_user; } encoding_prepare_menu(menu_id, b->encoding_priority, b->encoding); return 1; } /*************************************************/ /* encoding_show_menu() */ /* */ /* Set up the Encoding menu before it is shown. */ /* */ /* Parameters are as for a standard Toolbox */ /* event handler. */ /* */ /* Assumes: The "From document" item is */ /* component 0x11FFF in the top- */ /* level menu; */ /*************************************************/ int encoding_show_menu(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { browser_data * b; ChkError(toolbox_get_client_handle(0, idb->ancestor_id, (void *) &b)); if (!is_known_browser(b)) { if (idb->ancestor_id == choices_windowid && new_choices) { /* Fade "From document" item as it is not relevant to choices */ menu_set_fade(0, idb->self_id, 0x11FFF, 1); encoding_prepare_menu(menu_id, priority_default, new_choices->encoding); toolbox_set_client_handle(0, idb->self_id, NULL); return 1; } else { return 0; } } else { /* Unfade "From document" item as it is relevant to browser windows */ menu_set_fade(0, idb->self_id, 0x11FFF, 0); if (!entries_faded) { encoding_fade_unusable_entries(idb->self_id); entries_faded = 1; } toolbox_set_client_handle(0, idb->self_id, b); encoding_prepare_menu(menu_id, b->encoding_priority, b->encoding); } return 1; } /*************************************************/ /* encoding_changed_by_meta() */ /* */ /* Called by HTMLLib when a META tag that */ /* changes encoding is found. Update the */ /* browser_data struct and the menu accordingly. */ /* */ /* This routine is registered with HTMLLib in */ /* html_get_next_token() when the parse starts. */ /* */ /* Parameters: The number of the new encoding; */ /* */ /* Pointer to the relevant */ /* browser_data struct. */ /*************************************************/ void encoding_changed_by_meta(int encoding, void * handle) { browser_data * b = (browser_data *) handle; b->encoding = encoding; b->encoding_priority = priority_meta; encoding_update_menus(b); } /*************************************************/ /* encoding_update_menus() */ /* */ /* Update the Encoding menu if it is currently */ /* open for the specified browser. */ /* */ /* Parameters: Pointer to the browser_data */ /* whose encoding has changed. */ /*************************************************/ void encoding_update_menus(browser_data * b) { if (menu_id != NULL_ObjectId) { browser_data * b2; if (toolbox_get_client_handle(0, menu_id, (void *) &b2)) return; if (b2 == b) encoding_prepare_menu(menu_id, b->encoding_priority, b->encoding); } } /*************************************************/ /* encoding_get_encoding_item() */ /* */ /* Finds the menu item containing the name */ /* of the specified encoding. */ /* */ /* Parameters: the required encoding */ /* */ /* Pointer to the objectid to return */ /* information in */ /* */ /* Pointer to the componentid to */ /* return the information in. */ /* */ /* Returns: 1 if the encoding was found */ /* 0 if it was not */ /* */ /* Assumes: Parent menu items have */ /* consecutive component IDs */ /* starting at 0x11000 in each menu; */ /* */ /* The component ID of an encoding */ /* item is the number of the */ /* encoding it represents; */ /*************************************************/ int encoding_get_encoding_item(int encoding, ObjectId * encobjid, ComponentId * enccompid) { return encoding_get_encoding_item_r(menu_id, encoding, encobjid, enccompid); } /*************************************************/ /* encoding_get_encoding_item_r() */ /* */ /* Recursive backend to */ /* encoding_get_encoding_item */ /*************************************************/ static int encoding_get_encoding_item_r(ObjectId o, int encoding, ObjectId * encobjid, ComponentId * enccompid) { _kernel_oserror *e; ComponentId c; int state; /* We don't really want to know if this item is ticked, we just want to see if the item exists */ e = menu_get_tick(0, o, encoding, &state); if (!e) { *encobjid = o; *enccompid = encoding; return 1; } for (c = 0x11000; ; c++) { ObjectId sub; e = menu_get_sub_menu_show(0, o, c, &sub); /* If an error - component not found - end of submenus */ if (e) return 0; if (sub == NULL_ObjectId) continue; if (encoding_get_encoding_item_r(sub, encoding, encobjid, enccompid)) return 1; } } /*************************************************/ /* encoding_init() */ /* */ /* Initialises the encoding system - basically, */ /* creates the menu now (rather than letting it */ /* autocreate later - it's a shared object) so */ /* that the Object ID is known. */ /*************************************************/ _kernel_oserror *encoding_init(void) { /* Encoding menu may not be there, so this should be able to */ /* fail silently. */ toolbox_create_object(0, "Encoding", &menu_id); return NULL; } /*************************************************/ /* encoding_get_menuid(void) */ /* */ /* Returns the ObjectId of the main encoding */ /* menu. */ /*************************************************/ ObjectId encoding_get_menuid(void) { return menu_id; }