From 251763331de26a4356a6bfeb46b36f67c2070468 Mon Sep 17 00:00:00 2001 From: Richard Wilson Date: Sat, 31 Dec 2005 04:06:40 +0000 Subject: [project @ 2005-12-31 04:06:40 by rjw] Automated WIMP event handling functions. svn path=/import/netsurf/; revision=1904 --- riscos/wimp_event.c | 976 ++++++++++++++++++++++++++++++++++++++++++++++++++++ riscos/wimp_event.h | 68 ++++ 2 files changed, 1044 insertions(+) create mode 100644 riscos/wimp_event.c create mode 100644 riscos/wimp_event.h diff --git a/riscos/wimp_event.c b/riscos/wimp_event.c new file mode 100644 index 000000000..33f933602 --- /dev/null +++ b/riscos/wimp_event.c @@ -0,0 +1,976 @@ +/* + * This file is part of NetSurf, http://netsurf.sourceforge.net/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2005 Richard Wilson + */ + +/** \file + * Automated RISC OS WIMP event handling (implementation). + */ + +#include +#include +#include +#include +#include +#include "oslib/os.h" +#include "oslib/wimp.h" +#include "netsurf/riscos/dialog.h" +#include "netsurf/riscos/menus.h" +#include "netsurf/riscos/wimp.h" +#include "netsurf/riscos/wimp_event.h" +#include "netsurf/utils/log.h" +#include "netsurf/utils/utils.h" + +typedef enum { + EVENT_NUMERIC_FIELD, + EVENT_TEXT_FIELD, + EVENT_UP_ARROW, + EVENT_DOWN_ARROW, + EVENT_MENU_GRIGHT, + EVENT_CHECKBOX, + EVENT_RADIO, + EVENT_BUTTON, + EVENT_CANCEL, + EVENT_OK +} event_type; + +struct event_data_numeric_field { + int stepping; + int min; + int max; + int decimal_places; +}; + +struct event_data_menu_gright { + wimp_i field; + wimp_menu *menu; +}; + +struct icon_event { + event_type type; + wimp_i i; + union { + struct event_data_numeric_field numeric_field; + struct event_data_menu_gright menu_gright; + wimp_i linked_icon; + int radio_group; + void (*callback)(wimp_pointer *pointer); + } data; + union { + char *textual; + bool boolean; + } previous_value; + bool previous_shaded; + struct icon_event *next; +}; + +struct event_window { + wimp_w w; + bool (*ok_click)(wimp_w w); + bool (*mouse_click)(wimp_pointer *pointer); + bool (*keypress)(wimp_key *key); + void (*open_window)(wimp_open *open); + void (*close_window)(wimp_w w); + void (*redraw_window)(wimp_draw *redraw); + const char *help_prefix; + void *user_data; + struct icon_event *first; + struct event_window *next; + int max_radio_group; +}; + +static void ro_gui_wimp_event_ok_click(struct event_window *window, + wimp_mouse_state state); +static struct event_window *ro_gui_wimp_event_get_window(wimp_w w); +static struct event_window *ro_gui_wimp_event_find_window(wimp_w w); +static struct icon_event *ro_gui_wimp_event_get_event(wimp_w w, wimp_i i, + event_type type); + +static struct event_window *ro_gui_wimp_event_windows; + + +/** + * Memorises the current state of any registered components in a window. + * + * \param w the window to memorise + * \return true on success, false on memory exhaustion or for an unknown window + */ +bool ro_gui_wimp_event_memorise(wimp_w w) { + struct event_window *window; + struct icon_event *event; + bool error = false; + + window = ro_gui_wimp_event_find_window(w); + if (!window) + return false; + + for (event = window->first; event; event = event->next) { + switch (event->type) { + case EVENT_NUMERIC_FIELD: + case EVENT_TEXT_FIELD: + if (event->previous_value.textual) + free(event->previous_value.textual); + event->previous_value.textual = strdup( + ro_gui_get_icon_string(window->w, event->i)); + if (!event->previous_value.textual) { + error = true; + LOG(("Unable to store state for icon %i", event->i)); + } + break; + case EVENT_CHECKBOX: + case EVENT_RADIO: + event->previous_value.boolean = + ro_gui_get_icon_selected_state(window->w, event->i); + break; + default: + break; + } + if (event->type != EVENT_MENU_GRIGHT) + event->previous_shaded = ro_gui_get_icon_shaded_state(window->w, + event->i); + } + return !error; +} + + +/** + * Restore the state of any registered components in a window to their memorised state. + * + * \param w the window to restore + * \return true on success, false for an unknown window + */ +bool ro_gui_wimp_event_restore(wimp_w w) { + struct event_window *window; + struct icon_event *event; + + window = ro_gui_wimp_event_find_window(w); + if (!window) + return false; + + for (event = window->first; event; event = event->next) { + switch (event->type) { + case EVENT_NUMERIC_FIELD: + case EVENT_TEXT_FIELD: + if (event->previous_value.textual) + ro_gui_set_icon_string(window->w, event->i, + event->previous_value.textual); + break; + case EVENT_CHECKBOX: + case EVENT_RADIO: + ro_gui_set_icon_selected_state(window->w, event->i, + event->previous_value.boolean); + break; + default: + break; + } + if (event->type != EVENT_MENU_GRIGHT) + ro_gui_set_icon_shaded_state(window->w, event->i, + event->previous_shaded); + } + return true; +} + + +/** + * Ensures all values are within pre-determined boundaries. + * + * \param w the window to memorise + * \return true on success, false for an unknown window + */ +bool ro_gui_wimp_event_validate(wimp_w w) { + struct event_window *window; + struct icon_event *event; + int value; + + window = ro_gui_wimp_event_find_window(w); + if (!window) + return false; + + for (event = window->first; event; event = event->next) { + switch (event->type) { + case EVENT_NUMERIC_FIELD: + value = ro_gui_get_icon_decimal(window->w, event->i, + event->data.numeric_field.decimal_places); + if (value < event->data.numeric_field.min) + value = event->data.numeric_field.min; + else if (value > event->data.numeric_field.max) + value = event->data.numeric_field.max; + ro_gui_set_icon_decimal(window->w, event->i, value, + event->data.numeric_field.decimal_places); + break; + default: + break; + } + } + return true; +} + + +/** + * Free any resources associated with a window. + * + * \param w the window to free resources for + */ +void ro_gui_wimp_event_finalise(wimp_w w) { + struct event_window *window; + struct event_window *link; + struct icon_event *event; + + window = ro_gui_wimp_event_find_window(w); + if (!window) + return; + + if (window == ro_gui_wimp_event_windows) { + ro_gui_wimp_event_windows = window->next; + } else { + for (link = ro_gui_wimp_event_windows; link; link = link->next) { + if (link->next == window) { + link->next = window->next; + break; + } + } + } + + while (window->first) { + event = window->first; + window->first = event->next; + switch (event->type) { + case EVENT_NUMERIC_FIELD: + case EVENT_TEXT_FIELD: + if (event->previous_value.textual) + free(event->previous_value.textual); + event->previous_value.textual = NULL; + break; + default: + break; + } + free(event); + } + free(window); + return; +} + + +/** + * Set the associated help prefix for a given window. + * + * \param w the window to get the prefix for + * \param help_prefix the prefix to associate with the window (used directly) + * \return true on success, or NULL for memory exhaustion + */ +bool ro_gui_wimp_event_set_help_prefix(wimp_w w, const char *help_prefix) { + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->help_prefix = help_prefix; + return true; +} + + +/** + * Get the associated help prefix. + * + * \param w the window to get the prefix for + * \return the associated prefix, or NULL + */ +const char *ro_gui_wimp_event_get_help_prefix(wimp_w w) { + struct event_window *window; + + window = ro_gui_wimp_event_find_window(w); + if (window) + return window->help_prefix; + return NULL; +} + + +/** + * Sets the user data associated with a window. + * + * \param w the window to associate the data with + * \param user the data to associate + */ +bool ro_gui_wimp_event_set_user_data(wimp_w w, void *user) { + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->user_data = user; + return true; + +} + + +/** + * Gets the user data associated with a window. + * + * \param w the window to retrieve the data for + * \return the associated data, or NULL + */ +void *ro_gui_wimp_event_get_user_data(wimp_w w) { + struct event_window *window; + + window = ro_gui_wimp_event_find_window(w); + if (window) + return window->user_data; + return NULL; +} + + +/** + * Handles a menu selection event. + * + * \param w the window to owning the menu + * \param i the icon owning the menu + * \param menu the menu that has been selected + * \param selection the selection information + * \return true if the event was handled, false otherwise + */ +bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection) { + struct event_window *window; + struct icon_event *event; + struct icon_event *search; + wimp_menu_entry *menu_entry; + wimp_key key; + os_error *error; + wimp_caret caret; + wimp_icon_state ic; + unsigned int button_type; + + window = ro_gui_wimp_event_find_window(w); + if (!window) + return false; + + for (event = window->first; event; event = event->next) + if (event->i == i) + break; + if (!event) + return false; + + if (event->type != EVENT_MENU_GRIGHT) { + LOG(("Incorrect or missing menu reference.")); + return false; + } + + for (search = window->first; search; search = search->next) + if (search->i == event->data.menu_gright.field) + break; + if (!search) + return false; + + if (search->type != EVENT_TEXT_FIELD) { + LOG(("Incorrect or missing field reference.")); + return false; + } + + menu_entry = &menu->entries[selection->items[0]]; + for (i = 1; selection->items[i] != -1; i++) + menu_entry = &menu_entry->sub_menu-> + entries[selection->items[i]]; + + ro_gui_set_icon_string(window->w, search->i, + menu_entry->data.indirected_text.text); + + /* set the caret for writable icons and send a CTRL+U keypress to + * stimulate activity if needed */ + ic.w = window->w; + ic.i = search->i; + error = xwimp_get_icon_state(&ic); + if (error) { + LOG(("xwimp_get_icon_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + button_type = (ic.icon.flags & wimp_ICON_BUTTON_TYPE) >> wimp_ICON_BUTTON_TYPE_SHIFT; + if ((button_type != wimp_BUTTON_WRITABLE) && + (button_type != wimp_BUTTON_WRITE_CLICK_DRAG)) + return true; + error = xwimp_get_caret_position(&caret); + if (error) { + LOG(("xwimp_get_caret_position: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + if ((caret.w != window->w) || (caret.i != search->i)) { + error = xwimp_set_caret_position(window->w, search->i, -1, -1, + -1, strlen(menu_entry->data.indirected_text.text)); + if (error) { + LOG(("xwimp_set_caret_position: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + } + if (window->keypress) { + key.w = window->w; + key.c = 21; // ctrl+u + window->keypress(&key); + } + return true; +} + + +/** + * Handles a mouse click event in a registered window. + * + * The order of execution is: + * + * 1. Any registered mouse_click routine (see ro_gui_wimp_register_mouse_click()) + * 2. If the current icon is not registered with a type then it is assumed that no + * action is necessary, and the click is deemed to have been handled. + * 3. If the registered mouse_click routine returned false, or there was no registered + * routine then the automated action for the registered icon type is performed + * + * \param pointer the current pointer state + * \return true if the event was handled, false otherwise + */ +bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) { + struct event_window *window; + struct icon_event *event; + wimp_w w; + struct icon_event *search; + int current, step, stepping, min, max, decimal_places; + wimp_window_state open; + wimp_caret caret; + os_error *error; + + w = pointer->w; + window = ro_gui_wimp_event_find_window(w); + if (!window) + return false; + + /* registered routines take priority */ + if ((window->mouse_click) && (window->mouse_click(pointer))) + return true; + + for (event = window->first; event; event = event->next) + if (event->i == pointer->i) + break; + if (!event) + return true; + + switch (event->type) { + case EVENT_NUMERIC_FIELD: + case EVENT_TEXT_FIELD: + break; + case EVENT_UP_ARROW: + case EVENT_DOWN_ARROW: + for (search = window->first; search; search = search->next) + if (search->i == event->data.linked_icon) break; + if (!search) { + LOG(("Incorrect reference.")); + return false; + } + stepping = search->data.numeric_field.stepping; + min = search->data.numeric_field.min; + max = search->data.numeric_field.max; + decimal_places = search->data.numeric_field.decimal_places; + + if (pointer->buttons & wimp_CLICK_ADJUST) + step = -stepping; + else if (pointer->buttons & wimp_CLICK_SELECT) + step = stepping; + else + return true; + if (event->type == EVENT_DOWN_ARROW) + step = -step; + + current = ro_gui_get_icon_decimal(pointer->w, event->data.linked_icon, + decimal_places); + current += step; + if (current < min) + current = min; + if (current > max) + current = max; + ro_gui_set_icon_decimal(pointer->w, event->data.linked_icon, current, + decimal_places); + break; + case EVENT_MENU_GRIGHT: + /* if there's already a menu open then we assume that we are part of it. + * to follow the standard RISC OS behaviour we add a 'send to the back' + * button, then close the menu (which closes us) and then finally + * re-open ourselves. ugh! */ + if (current_menu != NULL) { + open.w = pointer->w; + error = xwimp_get_window_state(&open); + if (error) { + LOG(("xwimp_get_window_state: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + error = xwimp_get_caret_position(&caret); + if (error) { + LOG(("xwimp_get_caret_position: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + ro_gui_dialog_add_persistent(current_menu_window, + pointer->w); + ro_gui_menu_closed(false); + gui_poll(true); + error = xwimp_open_window((wimp_open *) &open); + if (error) { + LOG(("xwimp_open_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return false; + } + if (caret.w == pointer->w) { + error = xwimp_set_caret_position(caret.w, + caret.i, + caret.pos.x, caret.pos.y, + -1, caret.index); + if (error) { + LOG(("xwimp_set_caret_position: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + } + } + ro_gui_popup_menu(event->data.menu_gright.menu, pointer->w, pointer->i); + break; + case EVENT_CHECKBOX: + break; + case EVENT_RADIO: + for (search = window->first; search; search = search->next) + if ((search->type == EVENT_RADIO) && + (search->data.radio_group == + event->data.radio_group)) + ro_gui_set_icon_selected_state(pointer->w, + search->i, (search == event)); + /* TODO: Enforce radio behaviour */ + break; + case EVENT_BUTTON: + if (event->data.callback) + event->data.callback(pointer); + break; + case EVENT_CANCEL: + if (pointer->buttons & wimp_CLICK_SELECT) { + ro_gui_dialog_close(pointer->w); + ro_gui_menu_closed(true); + } else { + ro_gui_wimp_event_restore(pointer->w); + } + break; + case EVENT_OK: + ro_gui_wimp_event_ok_click(window, pointer->buttons); + break; + } + return true; +} + + +/** + * Perform the necessary actions following a click on the OK button. + * + * /param window the window to perform the action on + * /param state the mouse button state + */ +void ro_gui_wimp_event_ok_click(struct event_window *window, wimp_mouse_state state) { + struct icon_event *search; + + for (search = window->first; search; search = search->next) + if (search->type == EVENT_OK) { + if (ro_gui_get_icon_shaded_state(window->w, search->i)) + return; + break; + } + ro_gui_wimp_event_validate(window->w); + + if (window->ok_click) + if (!window->ok_click(window->w)) + return; + + if (state & wimp_CLICK_SELECT) { + ro_gui_dialog_close(window->w); + ro_gui_menu_closed(true); + } else { + ro_gui_wimp_event_memorise(window->w); + } +} + + +/** + * Handle any registered keypresses, and the standard RISC OS ones + * + * \param key the key state + */ +bool ro_gui_wimp_event_keypress(wimp_key *key) { + struct event_window *window; + + window = ro_gui_wimp_event_find_window(key->w); + if (!window) + return false; + + /* registered routines take priority */ + if (window->keypress) + if (window->keypress(key)) + return true; + + switch (key->c) { + /* Escape closes a dialog with a registered OK button */ + case wimp_KEY_ESCAPE: + if (!window->ok_click) + return false; + ro_gui_dialog_close(key->w); + ro_gui_menu_closed(true); + return true; + /* CTRL+F2 closes a window with a close icon */ + case wimp_KEY_CONTROL + wimp_KEY_F2: + if (!ro_gui_wimp_check_window_furniture(key->w, + wimp_WINDOW_CLOSE_ICON)) + return false; + ro_gui_dialog_close(key->w); + ro_gui_menu_closed(true); + return true; + /* Return performs the OK action */ + case wimp_KEY_RETURN: + if (!window->ok_click) + return false; + /* todo: check we aren't greyed out */ + ro_gui_wimp_event_ok_click(window, wimp_CLICK_SELECT); + return true; + } + return false; +} + + +/** + * Handle any open window requests + * + * \param open the window open request + */ +bool ro_gui_wimp_event_open_window(wimp_open *open) { + struct event_window *window; + + window = ro_gui_wimp_event_find_window(open->w); + if ((window) && (window->open_window)) { + window->open_window(open); + return true; + } + return false; +} + + +/** + * Service any close window handlers + * + * \param w the window being closed + */ +bool ro_gui_wimp_event_close_window(wimp_w w) { + struct event_window *window; + + window = ro_gui_wimp_event_find_window(w); + if ((window) && (window->close_window)) { + window->close_window(w); + return true; + } + return false; +} + + +/** + * Handle any redraw window requests + * + * \param redraw the window redraw request + */ +bool ro_gui_wimp_event_redraw_window(wimp_draw *redraw) { + struct event_window *window; + + window = ro_gui_wimp_event_find_window(redraw->w); + if ((window) && (window->redraw_window)) { + window->redraw_window(redraw); + return true; + } + return false; +} + + +/** + * Register a numeric field to be automatically handled + */ +bool ro_gui_wimp_event_register_numeric_field(wimp_w w, wimp_i i, wimp_i up, wimp_i down, + int min, int max, int stepping, int decimal_places) { + struct icon_event *event; + + event = ro_gui_wimp_event_get_event(w, i, EVENT_NUMERIC_FIELD); + if (!event) + return false; + event->data.numeric_field.min = min; + event->data.numeric_field.max = max; + event->data.numeric_field.stepping = stepping; + event->data.numeric_field.decimal_places = decimal_places; + + event = ro_gui_wimp_event_get_event(w, up, EVENT_UP_ARROW); + if (!event) + return false; + event->data.linked_icon = i; + + event = ro_gui_wimp_event_get_event(w, down, EVENT_DOWN_ARROW); + if (!event) + return false; + event->data.linked_icon = i; + + return true; +} + + +/** + * Register a text field to be automatically handled + */ +bool ro_gui_wimp_event_register_text_field(wimp_w w, wimp_i i) { + struct icon_event *event; + + event = ro_gui_wimp_event_get_event(w, i, EVENT_TEXT_FIELD); + if (!event) + return false; + return true; +} + + +/** + * Register an icon menu to be automatically handled + */ +bool ro_gui_wimp_event_register_menu_gright(wimp_w w, wimp_i i, wimp_i gright, wimp_menu *menu) { + struct icon_event *event; + + event = ro_gui_wimp_event_get_event(w, gright, EVENT_MENU_GRIGHT); + if (!event) + return false; + event->data.menu_gright.field = i; + event->data.menu_gright.menu = menu; + + return ro_gui_wimp_event_register_text_field(w, i); +} + + +/** + * Register a checkbox to be automatically handled + */ +bool ro_gui_wimp_event_register_checkbox(wimp_w w, wimp_i i) { + struct icon_event *event; + + event = ro_gui_wimp_event_get_event(w, i, EVENT_CHECKBOX); + if (!event) + return false; + return true; +} + + +/** + * Register a group of radio icons to be automatically handled + */ +bool ro_gui_wimp_event_register_radio(wimp_w w, wimp_i *i) { + struct event_window *window; + struct icon_event *event; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->max_radio_group++; + + while (*i != -1) { + event = ro_gui_wimp_event_get_event(w, *i, EVENT_RADIO); + if (!event) + return false; + event->data.radio_group = window->max_radio_group; + *i++; + } + return true; +} + + +/** + * Register a function to be called when a particular button is pressed. + */ +bool ro_gui_wimp_event_register_button(wimp_w w, wimp_i i, + void (*callback)(wimp_pointer *pointer)) { + struct icon_event *event; + + event = ro_gui_wimp_event_get_event(w, i, EVENT_BUTTON); + if (!event) + return false; + event->data.callback = callback; + return true; +} + + +/** + * Register a function to be called for the Cancel action on a window. + */ +bool ro_gui_wimp_event_register_cancel(wimp_w w, wimp_i i) { + struct icon_event *event; + + event = ro_gui_wimp_event_get_event(w, i, EVENT_CANCEL); + if (!event) + return false; + return true; +} + + +/** + * Register a function to be called for the OK action on a window. + */ +bool ro_gui_wimp_event_register_ok(wimp_w w, wimp_i i, + bool (*callback)(wimp_w w)) { + struct event_window *window; + struct icon_event *event; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->ok_click = callback; + + event = ro_gui_wimp_event_get_event(w, i, EVENT_OK); + if (!event) + return false; + return true; +} + + +/** + * Register a function to be called for all mouse-clicks to icons + * in a window that don't have registered actions. + */ +bool ro_gui_wimp_event_register_mouse_click(wimp_w w, + bool (*callback)(wimp_pointer *pointer)) { + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->mouse_click = callback; + return true; +} + + +/** + * Register a function to be called for all keypresses within a + * particular window. + */ +bool ro_gui_wimp_event_register_keypress(wimp_w w, + bool (*callback)(wimp_key *key)) { + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->keypress = callback; + return true; +} + + +/** + * Register a function to be called for all window opening requests. + */ +bool ro_gui_wimp_event_register_open_window(wimp_w w, + void (*callback)(wimp_open *open)) { + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->open_window = callback; + return true; +} + +/** + * Register a function to be called after the window has been closed. + */ +bool ro_gui_wimp_event_register_close_window(wimp_w w, + void (*callback)(wimp_w w)) { + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->close_window = callback; + return true; +} + +/** + * Register a function to be called for all window redraw operations. + */ +bool ro_gui_wimp_event_register_redraw_window(wimp_w w, + void (*callback)(wimp_draw *redraw)) { + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->redraw_window = callback; + return true; +} + + + +/** + * Finds the event data associated with a given window handle, or creates a new one. + * + * \param w the window to find data for + */ +struct event_window *ro_gui_wimp_event_get_window(wimp_w w) { + struct event_window *window; + + window = ro_gui_wimp_event_find_window(w); + if (window) + return window; + + window = calloc(1, sizeof(struct event_window)); + if (!window) + return NULL; + window->w = w; + window->next = ro_gui_wimp_event_windows; + ro_gui_wimp_event_windows = window; + return window; +} + + +/** + * Find the event data associated with a given window handle + * + * \param w the window to find data for + */ +struct event_window *ro_gui_wimp_event_find_window(wimp_w w) { + struct event_window *window; + + for (window = ro_gui_wimp_event_windows; window; window = window->next) { + if (window->w == w) + return window; + } + return NULL; +} + +struct icon_event *ro_gui_wimp_event_get_event(wimp_w w, wimp_i i, event_type type) { + struct event_window *window; + struct icon_event *event; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return NULL; + + for (event = window->first; event; event = event->next) { + if (event->i == i) { + event->type = type; + return event; + } + } + + event = calloc(1, sizeof(struct icon_event)); + if (!event) + return NULL; + event->i = i; + event->type = type; + event->next = window->first; + window->first = event; + + return event; +} diff --git a/riscos/wimp_event.h b/riscos/wimp_event.h new file mode 100644 index 000000000..58f4b4223 --- /dev/null +++ b/riscos/wimp_event.h @@ -0,0 +1,68 @@ +/* + * This file is part of NetSurf, http://netsurf.sourceforge.net/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2005 Richard Wilson + */ + +/** \file + * Automated RISC OS WIMP event handling (interface). + */ + + +#ifndef _NETSURF_RISCOS_WIMP_EVENT_H_ +#define _NETSURF_RISCOS_WIMP_EVENT_H_ + +#include +#include +#include +#include +#include +#include "oslib/os.h" +#include "oslib/wimp.h" + +bool ro_gui_wimp_event_memorise(wimp_w w); +bool ro_gui_wimp_event_restore(wimp_w w); +bool ro_gui_wimp_event_validate(wimp_w w); +void ro_gui_wimp_event_finalise(wimp_w w); + +bool ro_gui_wimp_event_set_help_prefix(wimp_w w, const char *help_prefix); +const char *ro_gui_wimp_event_get_help_prefix(wimp_w w); +bool ro_gui_wimp_event_set_user_data(wimp_w w, void *user); +void *ro_gui_wimp_event_get_user_data(wimp_w w); + +bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, + wimp_selection *selection); +bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer); +bool ro_gui_wimp_event_keypress(wimp_key *key); +bool ro_gui_wimp_event_open_window(wimp_open *open); +bool ro_gui_wimp_event_close_window(wimp_w w); +bool ro_gui_wimp_event_redraw_window(wimp_draw *redraw); + +bool ro_gui_wimp_event_register_numeric_field(wimp_w w, wimp_i i, wimp_i up, + wimp_i down, int min, int max, int stepping, + int decimal_places); +bool ro_gui_wimp_event_register_text_field(wimp_w w, wimp_i i); +bool ro_gui_wimp_event_register_menu_gright(wimp_w w, wimp_i i, + wimp_i gright, wimp_menu *menu); +bool ro_gui_wimp_event_register_checkbox(wimp_w w, wimp_i i); +bool ro_gui_wimp_event_register_radio(wimp_w w, wimp_i *i); +bool ro_gui_wimp_event_register_button(wimp_w w, wimp_i i, + void (*callback)(wimp_pointer *pointer)); +bool ro_gui_wimp_event_register_cancel(wimp_w w, wimp_i i); +bool ro_gui_wimp_event_register_ok(wimp_w w, wimp_i i, + bool (*callback)(wimp_w w)); + +bool ro_gui_wimp_event_register_mouse_click(wimp_w w, + bool (*callback)(wimp_pointer *pointer)); +bool ro_gui_wimp_event_register_keypress(wimp_w w, + bool (*callback)(wimp_key *key)); +bool ro_gui_wimp_event_register_open_window(wimp_w w, + void (*callback)(wimp_open *open)); +bool ro_gui_wimp_event_register_close_window(wimp_w w, + void (*callback)(wimp_w w)); +bool ro_gui_wimp_event_register_redraw_window(wimp_w w, + void (*callback)(wimp_draw *redraw)); + + +#endif -- cgit v1.2.3