root/lwlib/lwlib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. free_widget_value_tree
  2. copy_widget_value_tree
  3. allocate_widget_info
  4. free_widget_info
  5. mark_widget_destroyed
  6. allocate_widget_instance
  7. free_widget_instance
  8. get_widget_info
  9. lw_get_widget_info
  10. get_widget_instance
  11. lw_get_widget_instance
  12. find_instance
  13. safe_strcmp
  14. merge_widget_value
  15. name_to_widget
  16. set_one_value
  17. update_one_widget_instance
  18. update_all_widget_values
  19. lw_modify_all_widgets
  20. initialize_widget_instance
  21. find_in_table
  22. dialog_spec_p
  23. instantiate_widget_instance
  24. lw_register_widget
  25. lw_get_widget
  26. lw_make_widget
  27. lw_create_widget
  28. destroy_one_instance
  29. lw_destroy_widget
  30. lw_destroy_all_widgets
  31. lw_destroy_everything
  32. lw_destroy_all_pop_ups
  33. lw_raise_all_pop_up_widgets
  34. lw_pop_all_widgets
  35. lw_pop_up_all_widgets
  36. lw_pop_down_all_widgets
  37. lw_popup_menu
  38. get_one_value
  39. lw_get_some_values
  40. lw_get_all_values
  41. lw_get_widget_value_for_widget
  42. lw_internal_update_other_instances
  43. lw_get_widget_id
  44. lw_set_keyboard_focus
  45. show_one_widget_busy
  46. lw_show_busy
  47. lw_refigure_widget
  48. lw_window_is_in_menubar
  49. lw_set_main_areas
  50. lw_allow_resizing
  51. lw_separator_p

     1 /* A general interface to the widgets of different toolkits.
     2 
     3 Copyright (C) 1992, 1993 Lucid, Inc.
     4 Copyright (C) 1994-1996, 1999-2023 Free Software Foundation, Inc.
     5 
     6 This file is part of the Lucid Widget Library.
     7 
     8 The Lucid Widget Library is free software; you can redistribute it and/or
     9 modify it under the terms of the GNU General Public License as published by
    10 the Free Software Foundation; either version 2, or (at your option)
    11 any later version.
    12 
    13 The Lucid Widget Library is distributed in the hope that it will be useful,
    14 but WITHOUT ANY WARRANTY; without even the implied warranty of
    15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16 GNU General Public License for more details.
    17 
    18 You should have received a copy of the GNU General Public License
    19 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    20 
    21 #include <config.h>
    22 
    23 #include <setjmp.h>
    24 #include <lisp.h>
    25 #include <c-strcase.h>
    26 
    27 #include <sys/types.h>
    28 #include <stdio.h>
    29 #include "lwlib-int.h"
    30 #include "lwlib-utils.h"
    31 #include <X11/StringDefs.h>
    32 
    33 #if defined (USE_LUCID)
    34 #include "lwlib-Xlw.h"
    35 #endif
    36 #if defined (USE_MOTIF)
    37 #include "lwlib-Xm.h"
    38 #else /* not USE_MOTIF */
    39 #if defined (USE_LUCID)
    40 #define USE_XAW
    41 #endif /* not USE_MOTIF && USE_LUCID */
    42 #endif
    43 #if defined (USE_XAW)
    44 #ifdef HAVE_XAW3D
    45 #include <X11/Xaw3d/Paned.h>
    46 #else /* !HAVE_XAW3D */
    47 #include <X11/Xaw/Paned.h>
    48 #endif /* HAVE_XAW3D */
    49 #include "lwlib-Xaw.h"
    50 #endif
    51 
    52 #if !defined (USE_LUCID) && !defined (USE_MOTIF)
    53  #error  At least one of USE_LUCID or USE_MOTIF must be defined.
    54 #endif
    55 
    56 #ifndef max
    57 #define max(x, y) ((x) > (y) ? (x) : (y))
    58 #endif
    59 
    60 /* List of all widgets managed by the library. */
    61 static widget_info*
    62 all_widget_info = NULL;
    63 
    64 #ifdef USE_MOTIF
    65 const char *lwlib_toolkit_type = "motif";
    66 #else
    67 const char *lwlib_toolkit_type = "lucid";
    68 #endif
    69 
    70 static widget_value *merge_widget_value (widget_value *,
    71                                          widget_value *,
    72                                          int, int *);
    73 static void instantiate_widget_instance (widget_instance *);
    74 static void free_widget_value_tree (widget_value *);
    75 static widget_value *copy_widget_value_tree (widget_value *,
    76                                              change_type);
    77 static widget_info *allocate_widget_info (const char *, const char *, LWLIB_ID,
    78                                           widget_value *,
    79                                           lw_callback, lw_callback,
    80                                           lw_callback, lw_callback);
    81 static void free_widget_info (widget_info *);
    82 static void mark_widget_destroyed (Widget, XtPointer, XtPointer);
    83 static widget_instance *allocate_widget_instance (widget_info *,
    84                                                   Widget, Boolean);
    85 static void free_widget_instance (widget_instance *);
    86 static widget_info *get_widget_info (LWLIB_ID, Boolean);
    87 static widget_instance *get_widget_instance (Widget, Boolean);
    88 static widget_instance *find_instance (LWLIB_ID, Widget, Boolean);
    89 static Boolean safe_strcmp (const char *, const char *);
    90 static Widget name_to_widget (widget_instance *, const char *);
    91 static void set_one_value (widget_instance *, widget_value *, Boolean);
    92 static void update_one_widget_instance (widget_instance *, Boolean);
    93 static void update_all_widget_values (widget_info *, Boolean);
    94 static void initialize_widget_instance (widget_instance *);
    95 static widget_creation_function find_in_table (const char *, const widget_creation_entry *);
    96 static Boolean dialog_spec_p (const char *);
    97 static void destroy_one_instance (widget_instance *);
    98 static void lw_pop_all_widgets (LWLIB_ID, Boolean);
    99 static Boolean get_one_value (widget_instance *, widget_value *);
   100 static void show_one_widget_busy (Widget, Boolean);
   101 
   102 static void
   103 free_widget_value_tree (widget_value *wv)
   104 {
   105   if (!wv)
   106     return;
   107 
   108   xfree (wv->name);
   109   xfree (wv->value);
   110   xfree (wv->key);
   111 
   112   wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
   113 
   114   if (wv->toolkit_data && wv->free_toolkit_data)
   115     {
   116       XtFree (wv->toolkit_data);
   117       wv->toolkit_data = (void *) 0xDEADBEEF;
   118     }
   119 
   120   if (wv->contents && (wv->contents != (widget_value*)1))
   121     {
   122       free_widget_value_tree (wv->contents);
   123       wv->contents = (widget_value *) 0xDEADBEEF;
   124     }
   125   if (wv->next)
   126     {
   127       free_widget_value_tree (wv->next);
   128       wv->next = (widget_value *) 0xDEADBEEF;
   129     }
   130   xfree (wv);
   131 }
   132 
   133 static widget_value *
   134 copy_widget_value_tree (widget_value *val, change_type change)
   135 {
   136   widget_value* copy;
   137 
   138   if (!val)
   139     return NULL;
   140   if (val == (widget_value *) 1)
   141     return val;
   142 
   143   copy = xmalloc (sizeof (widget_value));
   144   copy->lname = copy->lkey = Qnil;
   145   copy->name = xstrdup (val->name);
   146   copy->value = val->value ? xstrdup (val->value) : NULL;
   147   copy->key = val->key ? xstrdup (val->key) : NULL;
   148   copy->help = val->help;
   149   copy->enabled = val->enabled;
   150   copy->button_type = val->button_type;
   151   copy->selected = val->selected;
   152   copy->edited = False;
   153   copy->change = change;
   154   copy->this_one_change = change;
   155   copy->contents = copy_widget_value_tree (val->contents, change);
   156   copy->call_data = val->call_data;
   157   copy->next = copy_widget_value_tree (val->next, change);
   158   copy->toolkit_data = NULL;
   159   copy->free_toolkit_data = False;
   160   return copy;
   161 }
   162 
   163 static widget_info *
   164 allocate_widget_info (const char* type,
   165                       const char* name,
   166                       LWLIB_ID id,
   167                       widget_value* val,
   168                       lw_callback pre_activate_cb,
   169                       lw_callback selection_cb,
   170                       lw_callback post_activate_cb,
   171                       lw_callback highlight_cb)
   172 {
   173   widget_info* info = (widget_info*) xmalloc (sizeof (widget_info));
   174   info->type = xstrdup (type);
   175   info->name = xstrdup (name);
   176   info->id = id;
   177   info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
   178   info->busy = False;
   179   info->pre_activate_cb = pre_activate_cb;
   180   info->selection_cb = selection_cb;
   181   info->post_activate_cb = post_activate_cb;
   182   info->highlight_cb = highlight_cb;
   183   info->instances = NULL;
   184 
   185   info->next = all_widget_info;
   186   all_widget_info = info;
   187 
   188   return info;
   189 }
   190 
   191 static void
   192 free_widget_info (widget_info *info)
   193 {
   194   xfree (info->type);
   195   xfree (info->name);
   196   free_widget_value_tree (info->val);
   197   memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
   198   xfree (info);
   199 }
   200 
   201 static void
   202 mark_widget_destroyed (Widget widget, XtPointer closure, XtPointer call_data)
   203 {
   204   widget_instance* instance = (widget_instance*)closure;
   205 
   206   /* be very conservative */
   207   if (instance->widget == widget)
   208     instance->widget = NULL;
   209 }
   210 
   211 static widget_instance *
   212 allocate_widget_instance (widget_info* info, Widget parent, Boolean pop_up_p)
   213 {
   214   widget_instance* instance =
   215     (widget_instance*) xmalloc (sizeof (widget_instance));
   216   memset (instance, 0, sizeof *instance);
   217   instance->parent = parent;
   218   instance->pop_up_p = pop_up_p;
   219   instance->info = info;
   220   instance->next = info->instances;
   221   info->instances = instance;
   222 
   223   instantiate_widget_instance (instance);
   224 
   225   XtAddCallback (instance->widget, XtNdestroyCallback,
   226                  mark_widget_destroyed, (XtPointer)instance);
   227   return instance;
   228 }
   229 
   230 static void
   231 free_widget_instance (widget_instance *instance)
   232 {
   233   memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
   234   xfree (instance);
   235 }
   236 
   237 static widget_info *
   238 get_widget_info (LWLIB_ID id, Boolean remove_p)
   239 {
   240   widget_info* info;
   241   widget_info* prev;
   242   for (prev = NULL, info = all_widget_info;
   243        info;
   244        prev = info, info = info->next)
   245     if (info->id == id)
   246      {
   247        if (remove_p)
   248          {
   249            if (prev)
   250              prev->next = info->next;
   251            else
   252              all_widget_info = info->next;
   253          }
   254       return info;
   255      }
   256   return NULL;
   257 }
   258 
   259 /* Internal function used by the library dependent implementation to get the
   260    widget_value for a given widget in an instance */
   261 widget_info *
   262 lw_get_widget_info (LWLIB_ID id)
   263 {
   264   return get_widget_info (id, 0);
   265 }
   266 
   267 static widget_instance *
   268 get_widget_instance (Widget widget, Boolean remove_p)
   269 {
   270   widget_info* info;
   271   widget_instance* instance;
   272   widget_instance* prev;
   273   for (info = all_widget_info; info; info = info->next)
   274     for (prev = NULL, instance = info->instances;
   275          instance;
   276          prev = instance, instance = instance->next)
   277       if (instance->widget == widget)
   278         {
   279           if (remove_p)
   280             {
   281               if (prev)
   282                 prev->next = instance->next;
   283               else
   284                 info->instances = instance->next;
   285             }
   286           return instance;
   287         }
   288   return (widget_instance *) 0;
   289 }
   290 
   291 /* Value is a pointer to the widget_instance corresponding to
   292    WIDGET, or null if WIDGET is not a lwlib widget.  */
   293 
   294 widget_instance *
   295 lw_get_widget_instance (Widget widget)
   296 {
   297   return get_widget_instance (widget, False);
   298 }
   299 
   300 static widget_instance*
   301 find_instance (LWLIB_ID id, Widget parent, Boolean pop_up_p)
   302 {
   303   widget_info* info = get_widget_info (id, False);
   304   widget_instance* instance;
   305 
   306   if (info)
   307     for (instance = info->instances; instance; instance = instance->next)
   308       if (instance->parent == parent && instance->pop_up_p == pop_up_p)
   309         return instance;
   310 
   311   return NULL;
   312 }
   313 
   314 
   315 /* utility function for widget_value */
   316 static Boolean
   317 safe_strcmp (const char *s1, const char *s2)
   318 {
   319   if (!!s1 ^ !!s2) return True;
   320   return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
   321 }
   322 
   323 
   324 #if 0
   325 # define EXPLAIN(name, oc, nc, desc, a1, a2)                            \
   326    printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n",              \
   327            name,                                                        \
   328            (oc == NO_CHANGE ? "none" :                                  \
   329             (oc == INVISIBLE_CHANGE ? "invisible" :                     \
   330              (oc == VISIBLE_CHANGE ? "visible" :                        \
   331               (oc == STRUCTURAL_CHANGE ? "structural" : "???")))),      \
   332            oc,                                                          \
   333            (nc == NO_CHANGE ? "none" :                                  \
   334             (nc == INVISIBLE_CHANGE ? "invisible" :                     \
   335              (nc == VISIBLE_CHANGE ? "visible" :                        \
   336               (nc == STRUCTURAL_CHANGE ? "structural" : "???")))),      \
   337            nc, desc, a1, a2)
   338 #else
   339 # define EXPLAIN(name, oc, nc, desc, a1, a2) ((void) 0)
   340 #endif
   341 
   342 
   343 static widget_value *
   344 merge_widget_value (widget_value *val1,
   345                     widget_value *val2,
   346                     int level,
   347                     int *change_p)
   348 {
   349   change_type change, this_one_change;
   350   widget_value* merged_next;
   351   widget_value* merged_contents;
   352 
   353   if (!val1)
   354     {
   355       if (val2)
   356         {
   357           *change_p = 1;
   358           return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
   359         }
   360       else
   361         return NULL;
   362     }
   363   if (!val2)
   364     {
   365       *change_p = 1;
   366       free_widget_value_tree (val1);
   367       return NULL;
   368     }
   369 
   370   change = NO_CHANGE;
   371 
   372   if (safe_strcmp (val1->name, val2->name))
   373     {
   374       EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
   375                val1->name, val2->name);
   376       change = max (change, STRUCTURAL_CHANGE);
   377       dupstring (&val1->name, val2->name);
   378     }
   379   if (safe_strcmp (val1->value, val2->value))
   380     {
   381       EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
   382                val1->value, val2->value);
   383       change = max (change, VISIBLE_CHANGE);
   384       dupstring (&val1->value, val2->value);
   385     }
   386   if (safe_strcmp (val1->key, val2->key))
   387     {
   388       EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
   389                val1->key, val2->key);
   390       change = max (change, VISIBLE_CHANGE);
   391       dupstring (&val1->key, val2->key);
   392     }
   393   if (! EQ (val1->help, val2->help))
   394     {
   395       EXPLAIN (val1->name, change, VISIBLE_CHANGE, "help change",
   396                val1->help, val2->help);
   397       change = max (change, VISIBLE_CHANGE);
   398       val1->help = val2->help;
   399     }
   400   if (val1->enabled != val2->enabled)
   401     {
   402       EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
   403                val1->enabled, val2->enabled);
   404       change = max (change, VISIBLE_CHANGE);
   405       val1->enabled = val2->enabled;
   406     }
   407   if (val1->button_type != val2->button_type)
   408     {
   409       EXPLAIN (val1->name, change, VISIBLE_CHANGE, "button type change",
   410                val1->button_type, val2->button_type);
   411       change = max (change, VISIBLE_CHANGE);
   412       val1->button_type = val2->button_type;
   413     }
   414   if (val1->selected != val2->selected)
   415     {
   416       EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
   417                val1->selected, val2->selected);
   418       change = max (change, VISIBLE_CHANGE);
   419       val1->selected = val2->selected;
   420     }
   421   if (val1->call_data != val2->call_data)
   422     {
   423       EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
   424                val1->call_data, val2->call_data);
   425       change = max (change, INVISIBLE_CHANGE);
   426       val1->call_data = val2->call_data;
   427     }
   428 
   429   if (level > 0)
   430     {
   431       merged_contents =
   432         merge_widget_value (val1->contents, val2->contents, level - 1,
   433                             change_p);
   434 
   435       if (val1->contents && !merged_contents)
   436         {
   437           /* This used to say INVISIBLE_CHANGE,
   438              but it is visible and vitally important when
   439              the contents of the menu bar itself are entirely deleted.
   440 
   441              But maybe it doesn't matter.  This fails to fix the bug.  */
   442           EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(contents gone)",
   443                    0, 0);
   444           change = max (change, STRUCTURAL_CHANGE);
   445         }
   446       else if (merged_contents && merged_contents->change != NO_CHANGE)
   447         {
   448           EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
   449                    0, 0);
   450           change = max (change, INVISIBLE_CHANGE);
   451 #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c.  */
   452 #ifdef USE_MOTIF
   453           change = max (merged_contents->change, change);
   454 #endif
   455 #endif
   456         }
   457 
   458       val1->contents = merged_contents;
   459     }
   460 
   461   this_one_change = change;
   462 
   463   merged_next = merge_widget_value (val1->next, val2->next, level, change_p);
   464 
   465   if (val1->next && !merged_next)
   466     {
   467       EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
   468                0, 0);
   469       change = max (change, STRUCTURAL_CHANGE);
   470     }
   471   else if (merged_next)
   472     {
   473       if (merged_next->change)
   474         EXPLAIN (val1->name, change, merged_next->change, "(following change)",
   475                  0, 0);
   476       change = max (change, merged_next->change);
   477     }
   478 
   479   val1->next = merged_next;
   480 
   481   val1->this_one_change = this_one_change;
   482   val1->change = change;
   483 
   484   if (change > NO_CHANGE && val1->toolkit_data)
   485     {
   486       *change_p = 1;
   487       if (val1->free_toolkit_data)
   488         XtFree (val1->toolkit_data);
   489       val1->toolkit_data = NULL;
   490     }
   491 
   492   return val1;
   493 }
   494 
   495 
   496 /* modifying the widgets */
   497 static Widget
   498 name_to_widget (widget_instance *instance, const char *name)
   499 {
   500   Widget widget = NULL;
   501 
   502   if (!instance->widget)
   503     return NULL;
   504 
   505   if (!strcmp (XtName (instance->widget), name))
   506     widget = instance->widget;
   507   else
   508     {
   509       int length = strlen (name) + 2;
   510       char* real_name = (char *) xmalloc (length);
   511       real_name [0] = '*';
   512       strcpy (real_name + 1, name);
   513 
   514       widget = XtNameToWidget (instance->widget, real_name);
   515 
   516       xfree (real_name);
   517     }
   518   return widget;
   519 }
   520 
   521 static void
   522 set_one_value (widget_instance* instance, widget_value* val, Boolean deep_p)
   523 {
   524   Widget widget = name_to_widget (instance, val->name);
   525 
   526   if (widget)
   527     {
   528 #if defined (USE_LUCID)
   529       if (lw_lucid_widget_p (instance->widget))
   530         xlw_update_one_widget (instance, widget, val, deep_p);
   531 #endif
   532 #if defined (USE_MOTIF)
   533       if (lw_motif_widget_p (instance->widget))
   534         xm_update_one_widget (instance, widget, val, deep_p);
   535 #endif
   536 #if defined (USE_XAW)
   537       if (lw_xaw_widget_p (instance->widget))
   538         xaw_update_one_widget (instance, widget, val, deep_p);
   539 #endif
   540     }
   541 }
   542 
   543 static void
   544 update_one_widget_instance (widget_instance* instance, Boolean deep_p)
   545 {
   546   widget_value *val;
   547 
   548   if (!instance->widget)
   549     /* the widget was destroyed */
   550     return;
   551 
   552   for (val = instance->info->val; val; val = val->next)
   553     if (val->change != NO_CHANGE)
   554       set_one_value (instance, val, deep_p);
   555 }
   556 
   557 static void
   558 update_all_widget_values (widget_info* info, Boolean deep_p)
   559 {
   560   widget_instance* instance;
   561   widget_value* val;
   562 
   563   for (instance = info->instances; instance; instance = instance->next)
   564     update_one_widget_instance (instance, deep_p);
   565 
   566   for (val = info->val; val; val = val->next)
   567     val->change = NO_CHANGE;
   568 }
   569 
   570 int
   571 lw_modify_all_widgets (LWLIB_ID id, widget_value* val, Boolean deep_p)
   572 {
   573   widget_info* info = get_widget_info (id, False);
   574   widget_value* new_val;
   575   widget_value* next_new_val;
   576   widget_value* cur;
   577   widget_value* prev;
   578   widget_value* next;
   579   int           found;
   580   int change_p = 0;
   581 
   582   if (!info)
   583     return 0;
   584 
   585   for (new_val = val; new_val; new_val = new_val->next)
   586     {
   587       next_new_val = new_val->next;
   588       new_val->next = NULL;
   589       found = False;
   590       for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
   591         if (!strcmp (cur->name, new_val->name))
   592           {
   593             found = True;
   594             next = cur->next;
   595             cur->next = NULL;
   596             cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1,
   597                                       &change_p);
   598             if (prev)
   599               prev->next = cur ? cur : next;
   600             else
   601               info->val = cur ? cur : next;
   602             if (cur)
   603               cur->next = next;
   604             break;
   605           }
   606       if (!found)
   607         {
   608           /* Could not find it, add it */
   609           if (prev)
   610             prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
   611           else
   612             info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
   613           change_p = 1;
   614         }
   615       new_val->next = next_new_val;
   616     }
   617 
   618   update_all_widget_values (info, deep_p);
   619   return change_p;
   620 }
   621 
   622 
   623 /* creating the widgets */
   624 
   625 static void
   626 initialize_widget_instance (widget_instance *instance)
   627 {
   628   widget_value* val;
   629 
   630   for (val = instance->info->val; val; val = val->next)
   631     val->change = STRUCTURAL_CHANGE;
   632 
   633   update_one_widget_instance (instance, True);
   634 
   635   for (val = instance->info->val; val; val = val->next)
   636     val->change = NO_CHANGE;
   637 }
   638 
   639 
   640 static widget_creation_function
   641 find_in_table (const char *type, const widget_creation_entry *table)
   642 {
   643   const widget_creation_entry* cur;
   644   for (cur = table; cur->type; cur++)
   645     if (!c_strcasecmp (type, cur->type))
   646       return cur->function;
   647   return NULL;
   648 }
   649 
   650 static Boolean
   651 dialog_spec_p (const char *name)
   652 {
   653   /* return True if name matches [EILPQeilpq][1-9][Bb] or
   654      [EILPQeilpq][1-9][Bb][Rr][1-9] */
   655   if (!name)
   656     return False;
   657 
   658   switch (name [0])
   659     {
   660     case 'E': case 'I': case 'L': case 'P': case 'Q':
   661     case 'e': case 'i': case 'l': case 'p': case 'q':
   662       if (name [1] >= '0' && name [1] <= '9')
   663         {
   664           if (name [2] != 'B' && name [2] != 'b')
   665             return False;
   666           if (!name [3])
   667             return True;
   668           if ((name [3] == 'T' || name [3] == 't') && !name [4])
   669             return True;
   670           if ((name [3] == 'R' || name [3] == 'r')
   671               && name [4] >= '0' && name [4] <= '9' && !name [5])
   672             return True;
   673           return False;
   674         }
   675       else
   676         return False;
   677 
   678     default:
   679       return False;
   680     }
   681 }
   682 
   683 static void
   684 instantiate_widget_instance (widget_instance *instance)
   685 {
   686   widget_creation_function function = NULL;
   687 
   688 #if defined (USE_LUCID)
   689   if (!function)
   690     function = find_in_table (instance->info->type, xlw_creation_table);
   691 #endif
   692 #if defined(USE_MOTIF)
   693   if (!function)
   694     function = find_in_table (instance->info->type, xm_creation_table);
   695 #endif
   696 #if defined (USE_XAW)
   697   if (!function)
   698     function = find_in_table (instance->info->type, xaw_creation_table);
   699 #endif
   700 
   701   if (!function)
   702     {
   703       if (dialog_spec_p (instance->info->type))
   704         {
   705 #if defined (USE_LUCID)
   706           /* not yet */
   707 #endif
   708 #if defined(USE_MOTIF)
   709           if (!function)
   710             function = xm_create_dialog;
   711 #endif
   712 #if defined (USE_XAW)
   713           if (!function)
   714             function = xaw_create_dialog;
   715 #endif
   716         }
   717     }
   718 
   719   if (!function)
   720     {
   721       printf ("No creation function for widget type %s\n",
   722               instance->info->type);
   723       emacs_abort ();
   724     }
   725 
   726   instance->widget = (*function) (instance);
   727 
   728   if (!instance->widget)
   729     emacs_abort ();
   730 
   731   /*   XtRealizeWidget (instance->widget);*/
   732 }
   733 
   734 void
   735 lw_register_widget (const char* type,
   736                     const char* name,
   737                     LWLIB_ID id,
   738                     widget_value* val,
   739                     lw_callback pre_activate_cb,
   740                     lw_callback selection_cb,
   741                     lw_callback post_activate_cb,
   742                     lw_callback highlight_cb)
   743 {
   744   if (!get_widget_info (id, False))
   745     allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
   746                           post_activate_cb, highlight_cb);
   747 }
   748 
   749 Widget
   750 lw_get_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
   751 {
   752   widget_instance* instance;
   753 
   754   instance = find_instance (id, parent, pop_up_p);
   755   return instance ? instance->widget : NULL;
   756 }
   757 
   758 Widget
   759 lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
   760 {
   761   widget_instance* instance;
   762   widget_info* info;
   763 
   764   instance = find_instance (id, parent, pop_up_p);
   765   if (!instance)
   766     {
   767       info = get_widget_info (id, False);
   768       if (!info)
   769         return NULL;
   770       instance = allocate_widget_instance (info, parent, pop_up_p);
   771       initialize_widget_instance (instance);
   772     }
   773   if (!instance->widget)
   774     emacs_abort ();
   775   return instance->widget;
   776 }
   777 
   778 Widget
   779 lw_create_widget (const char* type, const char* name, LWLIB_ID id, widget_value* val,
   780                   Widget parent, Boolean pop_up_p,
   781                   lw_callback pre_activate_cb, lw_callback selection_cb,
   782                   lw_callback post_activate_cb, lw_callback highlight_cb)
   783 {
   784   lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
   785                       post_activate_cb, highlight_cb);
   786   return lw_make_widget (id, parent, pop_up_p);
   787 }
   788 
   789 
   790 /* destroying the widgets */
   791 static void
   792 destroy_one_instance (widget_instance *instance)
   793 {
   794   /* Remove the destroy callback on the widget; that callback will try to
   795      dereference the instance object (to set its widget slot to 0, since the
   796      widget is dead.)  Since the instance is now dead, we don't have to worry
   797      about the fact that its widget is dead too.
   798 
   799      This happens in the Phase2Destroy of the widget, so this callback would
   800      not have been run until arbitrarily long after the instance was freed.
   801    */
   802   if (instance->widget)
   803     XtRemoveCallback (instance->widget, XtNdestroyCallback,
   804                       mark_widget_destroyed, (XtPointer)instance);
   805 
   806   if (instance->widget)
   807     {
   808       /* The else are pretty tricky here, including the empty statement
   809          at the end because it would be very bad to destroy a widget
   810          twice. */
   811 #if defined (USE_LUCID)
   812       if (lw_lucid_widget_p (instance->widget))
   813         xlw_destroy_instance (instance);
   814       else
   815 #endif
   816 #if defined (USE_MOTIF)
   817       if (lw_motif_widget_p (instance->widget))
   818         xm_destroy_instance (instance);
   819       else
   820 #endif
   821 #if defined (USE_XAW)
   822       if (lw_xaw_widget_p (instance->widget))
   823         xaw_destroy_instance (instance);
   824       else
   825 #endif
   826         {
   827           /* Empty compound statement to terminate if-then-else chain.  */
   828         }
   829     }
   830 
   831   free_widget_instance (instance);
   832 }
   833 
   834 void
   835 lw_destroy_widget (Widget w)
   836 {
   837   widget_instance* instance = get_widget_instance (w, True);
   838 
   839   if (instance)
   840     {
   841       widget_info *info = instance->info;
   842       /* instance has already been removed from the list; free it */
   843       destroy_one_instance (instance);
   844       /* if there are no instances left, free the info too */
   845       if (!info->instances)
   846         lw_destroy_all_widgets (info->id);
   847     }
   848 }
   849 
   850 void
   851 lw_destroy_all_widgets (LWLIB_ID id)
   852 {
   853   widget_info* info = get_widget_info (id, True);
   854   widget_instance* instance;
   855   widget_instance* next;
   856 
   857   if (info)
   858     {
   859       for (instance = info->instances; instance; )
   860         {
   861           next = instance->next;
   862           destroy_one_instance (instance);
   863           instance = next;
   864         }
   865       free_widget_info (info);
   866     }
   867 }
   868 
   869 void
   870 lw_destroy_everything (void)
   871 {
   872   while (all_widget_info)
   873     lw_destroy_all_widgets (all_widget_info->id);
   874 }
   875 
   876 void
   877 lw_destroy_all_pop_ups (void)
   878 {
   879   widget_info* info;
   880   widget_info* next;
   881   widget_instance* instance;
   882 
   883   for (info = all_widget_info; info; info = next)
   884     {
   885       next = info->next;
   886       instance = info->instances;
   887       if (instance && instance->pop_up_p)
   888         lw_destroy_all_widgets (info->id);
   889     }
   890 }
   891 
   892 #ifdef USE_MOTIF
   893 extern Widget first_child (Widget);     /* garbage */
   894 #endif
   895 
   896 Widget
   897 lw_raise_all_pop_up_widgets (void)
   898 {
   899   widget_info* info;
   900   widget_instance* instance;
   901   Widget result = NULL;
   902 
   903   for (info = all_widget_info; info; info = info->next)
   904     for (instance = info->instances; instance; instance = instance->next)
   905       if (instance->pop_up_p)
   906         {
   907           Widget widget = instance->widget;
   908           if (widget)
   909             {
   910               if (XtIsManaged (widget)
   911 #ifdef USE_MOTIF
   912                   /* What a complete load of crap!!!!
   913                      When a dialogShell is on the screen, it is not managed!
   914                    */
   915                   || (lw_motif_widget_p (instance->widget) &&
   916                       XtIsManaged (first_child (widget)))
   917 #endif
   918                   )
   919                 {
   920                   if (!result)
   921                     result = widget;
   922                   XMapRaised (XtDisplay (widget), XtWindow (widget));
   923                 }
   924             }
   925         }
   926   return result;
   927 }
   928 
   929 static void
   930 lw_pop_all_widgets (LWLIB_ID id, Boolean up)
   931 {
   932   widget_info* info = get_widget_info (id, False);
   933   widget_instance* instance;
   934 
   935   if (info)
   936     for (instance = info->instances; instance; instance = instance->next)
   937       if (instance->pop_up_p && instance->widget)
   938         {
   939 #if defined (USE_LUCID)
   940           if (lw_lucid_widget_p (instance->widget))
   941             {
   942               XtRealizeWidget (instance->widget);
   943               xlw_pop_instance (instance, up);
   944             }
   945 #endif
   946 #if defined (USE_MOTIF)
   947           if (lw_motif_widget_p (instance->widget))
   948             {
   949               XtRealizeWidget (instance->widget);
   950               xm_pop_instance (instance, up);
   951             }
   952 #endif
   953 #if defined (USE_XAW)
   954           if (lw_xaw_widget_p (instance->widget))
   955             {
   956               XtRealizeWidget (XtParent (instance->widget));
   957               XtRealizeWidget (instance->widget);
   958               xaw_pop_instance (instance, up);
   959             }
   960 #endif
   961         }
   962 }
   963 
   964 void
   965 lw_pop_up_all_widgets (LWLIB_ID id)
   966 {
   967   lw_pop_all_widgets (id, True);
   968 }
   969 
   970 void
   971 lw_pop_down_all_widgets (LWLIB_ID id)
   972 {
   973   lw_pop_all_widgets (id, False);
   974 }
   975 
   976 void
   977 lw_popup_menu (Widget widget, XEvent *event)
   978 {
   979 #if defined (USE_LUCID)
   980   if (lw_lucid_widget_p (widget))
   981     xlw_popup_menu (widget, event);
   982 #endif
   983 #if defined (USE_MOTIF)
   984   if (lw_motif_widget_p (widget))
   985     xm_popup_menu (widget, event);
   986 #endif
   987 #if defined (USE_XAW)
   988   if (lw_xaw_widget_p (widget))
   989     xaw_popup_menu (widget, event);
   990 #endif
   991 }
   992 
   993 /* get the values back */
   994 static Boolean
   995 get_one_value (widget_instance *instance, widget_value *val)
   996 {
   997   Widget widget = name_to_widget (instance, val->name);
   998 
   999   if (widget)
  1000     {
  1001 #if defined (USE_LUCID)
  1002       if (lw_lucid_widget_p (instance->widget))
  1003         xlw_update_one_value (instance, widget, val);
  1004 #endif
  1005 #if defined (USE_MOTIF)
  1006       if (lw_motif_widget_p (instance->widget))
  1007         xm_update_one_value (instance, widget, val);
  1008 #endif
  1009 #if defined (USE_XAW)
  1010       if (lw_xaw_widget_p (instance->widget))
  1011         xaw_update_one_value (instance, widget, val);
  1012 #endif
  1013       return True;
  1014     }
  1015   else
  1016     return False;
  1017 }
  1018 
  1019 Boolean
  1020 lw_get_some_values (LWLIB_ID id, widget_value *val_out)
  1021 {
  1022   widget_info* info = get_widget_info (id, False);
  1023   widget_instance* instance;
  1024   widget_value* val;
  1025   Boolean result = False;
  1026 
  1027   if (!info)
  1028     return False;
  1029 
  1030   instance = info->instances;
  1031   if (!instance)
  1032     return False;
  1033 
  1034   for (val = val_out; val; val = val->next)
  1035     if (get_one_value (instance, val))
  1036       result = True;
  1037 
  1038   return result;
  1039 }
  1040 
  1041 widget_value*
  1042 lw_get_all_values (LWLIB_ID id)
  1043 {
  1044   widget_info* info = get_widget_info (id, False);
  1045   if (info)
  1046     {
  1047       widget_value* val = info->val;
  1048       if (lw_get_some_values (id, val))
  1049         return val;
  1050     }
  1051   return NULL;
  1052 }
  1053 
  1054 /* internal function used by the library dependent implementation to get the
  1055    widget_value for a given widget in an instance */
  1056 widget_value*
  1057 lw_get_widget_value_for_widget (widget_instance *instance, Widget w)
  1058 {
  1059   char* name = XtName (w);
  1060   widget_value* cur;
  1061   for (cur = instance->info->val; cur; cur = cur->next)
  1062     if (!strcmp (cur->name, name))
  1063       return cur;
  1064   return NULL;
  1065 }
  1066 
  1067 /* update other instances value when one thing changed */
  1068 
  1069 /* To forbid recursive calls */
  1070 static Boolean lwlib_updating;
  1071 
  1072 /* This function can be used as an XtCallback for the widgets that get
  1073    modified to update other instances of the widgets.  Closure should be the
  1074    widget_instance. */
  1075 void
  1076 lw_internal_update_other_instances (Widget widget,
  1077                                     XtPointer closure,
  1078                                     XtPointer call_data)
  1079 {
  1080   widget_instance* instance = (widget_instance*)closure;
  1081   char* name = XtName (widget);
  1082   widget_info* info;
  1083   widget_instance* cur;
  1084   widget_value* val;
  1085 
  1086   /* Avoid possibly infinite recursion.  */
  1087   if (lwlib_updating)
  1088     return;
  1089 
  1090   /* protect against the widget being destroyed */
  1091   if (XtWidgetBeingDestroyedP (widget))
  1092     return;
  1093 
  1094   /* Return immediately if there are no other instances */
  1095   info = instance->info;
  1096   if (!info->instances->next)
  1097     return;
  1098 
  1099   lwlib_updating = True;
  1100 
  1101   for (val = info->val; val && strcmp (val->name, name); val = val->next);
  1102 
  1103   if (val && get_one_value (instance, val))
  1104     for (cur = info->instances; cur; cur = cur->next)
  1105       if (cur != instance)
  1106         set_one_value (cur, val, True);
  1107 
  1108   lwlib_updating = False;
  1109 }
  1110 
  1111 
  1112 /* get the id */
  1113 
  1114 LWLIB_ID
  1115 lw_get_widget_id (Widget w)
  1116 {
  1117   widget_instance* instance = get_widget_instance (w, False);
  1118 
  1119   return instance ? instance->info->id : 0;
  1120 }
  1121 
  1122 /* set the keyboard focus */
  1123 void
  1124 lw_set_keyboard_focus (Widget parent, Widget w)
  1125 {
  1126 #if defined (USE_MOTIF)
  1127   xm_set_keyboard_focus (parent, w);
  1128 #else
  1129   XtSetKeyboardFocus (parent, w);
  1130 #endif
  1131 }
  1132 
  1133 /* Show busy */
  1134 static void
  1135 show_one_widget_busy (Widget w, Boolean flag)
  1136 {
  1137   Pixel foreground = 0;
  1138   Pixel background = 1;
  1139   Widget widget_to_invert = XtNameToWidget (w, "*sheet");
  1140   if (!widget_to_invert)
  1141     widget_to_invert = w;
  1142 
  1143   XtVaGetValues (widget_to_invert,
  1144                  XtNforeground, &foreground,
  1145                  XtNbackground, &background,
  1146                  NULL);
  1147   XtVaSetValues (widget_to_invert,
  1148                  XtNforeground, background,
  1149                  XtNbackground, foreground,
  1150                  NULL);
  1151 }
  1152 
  1153 void
  1154 lw_show_busy (Widget w, Boolean busy)
  1155 {
  1156   widget_instance* instance = get_widget_instance (w, False);
  1157   widget_info* info;
  1158   widget_instance* next;
  1159 
  1160   if (instance)
  1161     {
  1162       info = instance->info;
  1163       if (info->busy != busy)
  1164         {
  1165           for (next = info->instances; next; next = next->next)
  1166             if (next->widget)
  1167               show_one_widget_busy (next->widget, busy);
  1168           info->busy = busy;
  1169         }
  1170     }
  1171 }
  1172 
  1173 /* This hack exists because Lucid/Athena need to execute the strange
  1174    function below to support geometry management. */
  1175 void
  1176 lw_refigure_widget (Widget w, Boolean doit)
  1177 {
  1178 #if defined (USE_XAW)
  1179   XawPanedSetRefigureMode (w, doit);
  1180 #endif
  1181 #if defined (USE_MOTIF)
  1182   if (doit)
  1183     XtManageChild (w);
  1184   else
  1185     XtUnmanageChild (w);
  1186 #endif
  1187 }
  1188 
  1189 /* Toolkit independent way of determining if an event window is in the
  1190    menubar. */
  1191 Boolean
  1192 lw_window_is_in_menubar (Window win, Widget menubar_widget)
  1193 {
  1194   return menubar_widget
  1195 #if defined (USE_LUCID)
  1196       && XtWindow (menubar_widget) == win;
  1197 #endif
  1198 #if defined (USE_MOTIF)
  1199       && ((XtWindow (menubar_widget) == win)
  1200           || (XtWindowToWidget (XtDisplay (menubar_widget), win)
  1201               && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget), win))
  1202                   == menubar_widget)));
  1203 #endif
  1204 }
  1205 
  1206 /* Motif hack to set the main window areas. */
  1207 void
  1208 lw_set_main_areas (Widget parent, Widget menubar, Widget work_area)
  1209 {
  1210 #if defined (USE_MOTIF)
  1211   xm_set_main_areas (parent, menubar, work_area);
  1212 #endif
  1213 }
  1214 
  1215 /* Manage resizing for Motif.  This disables resizing when the menubar
  1216    is about to be modified. */
  1217 void
  1218 lw_allow_resizing (Widget w, Boolean flag)
  1219 {
  1220 #if defined (USE_MOTIF)
  1221   xm_manage_resizing (w, flag);
  1222 #endif
  1223 }
  1224 
  1225 
  1226 /* Value is non-zero if LABEL is a menu separator.  If it is, *TYPE is
  1227    set to an appropriate enumerator of type enum menu_separator.
  1228    MOTIF_P non-zero means map separator types not supported by Motif
  1229    to similar ones that are supported.  */
  1230 
  1231 int
  1232 lw_separator_p (const char *label, enum menu_separator *type, int motif_p)
  1233 {
  1234   int separator_p = 0;
  1235 
  1236   if (strncmp (label, "--:",  3) == 0)
  1237     {
  1238       static struct separator_table
  1239       {
  1240         const char *name;
  1241         enum menu_separator type;
  1242       }
  1243       separator_names[] =
  1244       {
  1245         {"space",                     SEPARATOR_NO_LINE},
  1246         {"noLine",                    SEPARATOR_NO_LINE},
  1247         {"singleLine",                SEPARATOR_SINGLE_LINE},
  1248         {"doubleLine",                SEPARATOR_DOUBLE_LINE},
  1249         {"singleDashedLine",          SEPARATOR_SINGLE_DASHED_LINE},
  1250         {"doubleDashedLine",          SEPARATOR_DOUBLE_DASHED_LINE},
  1251         {"shadowEtchedIn",            SEPARATOR_SHADOW_ETCHED_IN},
  1252         {"shadowEtchedOut",           SEPARATOR_SHADOW_ETCHED_OUT},
  1253         {"shadowEtchedInDash",        SEPARATOR_SHADOW_ETCHED_IN_DASH},
  1254         {"shadowEtchedOutDash",       SEPARATOR_SHADOW_ETCHED_OUT_DASH},
  1255         {"shadowDoubleEtchedIn",      SEPARATOR_SHADOW_DOUBLE_ETCHED_IN},
  1256         {"shadowDoubleEtchedOut",     SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT},
  1257         {"shadowDoubleEtchedInDash",  SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH},
  1258         {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH},
  1259         {0,0}
  1260       };
  1261 
  1262       int i;
  1263 
  1264       label += 3;
  1265       for (i = 0; separator_names[i].name; ++i)
  1266         if (strcmp (label, separator_names[i].name) == 0)
  1267           {
  1268             separator_p = 1;
  1269             *type = separator_names[i].type;
  1270 
  1271             /* If separator type is not supported under Motif,
  1272                use a similar one.  */
  1273             if (motif_p && *type >= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN)
  1274               *type -= 4;
  1275             break;
  1276           }
  1277     }
  1278   else if (strnlen (label, 4) == 4
  1279            && memcmp (label, "--", 2) == 0
  1280            && label[2] != '-')
  1281     {
  1282       /* Alternative, more Emacs-style names.  */
  1283       static struct separator_table
  1284       {
  1285         const char *name;
  1286         enum menu_separator type;
  1287       }
  1288       separator_names[] =
  1289       {
  1290         {"space",                        SEPARATOR_NO_LINE},
  1291         {"no-line",                      SEPARATOR_NO_LINE},
  1292         {"single-line",                  SEPARATOR_SINGLE_LINE},
  1293         {"double-line",                  SEPARATOR_DOUBLE_LINE},
  1294         {"single-dashed-line",           SEPARATOR_SINGLE_DASHED_LINE},
  1295         {"double-dashed-line",           SEPARATOR_DOUBLE_DASHED_LINE},
  1296         {"shadow-etched-in",             SEPARATOR_SHADOW_ETCHED_IN},
  1297         {"shadow-etched-out",            SEPARATOR_SHADOW_ETCHED_OUT},
  1298         {"shadow-etched-in-dash",        SEPARATOR_SHADOW_ETCHED_IN_DASH},
  1299         {"shadow-etched-out-dash",       SEPARATOR_SHADOW_ETCHED_OUT_DASH},
  1300         {"shadow-double-etched-in",      SEPARATOR_SHADOW_DOUBLE_ETCHED_IN},
  1301         {"shadow-double-etched-out",     SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT},
  1302         {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH},
  1303         {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH},
  1304         {0,0}
  1305       };
  1306 
  1307       int i;
  1308 
  1309       label += 2;
  1310       for (i = 0; separator_names[i].name; ++i)
  1311         if (strcmp (label, separator_names[i].name) == 0)
  1312           {
  1313             separator_p = 1;
  1314             *type = separator_names[i].type;
  1315 
  1316             /* If separator type is not supported under Motif,
  1317                use a similar one.  */
  1318             if (motif_p && *type >= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN)
  1319               *type -= 4;
  1320             break;
  1321           }
  1322     }
  1323   else
  1324     {
  1325       /* Old-style separator, maybe.  It's a separator if it contains
  1326          only dashes.  */
  1327       if (*label == '-')
  1328         {
  1329           while (*label == '-')
  1330             ++label;
  1331           separator_p = *label == 0;
  1332 
  1333           *type = SEPARATOR_SHADOW_ETCHED_IN;
  1334         }
  1335     }
  1336 
  1337   return separator_p;
  1338 }

/* [<][>][^][v][top][bottom][index][help] */