/* 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 : Find.c */ /* */ /* Purpose: Functions relating to the Find */ /* dialogue box. */ /* */ /* Author : A.D.Hodgkinson */ /* */ /* History: 17-Apr-97: Created. */ /* 13-Mar-98: Working code implemented. */ /***************************************************/ #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 "svcprint.h" #include "Global.h" #include "Utils.h" #include "Browser.h" #include "Fetch.h" #include "Toolbars.h" #include "Windows.h" #include "Find.h" /* Static function prototypes */ static int find_from_start_toggled (int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle); static int find_ok (int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle); static int find_cancel (int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle); static int find_string_has_changed (int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle); /* Local statics */ static ObjectId id = NULL_ObjectId; static int fs_so = 0; static browser_data * over_b = NULL; static HStream * last_t = NULL; static int last_o = 0; /*************************************************/ /* find_to_be_shown() */ /* */ /* Called when the EFindToBeShown event is */ /* generated, typically when the Find window is */ /* about to be shown. Handles any icon */ /* processing commands in the writable. */ /* */ /* Parameters are as standard for a Toolbox */ /* event handler. */ /*************************************************/ int find_to_be_shown(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { char text[Limits_FindWrit]; id = idb->self_id; ChkError(windows_process_component_text(idb->self_id, FindWrit, text, sizeof(text), 0, 1)); /* 'Local' event handlers */ ChkError(event_register_toolbox_handler(idb->self_id, EFindOK, find_ok, NULL)); ChkError(event_register_toolbox_handler(idb->self_id, EFindCancel, find_cancel, NULL)); ChkError(event_register_toolbox_handler(idb->self_id, EFindFromStart, find_from_start_toggled, NULL)); ChkError(event_register_toolbox_handler(idb->self_id, WritableField_ValueChanged, find_string_has_changed, NULL)); /* Animation handler, if required */ if ( controls.dbox_anims && !gadget_get_type(0, idb->self_id, StatusBarAnimAnim, NULL) ) register_null_claimant(Wimp_ENull, toolbars_animate_slow, (void *) idb->self_id); /* Try to find the browser we were opened over */ if (toolbox_get_client_handle(0, idb->ancestor_id, (void *) &over_b)) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Message; strcpy(erb.errmess, "Can't find ancestor browser in find_to_be_shown"); show_error_ret(&erb); #endif over_b = last_browser; } if (!is_known_browser(over_b)) over_b = last_browser; /* Can't do much if we end up with no browser! */ if (!over_b) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Message; strcpy(erb.errmess, "Ended up with a NULL browser pointer in find_to_be_shown"); show_error_ret(&erb); #endif return 0; } /* Make sure the last found token / data offset stores are cleared */ last_t = NULL; last_o = 0; /* If From Start was automatically toggled off, turn it */ /* back on again. */ if (fs_so) { optionbutton_set_state(0, idb->self_id, FindFromStart, 1); } /* Make sure the forwards/backwards radios are up to date */ find_from_start_toggled(eventcode, event, idb, handle); return 1; } /*************************************************/ /* find_hidden() */ /* */ /* Called when the EFindHidden event is */ /* generated, typically when the Find window */ /* is closed. */ /* */ /* Parameters are as standard for a Toolbox */ /* event handler. */ /*************************************************/ int find_hidden(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { /* Remove any 'local' event handlers */ if ( controls.dbox_anims && !gadget_get_type(0, idb->self_id, StatusBarAnimAnim, NULL) ) deregister_null_claimant(Wimp_ENull, toolbars_animate_slow, (void *) idb->self_id); ChkError(event_deregister_toolbox_handlers_for_object(idb->self_id)); return 1; } /*************************************************/ /* find_close() */ /* */ /* Closes the Find dialogue, assuming its Object */ /* ID is stored in 'id'. */ /*************************************************/ void find_close(void) { over_b = NULL; last_t = NULL; last_o = 0; toolbox_hide_object(0, id); } /*************************************************/ /* find_from_start_toggled() */ /* */ /* Called when the EFindFromStart event is */ /* generated, typically when the 'From start' */ /* option in the Find dialogue box is toggled. */ /* */ /* Parameters are as standard for a Toolbox */ /* event handler. */ /*************************************************/ static int find_from_start_toggled(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { int state; /* Clear the 'automatically switched off' flag */ fs_so = 0; /* Get the option button state */ if (!optionbutton_get_state(0, idb->self_id, FindFromStart, &state)) { /* If switched on, grey out the 'Forwards' and 'Backwards' radios */ if (state) { set_gadget_state(idb->self_id, FindForwards, 1); set_gadget_state(idb->self_id, FindBackwards, 1); } /* Otherwise, ungrey them */ else { set_gadget_state(idb->self_id, FindForwards, 0); set_gadget_state(idb->self_id, FindBackwards, 0); } } return 1; } /*************************************************/ /* find_ok() */ /* */ /* Called when the EFindOK event is generated, */ /* typically from the 'OK' button in the Find */ /* dialogue box. */ /* */ /* Parameters are as standard for a Toolbox */ /* event handler. */ /*************************************************/ static int find_ok(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { WimpGetWindowStateBlock state; reformat_cell * cell; int line; HStream * found = NULL; int offset; char find[Limits_FindWrit]; int cs; int forwards, from_start; /* Get the search string */ ChkError(writablefield_get_value(0, idb->self_id, FindWrit, find, sizeof(find), NULL)); /* Searching from the start? If we can't read the value, */ /* default to 'from start' for this, unless we'd turned */ /* that off deliberately. */ if ( optionbutton_get_state(0, idb->self_id, FindFromStart, &from_start) ) from_start = !fs_so; /* If searching from the start, forwards is implicit; */ /* otherwise, read the 'Forwards' radio, and default */ /* to 'forwards' if this can't be read. */ if ( from_start || radiobutton_get_state(0, idb->self_id, FindForwards, &forwards, NULL) ) forwards = 1; /* Case insensitive, unless we can find out otherwise */ if ( optionbutton_get_state(0, idb->self_id, FindCaseSensitive, &cs) ) cs = 0; /* If we haven't found a token before, try to find */ /* one closest to the top left of the window. */ if (!last_t) { state.window_handle = over_b->window_handle; ChkError(wimp_get_window_state(&state)); line = browser_top_line(over_b, &cell, &state, 0); if (!cell) last_t = 0; else { int chunk; if (line < 0) line = 0; if (line > cell->nlines) last_t = 0; else { chunk = cell->ldata[line].chunks; if (chunk < 0) last_t = 0; else last_t = cell->cdata[chunk].t; } } /* If there's no token, must start at the top - */ /* otherwise, it's up to the user. */ if (!last_t) { optionbutton_set_state(0, idb->self_id, FindFromStart, 1); last_t = over_b->stream; set_gadget_state(idb->self_id, FindFromStart, 1); } else set_gadget_state(idb->self_id, FindFromStart, 0); last_o = 0; } /* Try to find the search string */ if (is_known_browser(over_b) && last_t) { found = fetch_find_text_token(over_b, find, from_start ? NULL : last_t, from_start ? 0 : last_o, &offset, cs, forwards); } /* Beep if nothing is found... */ if (!found) Beep; /* (See Utils.h) */ /* Otherwise, show the item */ else { last_t = found; last_o = offset; if ( !browser_show_token(over_b, last_t, last_o) ) Beep; else { /* If the item is successfully shown, there may be another. */ /* In that case, we want to turn off 'From start', if it is */ /* turned on, and make sure we're continuing forwards. */ if (from_start) { optionbutton_set_state(0, idb->self_id, FindFromStart, 0); find_from_start_toggled(eventcode, event, idb, handle); /* Flag that From Start was switched off automatically */ fs_so = 1; /* Set 'Forwards' */ radiobutton_set_state(0, idb->self_id, FindForwards, 1); /* The above button may not exist, so we still need to */ /* turn off 'Backwards' explicitly. */ radiobutton_set_state(0, idb->self_id, FindBackwards, 0); } } } return 1; } /*************************************************/ /* find_cancel() */ /* */ /* Called when the EFindCancel event is */ /* generated, typically from the 'Cancel' button */ /* in the Find dialogue box. */ /* */ /* Parameters are as standard for a Toolbox */ /* event handler. */ /*************************************************/ static int find_cancel(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { find_close(); return 1; } /*************************************************/ /* find_string_has_changed() */ /* */ /* Called when a WritableField_ValueChanged */ /* event is raised from the Find dialogue box. */ /* Invalidates the record of last item found. */ /* */ /* Parameters are as standard for a Toolbox */ /* event handler. */ /*************************************************/ static int find_string_has_changed(int eventcode, ToolboxEvent * event, IdBlock * idb, void * handle) { last_t = NULL; last_o = 0; return 1; }