123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905 |
- /*
- Widgets for the Midnight Commander
- Copyright (C) 1994-2024
- Free Software Foundation, Inc.
- Authors:
- Radek Doulik, 1994, 1995
- Miguel de Icaza, 1994, 1995
- Jakub Jelinek, 1995
- Andrej Borsenkow, 1996
- Norbert Warmuth, 1997
- Andrew Borodin <aborodin@vmail.ru>, 2009-2022
- This file is part of the Midnight Commander.
- The Midnight Commander is free software: you can redistribute it
- and/or modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
- The Midnight Commander is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /** \file widget-common.c
- * \brief Source: shared stuff of widgets
- */
- #include <config.h>
- #include <stdlib.h>
- #include <string.h>
- #include "lib/global.h"
- #include "lib/tty/tty.h"
- #include "lib/tty/color.h"
- #include "lib/skin.h"
- #include "lib/strutil.h"
- #include "lib/widget.h"
- /*** global variables ****************************************************************************/
- /*** file scope macro definitions ****************************************************************/
- /*** file scope type declarations ****************************************************************/
- /*** forward declarations (file scope functions) *************************************************/
- /*** file scope variables ************************************************************************/
- /* maximum value of used widget ID */
- static unsigned long widget_id = 0;
- /* --------------------------------------------------------------------------------------------- */
- /*** file scope functions ************************************************************************/
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Calc widget ID,
- * Widget ID is uniq for each widget created during MC session (like PID in OS).
- *
- * @return widget ID.
- */
- static unsigned long
- widget_set_id (void)
- {
- unsigned long id;
- id = widget_id++;
- /* TODO IF NEEDED: if id is already used, find next free id. */
- return id;
- }
- /* --------------------------------------------------------------------------------------------- */
- static cb_ret_t
- widget_default_resize (Widget *w, const WRect *r)
- {
- if (r == NULL)
- return MSG_NOT_HANDLED;
- w->rect = *r;
- return MSG_HANDLED;
- }
- /* --------------------------------------------------------------------------------------------- */
- static void
- widget_do_focus (Widget *w, gboolean enable)
- {
- if (w != NULL && widget_get_state (WIDGET (w->owner), WST_VISIBLE | WST_FOCUSED))
- widget_set_state (w, WST_FOCUSED, enable);
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Focus specified widget in it's owner.
- *
- * @param w widget to be focused.
- */
- static void
- widget_focus (Widget *w)
- {
- WGroup *g = w->owner;
- if (g == NULL || g->current == NULL)
- return;
- if (WIDGET (g->current->data) != w)
- {
- widget_do_focus (WIDGET (g->current->data), FALSE);
- /* Test if focus lost was allowed and focus has really been loose */
- if (g->current == NULL || !widget_get_state (WIDGET (g->current->data), WST_FOCUSED))
- {
- widget_do_focus (w, TRUE);
- g->current = widget_find (WIDGET (g), w);
- }
- }
- else if (!widget_get_state (w, WST_FOCUSED))
- widget_do_focus (w, TRUE);
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Put widget on top or bottom of Z-order.
- */
- static void
- widget_reorder (GList *l, gboolean set_top)
- {
- WGroup *g = WIDGET (l->data)->owner;
- g->widgets = g_list_remove_link (g->widgets, l);
- if (set_top)
- g->widgets = g_list_concat (g->widgets, l);
- else
- g->widgets = g_list_concat (l, g->widgets);
- }
- /* --------------------------------------------------------------------------------------------- */
- static gboolean
- hotkey_cmp (const char *s1, const char *s2)
- {
- gboolean n1, n2;
- n1 = s1 != NULL;
- n2 = s2 != NULL;
- if (n1 != n2)
- return FALSE;
- if (n1 && n2 && strcmp (s1, s2) != 0)
- return FALSE;
- return TRUE;
- }
- /* --------------------------------------------------------------------------------------------- */
- static void
- widget_default_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
- {
- /* do nothing */
- (void) w;
- (void) msg;
- (void) event;
- }
- /* --------------------------------------------------------------------------------------------- */
- static const int *
- widget_default_get_colors (const Widget *w)
- {
- const Widget *owner = CONST_WIDGET (w->owner);
- return (owner == NULL ? NULL : widget_get_colors (owner));
- }
- /* --------------------------------------------------------------------------------------------- */
- /*** public functions ****************************************************************************/
- /* --------------------------------------------------------------------------------------------- */
- struct hotkey_t
- hotkey_new (const char *text)
- {
- hotkey_t result;
- const char *cp, *p;
- if (text == NULL)
- text = "";
- /* search for '&', that is not on the of text */
- cp = strchr (text, '&');
- if (cp != NULL && cp[1] != '\0')
- {
- result.start = g_strndup (text, cp - text);
- /* skip '&' */
- cp++;
- p = str_cget_next_char (cp);
- result.hotkey = g_strndup (cp, p - cp);
- cp = p;
- result.end = g_strdup (cp);
- }
- else
- {
- result.start = g_strdup (text);
- result.hotkey = NULL;
- result.end = NULL;
- }
- return result;
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- hotkey_free (const hotkey_t hotkey)
- {
- g_free (hotkey.start);
- g_free (hotkey.hotkey);
- g_free (hotkey.end);
- }
- /* --------------------------------------------------------------------------------------------- */
- int
- hotkey_width (const hotkey_t hotkey)
- {
- int result;
- result = str_term_width1 (hotkey.start);
- result += (hotkey.hotkey != NULL) ? str_term_width1 (hotkey.hotkey) : 0;
- result += (hotkey.end != NULL) ? str_term_width1 (hotkey.end) : 0;
- return result;
- }
- /* --------------------------------------------------------------------------------------------- */
- gboolean
- hotkey_equal (const hotkey_t hotkey1, const hotkey_t hotkey2)
- {
- /* *INDENT-OFF* */
- return (strcmp (hotkey1.start, hotkey2.start) == 0) &&
- hotkey_cmp (hotkey1.hotkey, hotkey2.hotkey) &&
- hotkey_cmp (hotkey1.end, hotkey2.end);
- /* *INDENT-ON* */
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- hotkey_draw (const Widget *w, const hotkey_t hotkey, gboolean focused)
- {
- if (hotkey.start[0] != '\0')
- {
- widget_selectcolor (w, focused, FALSE);
- tty_print_string (hotkey.start);
- }
- if (hotkey.hotkey != NULL)
- {
- widget_selectcolor (w, focused, TRUE);
- tty_print_string (hotkey.hotkey);
- }
- if (hotkey.end != NULL)
- {
- widget_selectcolor (w, focused, FALSE);
- tty_print_string (hotkey.end);
- }
- }
- /* --------------------------------------------------------------------------------------------- */
- char *
- hotkey_get_text (const hotkey_t hotkey)
- {
- GString *text;
- text = g_string_new (hotkey.start);
- if (hotkey.hotkey != NULL)
- {
- g_string_append_c (text, '&');
- g_string_append (text, hotkey.hotkey);
- }
- if (hotkey.end != NULL)
- g_string_append (text, hotkey.end);
- return g_string_free (text, FALSE);
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- widget_init (Widget *w, const WRect *r, widget_cb_fn callback, widget_mouse_cb_fn mouse_callback)
- {
- w->id = widget_set_id ();
- w->rect = *r;
- w->pos_flags = WPOS_KEEP_DEFAULT;
- w->callback = callback;
- w->keymap = NULL;
- w->ext_keymap = NULL;
- w->ext_mode = FALSE;
- w->mouse_callback = mouse_callback != NULL ? mouse_callback : widget_default_mouse_callback;
- w->owner = NULL;
- w->mouse_handler = mouse_handle_event;
- w->mouse.forced_capture = FALSE;
- w->mouse.capture = FALSE;
- w->mouse.last_msg = MSG_MOUSE_NONE;
- w->mouse.last_buttons_down = 0;
- w->options = WOP_DEFAULT;
- w->state = WST_CONSTRUCT | WST_VISIBLE;
- w->make_global = widget_default_make_global;
- w->make_local = widget_default_make_local;
- w->find = widget_default_find;
- w->find_by_type = widget_default_find_by_type;
- w->find_by_id = widget_default_find_by_id;
- w->set_state = widget_default_set_state;
- w->destroy = widget_default_destroy;
- w->get_colors = widget_default_get_colors;
- }
- /* --------------------------------------------------------------------------------------------- */
- /* Default callback for widgets */
- cb_ret_t
- widget_default_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
- {
- (void) sender;
- (void) parm;
- switch (msg)
- {
- case MSG_INIT:
- case MSG_FOCUS:
- case MSG_UNFOCUS:
- case MSG_ENABLE:
- case MSG_DISABLE:
- case MSG_DRAW:
- case MSG_DESTROY:
- case MSG_CURSOR:
- case MSG_IDLE:
- return MSG_HANDLED;
- case MSG_RESIZE:
- return widget_default_resize (w, CONST_RECT (data));
- default:
- return MSG_NOT_HANDLED;
- }
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Apply new options to widget.
- *
- * @param w widget
- * @param options widget option flags to modify. Several flags per call can be modified.
- * @param enable TRUE if specified options should be added, FALSE if options should be removed
- */
- void
- widget_set_options (Widget *w, widget_options_t options, gboolean enable)
- {
- if (enable)
- w->options |= options;
- else
- w->options &= ~options;
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- widget_adjust_position (widget_pos_flags_t pos_flags, WRect *r)
- {
- if ((pos_flags & WPOS_FULLSCREEN) != 0)
- {
- r->y = 0;
- r->x = 0;
- r->lines = LINES;
- r->cols = COLS;
- }
- else
- {
- if ((pos_flags & WPOS_CENTER_HORZ) != 0)
- r->x = (COLS - r->cols) / 2;
- if ((pos_flags & WPOS_CENTER_VERT) != 0)
- r->y = (LINES - r->lines) / 2;
- if ((pos_flags & WPOS_TRYUP) != 0)
- {
- if (r->y > 3)
- r->y -= 2;
- else if (r->y == 3)
- r->y = 2;
- }
- }
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Change widget position and size.
- *
- * @param w widget
- * @param y y coordinate of top-left corner
- * @param x x coordinate of top-left corner
- * @param lines width
- * @param cols height
- */
- void
- widget_set_size (Widget *w, int y, int x, int lines, int cols)
- {
- WRect r = { y, x, lines, cols };
- send_message (w, NULL, MSG_RESIZE, 0, &r);
- widget_draw (w);
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Change widget position and size.
- *
- * @param w widget
- * @param r WRect object that holds position and size
- */
- void
- widget_set_size_rect (Widget *w, WRect *r)
- {
- send_message (w, NULL, MSG_RESIZE, 0, r);
- widget_draw (w);
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- widget_selectcolor (const Widget *w, gboolean focused, gboolean hotkey)
- {
- int color;
- const int *colors;
- colors = widget_get_colors (w);
- if (widget_get_state (w, WST_DISABLED))
- color = DISABLED_COLOR;
- else if (hotkey)
- color = colors[focused ? DLG_COLOR_HOT_FOCUS : DLG_COLOR_HOT_NORMAL];
- else
- color = colors[focused ? DLG_COLOR_FOCUS : DLG_COLOR_NORMAL];
- tty_setcolor (color);
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- widget_erase (Widget *w)
- {
- if (w != NULL)
- tty_fill_region (w->rect.y, w->rect.x, w->rect.lines, w->rect.cols, ' ');
- }
- /* --------------------------------------------------------------------------------------------- */
- void
- widget_set_visibility (Widget *w, gboolean make_visible)
- {
- if (widget_get_state (w, WST_VISIBLE) != make_visible)
- widget_set_state (w, WST_VISIBLE, make_visible);
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Check whether widget is active or not.
- * Widget is active if it's current in the its owner and each owner in the chain is current too.
- *
- * @param w the widget
- *
- * @return TRUE if the widget is active, FALSE otherwise
- */
- gboolean
- widget_is_active (const void *w)
- {
- const WGroup *owner;
- /* Is group top? */
- if (w == top_dlg->data)
- return TRUE;
- owner = CONST_WIDGET (w)->owner;
- /* Is widget in any group? */
- if (owner == NULL)
- return FALSE;
- if (w != owner->current->data)
- return FALSE;
- return widget_is_active (owner);
- }
- /* --------------------------------------------------------------------------------------------- */
- cb_ret_t
- widget_draw (Widget *w)
- {
- cb_ret_t ret = MSG_NOT_HANDLED;
- if (w != NULL && widget_get_state (w, WST_VISIBLE))
- {
- WGroup *g = w->owner;
- if (g != NULL && widget_get_state (WIDGET (g), WST_ACTIVE))
- ret = w->callback (w, NULL, MSG_DRAW, 0, NULL);
- }
- return ret;
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Replace widget in the dialog.
- *
- * @param old_w old widget that need to be replaced
- * @param new_w new widget that will replace @old_w
- */
- void
- widget_replace (Widget *old_w, Widget *new_w)
- {
- WGroup *g = old_w->owner;
- gboolean should_focus = FALSE;
- GList *holder;
- if (g->widgets == NULL)
- return;
- if (g->current == NULL)
- g->current = g->widgets;
- /* locate widget position in the list */
- if (old_w == g->current->data)
- holder = g->current;
- else
- holder = g_list_find (g->widgets, old_w);
- /* if old widget is focused, we should focus the new one... */
- if (widget_get_state (old_w, WST_FOCUSED))
- should_focus = TRUE;
- /* ...but if new widget isn't selectable, we cannot focus it */
- if (!widget_get_options (new_w, WOP_SELECTABLE))
- should_focus = FALSE;
- /* if new widget isn't selectable, select other widget before replace */
- if (!should_focus)
- {
- GList *l;
- for (l = group_get_widget_next_of (holder);
- !widget_is_focusable (WIDGET (l->data)) && l != holder;
- l = group_get_widget_next_of (l))
- ;
- widget_select (WIDGET (l->data));
- }
- /* replace widget */
- new_w->owner = g;
- new_w->id = old_w->id;
- holder->data = new_w;
- send_message (old_w, NULL, MSG_DESTROY, 0, NULL);
- send_message (new_w, NULL, MSG_INIT, 0, NULL);
- if (should_focus)
- widget_select (new_w);
- else
- widget_draw (new_w);
- }
- /* --------------------------------------------------------------------------------------------- */
- gboolean
- widget_is_focusable (const Widget *w)
- {
- return (widget_get_options (w, WOP_SELECTABLE) && widget_get_state (w, WST_VISIBLE) &&
- !widget_get_state (w, WST_DISABLED));
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Select specified widget in it's owner.
- *
- * Note: this function (and widget_focus(), which it calls) is a no-op
- * if the widget is already selected.
- *
- * @param w widget to be selected
- */
- void
- widget_select (Widget *w)
- {
- WGroup *g;
- if (!widget_get_options (w, WOP_SELECTABLE))
- return;
- g = GROUP (w->owner);
- if (g != NULL)
- {
- if (widget_get_options (w, WOP_TOP_SELECT))
- {
- GList *l;
- l = widget_find (WIDGET (g), w);
- widget_reorder (l, TRUE);
- }
- widget_focus (w);
- }
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Set widget at bottom of widget list.
- */
- void
- widget_set_bottom (Widget *w)
- {
- widget_reorder (widget_find (WIDGET (w->owner), w), FALSE);
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Look up key event of widget and translate it to command ID.
- * @param w widget
- * @param key key event
- *
- * @return command ID binded with @key.
- */
- long
- widget_lookup_key (Widget *w, int key)
- {
- if (w->ext_mode)
- {
- w->ext_mode = FALSE;
- return keybind_lookup_keymap_command (w->ext_keymap, key);
- }
- return keybind_lookup_keymap_command (w->keymap, key);
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Default widget callback to convert widget coordinates from local (relative to owner) to global
- * (relative to screen).
- *
- * @param w widget
- * @delta offset for top-left corner coordinates. Used for child widgets of WGroup
- */
- void
- widget_default_make_global (Widget *w, const WRect *delta)
- {
- if (delta != NULL)
- rect_move (&w->rect, delta->y, delta->x);
- else if (w->owner != NULL)
- rect_move (&w->rect, WIDGET (w->owner)->rect.y, WIDGET (w->owner)->rect.x);
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Default widget callback to convert widget coordinates from global (relative to screen) to local
- * (relative to owner).
- *
- * @param w widget
- * @delta offset for top-left corner coordinates. Used for child widgets of WGroup
- */
- void
- widget_default_make_local (Widget *w, const WRect *delta)
- {
- if (delta != NULL)
- rect_move (&w->rect, -delta->y, -delta->x);
- else if (w->owner != NULL)
- rect_move (&w->rect, -WIDGET (w->owner)->rect.y, -WIDGET (w->owner)->rect.x);
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Default callback function to find widget.
- *
- * @param w widget
- * @param what widget to find
- *
- * @return holder of @what if widget is @what, NULL otherwise
- */
- GList *
- widget_default_find (const Widget *w, const Widget *what)
- {
- return (w != what
- || w->owner == NULL) ? NULL : g_list_find (CONST_GROUP (w->owner)->widgets, what);
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Default callback function to find widget by widget type using widget callback.
- *
- * @param w widget
- * @param cb widget callback
- *
- * @return @w if widget callback is @cb, NULL otherwise
- */
- Widget *
- widget_default_find_by_type (const Widget *w, widget_cb_fn cb)
- {
- return (w->callback == cb ? WIDGET (w) : NULL);
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Default callback function to find widget by widget ID.
- *
- * @param w widget
- * @param id widget ID
- *
- * @return @w if widget id is equal to @id, NULL otherwise
- */
- Widget *
- widget_default_find_by_id (const Widget *w, unsigned long id)
- {
- return (w->id == id ? WIDGET (w) : NULL);
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Default callback function to modify state of widget.
- *
- * @param w widget
- * @param state widget state flag to modify
- * @param enable specifies whether to turn the flag on (TRUE) or off (FALSE).
- * Only one flag per call can be modified.
- * @return MSG_HANDLED if set was handled successfully, MSG_NOT_HANDLED otherwise.
- */
- cb_ret_t
- widget_default_set_state (Widget *w, widget_state_t state, gboolean enable)
- {
- gboolean ret = MSG_HANDLED;
- Widget *owner = WIDGET (GROUP (w->owner));
- if (enable)
- w->state |= state;
- else
- w->state &= ~state;
- if (enable)
- {
- /* exclusive bits */
- switch (state)
- {
- case WST_CONSTRUCT:
- w->state &= ~(WST_ACTIVE | WST_SUSPENDED | WST_CLOSED);
- break;
- case WST_ACTIVE:
- w->state &= ~(WST_CONSTRUCT | WST_SUSPENDED | WST_CLOSED);
- break;
- case WST_SUSPENDED:
- w->state &= ~(WST_CONSTRUCT | WST_ACTIVE | WST_CLOSED);
- break;
- case WST_CLOSED:
- w->state &= ~(WST_CONSTRUCT | WST_ACTIVE | WST_SUSPENDED);
- break;
- default:
- break;
- }
- }
- if (owner == NULL)
- return MSG_NOT_HANDLED;
- switch (state)
- {
- case WST_VISIBLE:
- if (widget_get_state (owner, WST_ACTIVE))
- {
- /* redraw owner to show/hide widget */
- widget_draw (owner);
- if (!enable)
- {
- /* try select another widget if current one got hidden */
- if (w == GROUP (owner)->current->data)
- group_select_next_widget (GROUP (owner));
- widget_update_cursor (owner); /* FIXME: unneeded? */
- }
- }
- break;
- case WST_DISABLED:
- ret = send_message (w, NULL, enable ? MSG_DISABLE : MSG_ENABLE, 0, NULL);
- if (ret == MSG_HANDLED && widget_get_state (owner, WST_ACTIVE))
- ret = widget_draw (w);
- break;
- case WST_FOCUSED:
- {
- widget_msg_t msg;
- msg = enable ? MSG_FOCUS : MSG_UNFOCUS;
- ret = send_message (w, NULL, msg, 0, NULL);
- if (ret == MSG_HANDLED && widget_get_state (owner, WST_ACTIVE))
- {
- widget_draw (w);
- /* Notify owner that focus was moved from one widget to another */
- send_message (owner, w, MSG_CHANGED_FOCUS, 0, NULL);
- }
- }
- break;
- default:
- break;
- }
- return ret;
- }
- /* --------------------------------------------------------------------------------------------- */
- /**
- * Default callback function to destroy widget.
- *
- * @param w widget
- */
- void
- widget_default_destroy (Widget *w)
- {
- send_message (w, NULL, MSG_DESTROY, 0, NULL);
- g_free (w);
- }
- /* --------------------------------------------------------------------------------------------- */
- /* get mouse pointer location within widget */
- Gpm_Event
- mouse_get_local (const Gpm_Event *global, const Widget *w)
- {
- Gpm_Event local;
- memset (&local, 0, sizeof (local));
- local.buttons = global->buttons;
- local.x = global->x - w->rect.x;
- local.y = global->y - w->rect.y;
- local.type = global->type;
- return local;
- }
- /* --------------------------------------------------------------------------------------------- */
- gboolean
- mouse_global_in_widget (const Gpm_Event *event, const Widget *w)
- {
- const WRect *r = &w->rect;
- return (event->x > r->x) && (event->y > r->y) && (event->x <= r->x + r->cols)
- && (event->y <= r->y + r->lines);
- }
- /* --------------------------------------------------------------------------------------------- */
|