root/lib/widget/widget-common.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. widget_set_id
  2. widget_default_resize
  3. widget_do_focus
  4. widget_focus
  5. widget_reorder
  6. hotkey_cmp
  7. widget_default_mouse_callback
  8. widget_default_get_colors
  9. hotkey_new
  10. hotkey_free
  11. hotkey_width
  12. hotkey_equal
  13. hotkey_draw
  14. hotkey_get_text
  15. widget_init
  16. widget_destroy
  17. widget_default_callback
  18. widget_set_options
  19. widget_adjust_position
  20. widget_set_size
  21. widget_selectcolor
  22. widget_erase
  23. widget_is_active
  24. widget_draw
  25. widget_replace
  26. widget_select
  27. widget_set_bottom
  28. widget_overlapped
  29. widget_lookup_key
  30. widget_default_find
  31. widget_default_find_by_type
  32. widget_default_find_by_id
  33. widget_default_set_state
  34. mouse_get_local
  35. mouse_global_in_widget

   1 /*
   2    Widgets for the Midnight Commander
   3 
   4    Copyright (C) 1994-2020
   5    Free Software Foundation, Inc.
   6 
   7    Authors:
   8    Radek Doulik, 1994, 1995
   9    Miguel de Icaza, 1994, 1995
  10    Jakub Jelinek, 1995
  11    Andrej Borsenkow, 1996
  12    Norbert Warmuth, 1997
  13    Andrew Borodin <aborodin@vmail.ru>, 2009, 2010, 2011, 2012, 2013
  14 
  15    This file is part of the Midnight Commander.
  16 
  17    The Midnight Commander is free software: you can redistribute it
  18    and/or modify it under the terms of the GNU General Public License as
  19    published by the Free Software Foundation, either version 3 of the License,
  20    or (at your option) any later version.
  21 
  22    The Midnight Commander is distributed in the hope that it will be useful,
  23    but WITHOUT ANY WARRANTY; without even the implied warranty of
  24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25    GNU General Public License for more details.
  26 
  27    You should have received a copy of the GNU General Public License
  28    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  29  */
  30 
  31 /** \file widget-common.c
  32  *  \brief Source: shared stuff of widgets
  33  */
  34 
  35 #include <config.h>
  36 
  37 #include <stdlib.h>
  38 #include <string.h>
  39 
  40 #include "lib/global.h"
  41 
  42 #include "lib/tty/tty.h"
  43 #include "lib/tty/color.h"
  44 #include "lib/skin.h"
  45 #include "lib/strutil.h"
  46 #include "lib/widget.h"
  47 
  48 /*** global variables ****************************************************************************/
  49 
  50 /*** file scope macro definitions ****************************************************************/
  51 
  52 /*** file scope type declarations ****************************************************************/
  53 
  54 /*** file scope variables ************************************************************************/
  55 
  56 /* maximum value of used widget ID */
  57 static unsigned long widget_id = 0;
  58 
  59 /* --------------------------------------------------------------------------------------------- */
  60 /*** file scope functions ************************************************************************/
  61 /* --------------------------------------------------------------------------------------------- */
  62 
  63 /**
  64  * Calc widget ID,
  65  * Widget ID is uniq for each widget created during MC session (like PID in OS).
  66  *
  67  * @return widget ID.
  68  */
  69 static unsigned long
  70 widget_set_id (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
  71 {
  72     unsigned long id;
  73 
  74     id = widget_id++;
  75     /* TODO IF NEEDED: if id is already used, find next free id. */
  76 
  77     return id;
  78 }
  79 
  80 /* --------------------------------------------------------------------------------------------- */
  81 
  82 static cb_ret_t
  83 widget_default_resize (Widget * w, const WRect * r)
     /* [previous][next][first][last][top][bottom][index][help]  */
  84 {
  85     if (r == NULL)
  86         return MSG_NOT_HANDLED;
  87 
  88     w->y = r->y;
  89     w->x = r->x;
  90     w->lines = r->lines;
  91     w->cols = r->cols;
  92 
  93     return MSG_HANDLED;
  94 }
  95 
  96 /* --------------------------------------------------------------------------------------------- */
  97 
  98 static void
  99 widget_do_focus (Widget * w, gboolean enable)
     /* [previous][next][first][last][top][bottom][index][help]  */
 100 {
 101     if (w != NULL && widget_get_state (WIDGET (w->owner), WST_FOCUSED))
 102         widget_set_state (w, WST_FOCUSED, enable);
 103 }
 104 
 105 /* --------------------------------------------------------------------------------------------- */
 106 /**
 107  * Focus specified widget in it's owner.
 108  *
 109  * @param w widget to be focused.
 110  */
 111 
 112 static void
 113 widget_focus (Widget * w)
     /* [previous][next][first][last][top][bottom][index][help]  */
 114 {
 115     WGroup *g = w->owner;
 116 
 117     if (g == NULL)
 118         return;
 119 
 120     if (WIDGET (g->current->data) != w)
 121     {
 122         widget_do_focus (WIDGET (g->current->data), FALSE);
 123         /* Test if focus lost was allowed and focus has really been loose */
 124         if (g->current == NULL || !widget_get_state (WIDGET (g->current->data), WST_FOCUSED))
 125         {
 126             widget_do_focus (w, TRUE);
 127             g->current = widget_find (WIDGET (g), w);
 128         }
 129     }
 130     else if (!widget_get_state (w, WST_FOCUSED))
 131         widget_do_focus (w, TRUE);
 132 }
 133 
 134 /* --------------------------------------------------------------------------------------------- */
 135 
 136 /**
 137  * Put widget on top or bottom of Z-order.
 138  */
 139 static void
 140 widget_reorder (GList * l, gboolean set_top)
     /* [previous][next][first][last][top][bottom][index][help]  */
 141 {
 142     WGroup *g = WIDGET (l->data)->owner;
 143 
 144     g->widgets = g_list_remove_link (g->widgets, l);
 145     if (set_top)
 146         g->widgets = g_list_concat (g->widgets, l);
 147     else
 148         g->widgets = g_list_concat (l, g->widgets);
 149 }
 150 
 151 /* --------------------------------------------------------------------------------------------- */
 152 
 153 static gboolean
 154 hotkey_cmp (const char *s1, const char *s2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 155 {
 156     gboolean n1, n2;
 157 
 158     n1 = s1 != NULL;
 159     n2 = s2 != NULL;
 160 
 161     if (n1 != n2)
 162         return FALSE;
 163 
 164     if (n1 && n2 && strcmp (s1, s2) != 0)
 165         return FALSE;
 166 
 167     return TRUE;
 168 }
 169 
 170 /* --------------------------------------------------------------------------------------------- */
 171 
 172 static void
 173 widget_default_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event)
     /* [previous][next][first][last][top][bottom][index][help]  */
 174 {
 175     /* do nothing */
 176     (void) w;
 177     (void) msg;
 178     (void) event;
 179 }
 180 
 181 /* --------------------------------------------------------------------------------------------- */
 182 
 183 static const int *
 184 widget_default_get_colors (const Widget * w)
     /* [previous][next][first][last][top][bottom][index][help]  */
 185 {
 186     const Widget *owner = CONST_WIDGET (w->owner);
 187 
 188     return (owner == NULL ? NULL : widget_get_colors (owner));
 189 }
 190 
 191 /* --------------------------------------------------------------------------------------------- */
 192 /*** public functions ****************************************************************************/
 193 /* --------------------------------------------------------------------------------------------- */
 194 
 195 struct hotkey_t
 196 hotkey_new (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 197 {
 198     hotkey_t result;
 199     const char *cp, *p;
 200 
 201     if (text == NULL)
 202         text = "";
 203 
 204     /* search for '&', that is not on the of text */
 205     cp = strchr (text, '&');
 206     if (cp != NULL && cp[1] != '\0')
 207     {
 208         result.start = g_strndup (text, cp - text);
 209 
 210         /* skip '&' */
 211         cp++;
 212         p = str_cget_next_char (cp);
 213         result.hotkey = g_strndup (cp, p - cp);
 214 
 215         cp = p;
 216         result.end = g_strdup (cp);
 217     }
 218     else
 219     {
 220         result.start = g_strdup (text);
 221         result.hotkey = NULL;
 222         result.end = NULL;
 223     }
 224 
 225     return result;
 226 }
 227 
 228 /* --------------------------------------------------------------------------------------------- */
 229 
 230 void
 231 hotkey_free (const hotkey_t hotkey)
     /* [previous][next][first][last][top][bottom][index][help]  */
 232 {
 233     g_free (hotkey.start);
 234     g_free (hotkey.hotkey);
 235     g_free (hotkey.end);
 236 }
 237 
 238 /* --------------------------------------------------------------------------------------------- */
 239 
 240 int
 241 hotkey_width (const hotkey_t hotkey)
     /* [previous][next][first][last][top][bottom][index][help]  */
 242 {
 243     int result;
 244 
 245     result = str_term_width1 (hotkey.start);
 246     result += (hotkey.hotkey != NULL) ? str_term_width1 (hotkey.hotkey) : 0;
 247     result += (hotkey.end != NULL) ? str_term_width1 (hotkey.end) : 0;
 248     return result;
 249 }
 250 
 251 /* --------------------------------------------------------------------------------------------- */
 252 
 253 gboolean
 254 hotkey_equal (const hotkey_t hotkey1, const hotkey_t hotkey2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 255 {
 256     /* *INDENT-OFF* */
 257     return (strcmp (hotkey1.start, hotkey2.start) == 0) &&
 258            hotkey_cmp (hotkey1.hotkey, hotkey2.hotkey) &&
 259            hotkey_cmp (hotkey1.end, hotkey2.end);
 260     /* *INDENT-ON* */
 261 }
 262 
 263 /* --------------------------------------------------------------------------------------------- */
 264 
 265 void
 266 hotkey_draw (Widget * w, const hotkey_t hotkey, gboolean focused)
     /* [previous][next][first][last][top][bottom][index][help]  */
 267 {
 268     if (hotkey.start[0] != '\0')
 269     {
 270         widget_selectcolor (w, focused, FALSE);
 271         tty_print_string (hotkey.start);
 272     }
 273 
 274     if (hotkey.hotkey != NULL)
 275     {
 276         widget_selectcolor (w, focused, TRUE);
 277         tty_print_string (hotkey.hotkey);
 278     }
 279 
 280     if (hotkey.end != NULL)
 281     {
 282         widget_selectcolor (w, focused, FALSE);
 283         tty_print_string (hotkey.end);
 284     }
 285 }
 286 
 287 /* --------------------------------------------------------------------------------------------- */
 288 
 289 char *
 290 hotkey_get_text (const hotkey_t hotkey)
     /* [previous][next][first][last][top][bottom][index][help]  */
 291 {
 292     GString *text;
 293 
 294     text = g_string_new (hotkey.start);
 295 
 296     if (hotkey.hotkey != NULL)
 297     {
 298         g_string_append_c (text, '&');
 299         g_string_append (text, hotkey.hotkey);
 300     }
 301 
 302     if (hotkey.end != NULL)
 303         g_string_append (text, hotkey.end);
 304 
 305     return g_string_free (text, FALSE);
 306 }
 307 
 308 /* --------------------------------------------------------------------------------------------- */
 309 
 310 void
 311 widget_init (Widget * w, int y, int x, int lines, int cols,
     /* [previous][next][first][last][top][bottom][index][help]  */
 312              widget_cb_fn callback, widget_mouse_cb_fn mouse_callback)
 313 {
 314     w->id = widget_set_id ();
 315     w->x = x;
 316     w->y = y;
 317     w->cols = cols;
 318     w->lines = lines;
 319     w->pos_flags = WPOS_KEEP_DEFAULT;
 320     w->callback = callback;
 321 
 322     w->keymap = NULL;
 323     w->ext_keymap = NULL;
 324     w->ext_mode = FALSE;
 325 
 326     w->mouse_callback = mouse_callback != NULL ? mouse_callback : widget_default_mouse_callback;
 327     w->owner = NULL;
 328     w->mouse_handler = mouse_handle_event;
 329     w->mouse.forced_capture = FALSE;
 330     w->mouse.capture = FALSE;
 331     w->mouse.last_msg = MSG_MOUSE_NONE;
 332     w->mouse.last_buttons_down = 0;
 333 
 334     w->options = WOP_DEFAULT;
 335     w->state = WST_CONSTRUCT;
 336 
 337     w->find = widget_default_find;
 338     w->find_by_type = widget_default_find_by_type;
 339     w->find_by_id = widget_default_find_by_id;
 340 
 341     w->set_state = widget_default_set_state;
 342     w->get_colors = widget_default_get_colors;
 343 }
 344 
 345 /* --------------------------------------------------------------------------------------------- */
 346 
 347 void
 348 widget_destroy (Widget * w)
     /* [previous][next][first][last][top][bottom][index][help]  */
 349 {
 350     send_message (w, NULL, MSG_DESTROY, 0, NULL);
 351     g_free (w);
 352 }
 353 
 354 /* --------------------------------------------------------------------------------------------- */
 355 
 356 /* Default callback for widgets */
 357 cb_ret_t
 358 widget_default_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 359 {
 360     (void) sender;
 361     (void) parm;
 362 
 363     switch (msg)
 364     {
 365     case MSG_INIT:
 366     case MSG_FOCUS:
 367     case MSG_UNFOCUS:
 368     case MSG_ENABLE:
 369     case MSG_DISABLE:
 370     case MSG_DRAW:
 371     case MSG_DESTROY:
 372     case MSG_CURSOR:
 373     case MSG_IDLE:
 374         return MSG_HANDLED;
 375 
 376     case MSG_RESIZE:
 377         return widget_default_resize (w, CONST_RECT (data));
 378 
 379     default:
 380         return MSG_NOT_HANDLED;
 381     }
 382 }
 383 
 384 /* --------------------------------------------------------------------------------------------- */
 385 
 386 /**
 387  * Apply new options to widget.
 388  *
 389  * @param w       widget
 390  * @param options widget option flags to modify. Several flags per call can be modified.
 391  * @param enable  TRUE if specified options should be added, FALSE if options should be removed
 392  */
 393 void
 394 widget_set_options (Widget * w, widget_options_t options, gboolean enable)
     /* [previous][next][first][last][top][bottom][index][help]  */
 395 {
 396     if (enable)
 397         w->options |= options;
 398     else
 399         w->options &= ~options;
 400 }
 401 
 402 /* --------------------------------------------------------------------------------------------- */
 403 
 404 void
 405 widget_adjust_position (widget_pos_flags_t pos_flags, int *y, int *x, int *lines, int *cols)
     /* [previous][next][first][last][top][bottom][index][help]  */
 406 {
 407     if ((pos_flags & WPOS_FULLSCREEN) != 0)
 408     {
 409         *y = 0;
 410         *x = 0;
 411         *lines = LINES;
 412         *cols = COLS;
 413     }
 414     else
 415     {
 416         if ((pos_flags & WPOS_CENTER_HORZ) != 0)
 417             *x = (COLS - *cols) / 2;
 418 
 419         if ((pos_flags & WPOS_CENTER_VERT) != 0)
 420             *y = (LINES - *lines) / 2;
 421 
 422         if ((pos_flags & WPOS_TRYUP) != 0)
 423         {
 424             if (*y > 3)
 425                 *y -= 2;
 426             else if (*y == 3)
 427                 *y = 2;
 428         }
 429     }
 430 }
 431 
 432 /* --------------------------------------------------------------------------------------------- */
 433 /**
 434  * Change widget position and size.
 435  *
 436  * @param w widget
 437  * @param y y coordinate of top-left corner
 438  * @param x x coordinate of top-left corner
 439  * @param lines width
 440  * @param cols height
 441  */
 442 
 443 void
 444 widget_set_size (Widget * w, int y, int x, int lines, int cols)
     /* [previous][next][first][last][top][bottom][index][help]  */
 445 {
 446     WRect r = { y, x, lines, cols };
 447 
 448     send_message (w, NULL, MSG_RESIZE, 0, &r);
 449 
 450     if (w->owner != NULL && widget_get_state (WIDGET (w->owner), WST_ACTIVE))
 451         widget_draw (w);
 452 }
 453 
 454 /* --------------------------------------------------------------------------------------------- */
 455 
 456 void
 457 widget_selectcolor (Widget * w, gboolean focused, gboolean hotkey)
     /* [previous][next][first][last][top][bottom][index][help]  */
 458 {
 459     int color;
 460     const int *colors;
 461 
 462     colors = widget_get_colors (w);
 463 
 464     if (widget_get_state (w, WST_DISABLED))
 465         color = DISABLED_COLOR;
 466     else if (hotkey)
 467         color = colors[focused ? DLG_COLOR_HOT_FOCUS : DLG_COLOR_HOT_NORMAL];
 468     else
 469         color = colors[focused ? DLG_COLOR_FOCUS : DLG_COLOR_NORMAL];
 470 
 471     tty_setcolor (color);
 472 }
 473 
 474 /* --------------------------------------------------------------------------------------------- */
 475 
 476 void
 477 widget_erase (Widget * w)
     /* [previous][next][first][last][top][bottom][index][help]  */
 478 {
 479     if (w != NULL)
 480         tty_fill_region (w->y, w->x, w->lines, w->cols, ' ');
 481 }
 482 
 483 /* --------------------------------------------------------------------------------------------- */
 484 /**
 485   * Check whether widget is active or not.
 486   * Widget is active if it's current in the its owner and each owner in the chain is current too.
 487   *
 488   * @param w the widget
 489   *
 490   * @return TRUE if the widget is active, FALSE otherwise
 491   */
 492 
 493 gboolean
 494 widget_is_active (const void *w)
     /* [previous][next][first][last][top][bottom][index][help]  */
 495 {
 496     const WGroup *owner;
 497 
 498     /* Is group top? */
 499     if (w == top_dlg->data)
 500         return TRUE;
 501 
 502     owner = CONST_WIDGET (w)->owner;
 503 
 504     /* Is widget in any group? */
 505     if (owner == NULL)
 506         return FALSE;
 507 
 508     if (w != owner->current->data)
 509         return FALSE;
 510 
 511     return widget_is_active (owner);
 512 }
 513 
 514 /* --------------------------------------------------------------------------------------------- */
 515 
 516 cb_ret_t
 517 widget_draw (Widget * w)
     /* [previous][next][first][last][top][bottom][index][help]  */
 518 {
 519     cb_ret_t ret = MSG_NOT_HANDLED;
 520 
 521     if (w != NULL)
 522     {
 523         WGroup *g = w->owner;
 524 
 525         if (g != NULL && widget_get_state (WIDGET (g), WST_ACTIVE))
 526             ret = w->callback (w, NULL, MSG_DRAW, 0, NULL);
 527     }
 528 
 529     return ret;
 530 }
 531 
 532 /* --------------------------------------------------------------------------------------------- */
 533 /**
 534   * Replace widget in the dialog.
 535   *
 536   * @param old_w old widget that need to be replaced
 537   * @param new_w new widget that will replace @old_w
 538   */
 539 
 540 void
 541 widget_replace (Widget * old_w, Widget * new_w)
     /* [previous][next][first][last][top][bottom][index][help]  */
 542 {
 543     WGroup *g = old_w->owner;
 544     gboolean should_focus = FALSE;
 545     GList *holder;
 546 
 547     if (g->widgets == NULL)
 548         return;
 549 
 550     if (g->current == NULL)
 551         g->current = g->widgets;
 552 
 553     /* locate widget position in the list */
 554     if (old_w == g->current->data)
 555         holder = g->current;
 556     else
 557         holder = g_list_find (g->widgets, old_w);
 558 
 559     /* if old widget is focused, we should focus the new one... */
 560     if (widget_get_state (old_w, WST_FOCUSED))
 561         should_focus = TRUE;
 562     /* ...but if new widget isn't selectable, we cannot focus it */
 563     if (!widget_get_options (new_w, WOP_SELECTABLE))
 564         should_focus = FALSE;
 565 
 566     /* if new widget isn't selectable, select other widget before replace */
 567     if (!should_focus)
 568     {
 569         GList *l;
 570 
 571         for (l = group_get_widget_next_of (holder);
 572              !widget_get_options (WIDGET (l->data), WOP_SELECTABLE)
 573              && !widget_get_state (WIDGET (l->data), WST_DISABLED);
 574              l = group_get_widget_next_of (l))
 575             ;
 576 
 577         widget_select (WIDGET (l->data));
 578     }
 579 
 580     /* replace widget */
 581     new_w->owner = g;
 582     new_w->id = old_w->id;
 583     holder->data = new_w;
 584 
 585     send_message (old_w, NULL, MSG_DESTROY, 0, NULL);
 586     send_message (new_w, NULL, MSG_INIT, 0, NULL);
 587 
 588     if (should_focus)
 589         widget_select (new_w);
 590     else
 591         widget_draw (new_w);
 592 }
 593 
 594 /* --------------------------------------------------------------------------------------------- */
 595 /**
 596  * Select specified widget in it's owner.
 597  *
 598  * Note: this function (and widget_focus(), which it calls) is a no-op
 599  * if the widget is already selected.
 600  *
 601  * @param w widget to be selected
 602  */
 603 
 604 void
 605 widget_select (Widget * w)
     /* [previous][next][first][last][top][bottom][index][help]  */
 606 {
 607     WGroup *g;
 608 
 609     if (!widget_get_options (w, WOP_SELECTABLE))
 610         return;
 611 
 612     g = GROUP (w->owner);
 613     if (g != NULL)
 614     {
 615         if (widget_get_options (w, WOP_TOP_SELECT))
 616         {
 617             GList *l;
 618 
 619             l = widget_find (WIDGET (g), w);
 620             widget_reorder (l, TRUE);
 621         }
 622 
 623         widget_focus (w);
 624     }
 625 }
 626 
 627 /* --------------------------------------------------------------------------------------------- */
 628 /**
 629  * Set widget at bottom of widget list.
 630  */
 631 
 632 void
 633 widget_set_bottom (Widget * w)
     /* [previous][next][first][last][top][bottom][index][help]  */
 634 {
 635     widget_reorder (widget_find (WIDGET (w->owner), w), FALSE);
 636 }
 637 
 638 /* --------------------------------------------------------------------------------------------- */
 639 /**
 640   * Check whether two widgets are overlapped or not.
 641   * @param a 1st widget
 642   * @param b 2nd widget
 643   *
 644   * @return TRUE if widgets are overlapped, FALSE otherwise.
 645   */
 646 
 647 gboolean
 648 widget_overlapped (const Widget * a, const Widget * b)
     /* [previous][next][first][last][top][bottom][index][help]  */
 649 {
 650     return !((b->x >= a->x + a->cols)
 651              || (a->x >= b->x + b->cols) || (b->y >= a->y + a->lines) || (a->y >= b->y + b->lines));
 652 }
 653 
 654 /* --------------------------------------------------------------------------------------------- */
 655 /**
 656   * Look up key event of widget and translate it to command ID.
 657   * @param w   widget
 658   * @param key key event
 659   *
 660   * @return command ID binded with @key.
 661   */
 662 
 663 long
 664 widget_lookup_key (Widget * w, int key)
     /* [previous][next][first][last][top][bottom][index][help]  */
 665 {
 666     if (w->ext_mode)
 667     {
 668         w->ext_mode = FALSE;
 669         return keybind_lookup_keymap_command (w->ext_keymap, key);
 670     }
 671 
 672     return keybind_lookup_keymap_command (w->keymap, key);
 673 }
 674 
 675 /* --------------------------------------------------------------------------------------------- */
 676 /**
 677  * Default callback function to find widget.
 678  *
 679  * @param w widget
 680  * @param what widget to find
 681  *
 682  * @return holder of @what if widget is @what, NULL otherwise
 683  */
 684 
 685 GList *
 686 widget_default_find (const Widget * w, const Widget * what)
     /* [previous][next][first][last][top][bottom][index][help]  */
 687 {
 688     return (w != what
 689             || w->owner == NULL) ? NULL : g_list_find (CONST_GROUP (w->owner)->widgets, what);
 690 }
 691 
 692 /* --------------------------------------------------------------------------------------------- */
 693 
 694 /**
 695  * Default callback function to find widget by widget type using widget callback.
 696  *
 697  * @param w widget
 698  * @param cb widget callback
 699  *
 700  * @return @w if widget callback is @cb, NULL otherwise
 701  */
 702 
 703 Widget *
 704 widget_default_find_by_type (const Widget * w, widget_cb_fn cb)
     /* [previous][next][first][last][top][bottom][index][help]  */
 705 {
 706     return (w->callback == cb ? WIDGET (w) : NULL);
 707 }
 708 
 709 /* --------------------------------------------------------------------------------------------- */
 710 /**
 711  * Default callback function to find widget by widget ID.
 712  *
 713  * @param w widget
 714  * @param id widget ID
 715  *
 716  * @return @w if widget id is equal to @id, NULL otherwise
 717  */
 718 
 719 Widget *
 720 widget_default_find_by_id (const Widget * w, unsigned long id)
     /* [previous][next][first][last][top][bottom][index][help]  */
 721 {
 722     return (w->id == id ? WIDGET (w) : NULL);
 723 }
 724 
 725 /* --------------------------------------------------------------------------------------------- */
 726 
 727 /**
 728  * Default callback function to modify state of widget.
 729  *
 730  * @param w      widget
 731  * @param state  widget state flag to modify
 732  * @param enable specifies whether to turn the flag on (TRUE) or off (FALSE).
 733  *               Only one flag per call can be modified.
 734  * @return       MSG_HANDLED if set was handled successfully, MSG_NOT_HANDLED otherwise.
 735  */
 736 
 737 cb_ret_t
 738 widget_default_set_state (Widget * w, widget_state_t state, gboolean enable)
     /* [previous][next][first][last][top][bottom][index][help]  */
 739 {
 740     gboolean ret = MSG_HANDLED;
 741 
 742     if (enable)
 743         w->state |= state;
 744     else
 745         w->state &= ~state;
 746 
 747     if (enable)
 748     {
 749         /* exclusive bits */
 750         if ((state & WST_CONSTRUCT) != 0)
 751             w->state &= ~(WST_ACTIVE | WST_SUSPENDED | WST_CLOSED);
 752         else if ((state & WST_ACTIVE) != 0)
 753             w->state &= ~(WST_CONSTRUCT | WST_SUSPENDED | WST_CLOSED);
 754         else if ((state & WST_SUSPENDED) != 0)
 755             w->state &= ~(WST_CONSTRUCT | WST_ACTIVE | WST_CLOSED);
 756         else if ((state & WST_CLOSED) != 0)
 757             w->state &= ~(WST_CONSTRUCT | WST_ACTIVE | WST_SUSPENDED);
 758     }
 759 
 760     if (w->owner == NULL)
 761         return MSG_NOT_HANDLED;
 762 
 763     switch (state)
 764     {
 765     case WST_DISABLED:
 766         ret = send_message (w, NULL, enable ? MSG_DISABLE : MSG_ENABLE, 0, NULL);
 767         if (ret == MSG_HANDLED && widget_get_state (WIDGET (w->owner), WST_ACTIVE))
 768             ret = widget_draw (w);
 769         break;
 770 
 771     case WST_FOCUSED:
 772         {
 773             widget_msg_t msg;
 774 
 775             msg = enable ? MSG_FOCUS : MSG_UNFOCUS;
 776             ret = send_message (w, NULL, msg, 0, NULL);
 777             if (ret == MSG_HANDLED && widget_get_state (WIDGET (w->owner), WST_ACTIVE))
 778             {
 779                 widget_draw (w);
 780                 /* Notify owner that focus was moved from one widget to another */
 781                 send_message (w->owner, w, MSG_CHANGED_FOCUS, 0, NULL);
 782             }
 783         }
 784         break;
 785 
 786     default:
 787         break;
 788     }
 789 
 790     return ret;
 791 }
 792 
 793 /* --------------------------------------------------------------------------------------------- */
 794 /* get mouse pointer location within widget */
 795 
 796 Gpm_Event
 797 mouse_get_local (const Gpm_Event * global, const Widget * w)
     /* [previous][next][first][last][top][bottom][index][help]  */
 798 {
 799     Gpm_Event local;
 800 
 801     local.buttons = global->buttons;
 802 #ifdef HAVE_LIBGPM
 803     local.clicks = 0;
 804     local.margin = 0;
 805     local.modifiers = 0;
 806     local.vc = 0;
 807 #endif
 808     local.x = global->x - w->x;
 809     local.y = global->y - w->y;
 810     local.type = global->type;
 811 
 812     return local;
 813 }
 814 
 815 /* --------------------------------------------------------------------------------------------- */
 816 
 817 gboolean
 818 mouse_global_in_widget (const Gpm_Event * event, const Widget * w)
     /* [previous][next][first][last][top][bottom][index][help]  */
 819 {
 820     return (event->x > w->x) && (event->y > w->y) && (event->x <= w->x + w->cols)
 821         && (event->y <= w->y + w->lines);
 822 }
 823 
 824 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */