root/lwlib/lwlib-Xm.c

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

DEFINITIONS

This source file includes following definitions.
  1. x_print_complete_resource_name
  2. make_destroyed_instance
  3. free_destroyed_instance
  4. first_child
  5. lw_motif_widget_p
  6. resource_motif_string
  7. destroy_all_children
  8. xm_arm_callback
  9. xm_update_label
  10. xm_update_list
  11. xm_update_pushbutton
  12. xm_update_cascadebutton
  13. xm_update_toggle
  14. xm_update_radiobox
  15. make_menu_in_widget
  16. update_one_menu_entry
  17. xm_update_menu
  18. xm_update_text
  19. xm_update_text_field
  20. xm_update_one_widget
  21. xm_update_one_value
  22. activate_button
  23. dialog_key_cb
  24. make_dialog
  25. find_matching_instance
  26. mark_dead_instance_destroyed
  27. recenter_widget
  28. recycle_instance
  29. xm_create_dialog
  30. make_menubar
  31. remove_grabs
  32. make_popup_menu
  33. make_main
  34. make_one
  35. make_project_p_sheet
  36. make_debugger_p_sheet
  37. make_breaklist_p_sheet
  38. make_le_browser_p_sheet
  39. make_class_browser_p_sheet
  40. make_call_browser_p_sheet
  41. make_build_dialog
  42. make_editmode_dialog
  43. make_search_dialog
  44. make_project_display_dialog
  45. xm_destroy_instance
  46. xm_popup_menu
  47. set_min_dialog_size
  48. xm_pop_instance
  49. do_call
  50. xm_internal_update_other_instances
  51. xm_generic_callback
  52. xm_nosel_callback
  53. xm_pull_down_callback
  54. xm_pop_down_callback
  55. xm_pop_up_callback
  56. xm_set_keyboard_focus
  57. xm_set_main_areas
  58. xm_manage_resizing

     1 /* The lwlib interface to Motif widgets.
     2 
     3 Copyright (C) 1994-1997, 1999-2023 Free Software Foundation, Inc.
     4 Copyright (C) 1992 Lucid, 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 1, 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 <unistd.h>
    24 #include <stdio.h>
    25 #include <setjmp.h>
    26 
    27 #include <X11/StringDefs.h>
    28 #include <X11/IntrinsicP.h>
    29 #include <X11/ObjectP.h>
    30 #include <X11/CoreP.h>
    31 #include <X11/CompositeP.h>
    32 
    33 #include <lisp.h>
    34 
    35 #include "lwlib-Xm.h"
    36 #include "lwlib-utils.h"
    37 
    38 #include <Xm/BulletinB.h>
    39 #include <Xm/CascadeB.h>
    40 #include <Xm/CascadeBG.h>
    41 #include <Xm/DrawingA.h>
    42 #include <Xm/FileSB.h>
    43 #include <Xm/Label.h>
    44 #include <Xm/List.h>
    45 #include <Xm/MainW.h>
    46 #include <Xm/MenuShell.h>
    47 #include <Xm/MessageB.h>
    48 #include <Xm/PanedW.h>
    49 #include <Xm/PushB.h>
    50 #include <Xm/PushBG.h>
    51 #include <Xm/ArrowB.h>
    52 #include <Xm/SelectioB.h>
    53 #include <Xm/Text.h>
    54 #include <Xm/TextF.h>
    55 #include <Xm/ToggleB.h>
    56 #include <Xm/ToggleBG.h>
    57 #include <Xm/RowColumn.h>
    58 #include <Xm/ScrolledW.h>
    59 #include <Xm/Separator.h>
    60 #include <Xm/DialogS.h>
    61 #include <Xm/Form.h>
    62 
    63 enum do_call_type { pre_activate, selection, no_selection, post_activate };
    64 
    65 
    66 /* Structures to keep destroyed instances */
    67 typedef struct _destroyed_instance
    68 {
    69   char*         name;
    70   char*         type;
    71   Widget        widget;
    72   Widget        parent;
    73   Boolean       pop_up_p;
    74   struct _destroyed_instance*   next;
    75 } destroyed_instance;
    76 
    77 static destroyed_instance *make_destroyed_instance (char *, char *,
    78                                                     Widget, Widget,
    79                                                     Boolean);
    80 static void free_destroyed_instance (destroyed_instance*);
    81 Widget first_child (Widget);
    82 static XmString resource_motif_string (Widget, char *);
    83 static void destroy_all_children (Widget, int);
    84 static void xm_update_label (widget_instance *, Widget, widget_value *);
    85 static void xm_update_list (widget_instance *, Widget, widget_value *);
    86 static void xm_update_pushbutton (widget_instance *, Widget,
    87                                   widget_value *);
    88 static void xm_update_cascadebutton (widget_instance *, Widget,
    89                                      widget_value *);
    90 static void xm_update_toggle (widget_instance *, Widget, widget_value *);
    91 static void xm_update_radiobox (widget_instance *, Widget, widget_value *);
    92 static void make_menu_in_widget (widget_instance *, Widget,
    93                                  widget_value *, int);
    94 static void update_one_menu_entry (widget_instance *, Widget,
    95                                    widget_value *, Boolean);
    96 static void xm_update_menu (widget_instance *, Widget, widget_value *,
    97                             Boolean);
    98 static void xm_update_text (widget_instance *, Widget, widget_value *);
    99 static void xm_update_text_field (widget_instance *, Widget,
   100                                   widget_value *);
   101 static void activate_button (Widget, XtPointer, XtPointer);
   102 static Widget make_dialog (char *, Widget, Boolean, char *, char *,
   103                            Boolean, Boolean, Boolean, int, int);
   104 static destroyed_instance* find_matching_instance (widget_instance*);
   105 static void mark_dead_instance_destroyed (Widget, XtPointer, XtPointer);
   106 static void recenter_widget (Widget);
   107 static Widget recycle_instance (destroyed_instance*);
   108 static Widget make_menubar (widget_instance*);
   109 static void remove_grabs (Widget, XtPointer, XtPointer);
   110 static Widget make_popup_menu (widget_instance*);
   111 static Widget make_main (widget_instance*);
   112 static void set_min_dialog_size (Widget);
   113 static void do_call (Widget, XtPointer, enum do_call_type);
   114 static void xm_generic_callback (Widget, XtPointer, XtPointer);
   115 static void xm_nosel_callback (Widget, XtPointer, XtPointer);
   116 static void xm_pull_down_callback (Widget, XtPointer, XtPointer);
   117 static void xm_pop_down_callback (Widget, XtPointer, XtPointer);
   118 static void xm_pop_up_callback (Widget, XtPointer, XtPointer);
   119 static void xm_internal_update_other_instances (Widget, XtPointer,
   120                                                 XtPointer);
   121 static void xm_arm_callback (Widget, XtPointer, XtPointer);
   122 
   123 #if 0
   124 void xm_update_one_widget (widget_instance *, Widget, widget_value *,
   125                            Boolean);
   126 void xm_pop_instance (widget_instance*, Boolean);
   127 void xm_manage_resizing (Widget, Boolean);
   128 #endif
   129 
   130 
   131 #if 0
   132 
   133 /* Print the complete X resource name of widget WIDGET to stderr.
   134    This is sometimes handy to have available.  */
   135 
   136 void
   137 x_print_complete_resource_name (Widget widget)
   138 {
   139   int i;
   140   String names[100];
   141 
   142   for (i = 0; i < 100 && widget != NULL; ++i)
   143     {
   144       names[i] = XtName (widget);
   145       widget = XtParent (widget);
   146     }
   147 
   148   for (--i; i >= 1; --i)
   149     fprintf (stderr, "%s.", names[i]);
   150   fprintf (stderr, "%s\n", names[0]);
   151 }
   152 
   153 #endif /* 0 */
   154 
   155 
   156 static destroyed_instance *all_destroyed_instances = NULL;
   157 
   158 static destroyed_instance*
   159 make_destroyed_instance (char* name,
   160                          char* type,
   161                          Widget widget,
   162                          Widget parent,
   163                          Boolean pop_up_p)
   164 {
   165   destroyed_instance* instance =
   166     (destroyed_instance*) xmalloc (sizeof (destroyed_instance));
   167   instance->name = xstrdup (name);
   168   instance->type = xstrdup (type);
   169   instance->widget = widget;
   170   instance->parent = parent;
   171   instance->pop_up_p = pop_up_p;
   172   instance->next = NULL;
   173   return instance;
   174 }
   175 
   176 static void
   177 free_destroyed_instance (destroyed_instance* instance)
   178 {
   179   xfree (instance->name);
   180   xfree (instance->type);
   181   xfree (instance);
   182 }
   183 
   184 /* motif utility functions */
   185 Widget
   186 first_child (Widget widget)
   187 {
   188   return ((CompositeWidget)widget)->composite.children [0];
   189 }
   190 
   191 Boolean
   192 lw_motif_widget_p (Widget widget)
   193 {
   194   return
   195     XtClass (widget) == xmDialogShellWidgetClass
   196       || XmIsPrimitive (widget) || XmIsManager (widget) || XmIsGadget (widget);
   197 }
   198 
   199 static XmString
   200 resource_motif_string (Widget widget,
   201                        char* name)
   202 {
   203   XtResource resource;
   204   XmString result = 0;
   205 
   206   resource.resource_name = name;
   207   resource.resource_class = XmCXmString;
   208   resource.resource_type = XmRXmString;
   209   resource.resource_size = sizeof (XmString);
   210   resource.resource_offset = 0;
   211   resource.default_type = XtRImmediate;
   212   resource.default_addr = 0;
   213 
   214   XtGetSubresources (widget, (XtPointer)&result, "dialogString",
   215                      "DialogString", &resource, 1, NULL, 0);
   216   return result;
   217 }
   218 
   219 /* Destroy all of the children of WIDGET
   220    starting with number FIRST_CHILD_TO_DESTROY.  */
   221 
   222 static void
   223 destroy_all_children (Widget widget,
   224                       int first_child_to_destroy)
   225 {
   226   Widget* children;
   227   unsigned int number;
   228   int i;
   229 
   230   children = XtCompositeChildren (widget, &number);
   231   if (children)
   232     {
   233       XtUnmanageChildren (children + first_child_to_destroy,
   234                           number - first_child_to_destroy);
   235 
   236       /* Unmanage all children and destroy them.  They will only be
   237          really destroyed when we get out of DispatchEvent.  */
   238       for (i = first_child_to_destroy; i < number; i++)
   239         {
   240           Arg al[2];
   241           Widget submenu = 0;
   242           /* Cascade buttons have submenus,and these submenus
   243              need to be freed.  But they are not included in
   244              XtCompositeChildren.  So get it out of the cascade button
   245              and free it.  If this child is not a cascade button,
   246              then submenu should remain unchanged.  */
   247           XtSetArg (al[0], XmNsubMenuId, &submenu);
   248           XtGetValues (children[i], al, 1);
   249           if (submenu)
   250             {
   251               destroy_all_children (submenu, 0);
   252               XtDestroyWidget (submenu);
   253             }
   254           XtDestroyWidget (children[i]);
   255         }
   256 
   257       XtFree ((char *) children);
   258     }
   259 }
   260 
   261 
   262 
   263 /* Callback XmNarmCallback and XmNdisarmCallback for buttons in a
   264    menu.  CLIENT_DATA contains a pointer to the widget_value
   265    corresponding to widget W.  CALL_DATA contains a
   266    XmPushButtonCallbackStruct containing the reason why the callback
   267    is called.  */
   268 
   269 static void
   270 xm_arm_callback (Widget w, XtPointer client_data, XtPointer call_data)
   271 {
   272   XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct *) call_data;
   273   widget_value *wv = NULL;
   274   widget_instance *instance = client_data;
   275   XtPointer user_data;
   276   Arg al[2];
   277   int ac = 0;
   278 
   279   XtSetArg (al[ac], XmNuserData, &user_data); ac++;
   280   XtGetValues (w, al, ac);
   281   wv = user_data;
   282 
   283   if (wv != NULL)
   284     {
   285       if (instance->info->highlight_cb
   286           && (cbs->reason == XmCR_DISARM
   287               || (cbs->event
   288                   && (cbs->event->type == EnterNotify
   289                       || cbs->event->type == MotionNotify))))
   290         {
   291           call_data = cbs->reason == XmCR_DISARM ? NULL : wv;
   292           instance->info->highlight_cb (w, instance->info->id, call_data);
   293         }
   294     }
   295 }
   296 
   297 
   298 
   299 /* Update the label of widget WIDGET.  WIDGET must be a Label widget
   300    or a subclass of Label.  WIDGET_INSTANCE is unused.  VAL contains
   301    the value to update.
   302 
   303    Menus:
   304 
   305    Emacs fills VAL->name with the text to display in the menu, and
   306    sets VAL->value to null.  Function make_menu_in_widget creates
   307    widgets with VAL->name as resource name.  This works because the
   308    Label widget uses its resource name for display if no
   309    XmNlabelString is set.
   310 
   311    Dialogs:
   312 
   313    VAL->name is again set to the resource name, but VAL->value is
   314    not null, and contains the label string to display.  */
   315 
   316 static void
   317 xm_update_label (widget_instance* instance,
   318                  Widget widget,
   319                  widget_value* val)
   320 {
   321   XmString res_string = 0;
   322   XmString built_string = 0;
   323   XmString key_string = 0;
   324   Arg al [256];
   325   int ac;
   326 
   327   ac = 0;
   328 
   329   if (val->value)
   330     {
   331       /* A label string is specified, i.e. we are in a dialog.  First
   332          see if it is overridden by something from the resource file.  */
   333       res_string = resource_motif_string (widget, val->value);
   334 
   335       if (res_string)
   336         {
   337           XtSetArg (al [ac], XmNlabelString, res_string); ac++;
   338         }
   339       else
   340         {
   341           built_string =
   342             XmStringCreateLocalized (val->value);
   343           XtSetArg (al [ac], XmNlabelString, built_string); ac++;
   344         }
   345 
   346       XtSetArg (al [ac], XmNlabelType, XmSTRING); ac++;
   347     }
   348 
   349   if (val->key)
   350     {
   351       key_string = XmStringCreateLocalized (val->key);
   352       XtSetArg (al [ac], XmNacceleratorText, key_string); ac++;
   353     }
   354 
   355   if (ac)
   356     XtSetValues (widget, al, ac);
   357 
   358   if (built_string)
   359     XmStringFree (built_string);
   360 
   361   if (key_string)
   362     XmStringFree (key_string);
   363 }
   364 
   365 /* update of list */
   366 static void
   367 xm_update_list (widget_instance* instance,
   368                 Widget widget,
   369                 widget_value* val)
   370 {
   371   widget_value* cur;
   372   int i;
   373   XtRemoveAllCallbacks (widget, XmNsingleSelectionCallback);
   374   XtAddCallback (widget, XmNsingleSelectionCallback, xm_generic_callback,
   375                  instance);
   376   for (cur = val->contents, i = 0; cur; cur = cur->next)
   377     if (cur->value)
   378       {
   379         XmString xmstr = XmStringCreateLocalized (cur->value);
   380         i += 1;
   381         XmListAddItem (widget, xmstr, 0);
   382         if (cur->selected)
   383           XmListSelectPos (widget, i, False);
   384         XmStringFree (xmstr);
   385       }
   386 }
   387 
   388 /* update of buttons */
   389 static void
   390 xm_update_pushbutton (widget_instance* instance,
   391                       Widget widget,
   392                       widget_value* val)
   393 {
   394   XtVaSetValues (widget, XmNalignment, XmALIGNMENT_CENTER, NULL);
   395   XtRemoveAllCallbacks (widget, XmNactivateCallback);
   396   XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
   397 }
   398 
   399 static void
   400 xm_update_cascadebutton (widget_instance* instance,
   401                          Widget widget,
   402                          widget_value* val)
   403 {
   404   /* Should also rebuild the menu by calling ...update_menu... */
   405   XtRemoveAllCallbacks (widget, XmNcascadingCallback);
   406   XtAddCallback (widget, XmNcascadingCallback, xm_pull_down_callback,
   407                  instance);
   408 }
   409 
   410 /* update toggle and radiobox */
   411 static void
   412 xm_update_toggle (widget_instance* instance,
   413                   Widget widget,
   414                   widget_value* val)
   415 {
   416   XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
   417   XtAddCallback (widget, XmNvalueChangedCallback,
   418                  xm_generic_callback, instance);
   419   XtVaSetValues (widget, XmNset, val->selected,
   420                  XmNalignment, XmALIGNMENT_BEGINNING, NULL);
   421 }
   422 
   423 static void
   424 xm_update_radiobox (widget_instance* instance,
   425                     Widget widget,
   426                     widget_value* val)
   427 
   428 {
   429   Widget toggle;
   430   widget_value* cur;
   431 
   432   /* update the callback */
   433   XtRemoveAllCallbacks (widget, XmNentryCallback);
   434   XtAddCallback (widget, XmNentryCallback, xm_generic_callback, instance);
   435 
   436   /* first update all the toggles */
   437   /* Energize kernel interface is currently bad.  It sets the selected widget
   438      with the selected flag but returns it by its name.  So we currently
   439      have to support both setting the selection with the selected slot
   440      of val contents and setting it with the "value" slot of val.  The latter
   441      has a higher priority.  This to be removed when the kernel is fixed. */
   442   for (cur = val->contents; cur; cur = cur->next)
   443     {
   444       toggle = XtNameToWidget (widget, cur->value);
   445       if (toggle)
   446         {
   447           XtSetSensitive (toggle, cur->enabled);
   448           if (!val->value && cur->selected)
   449             XtVaSetValues (toggle, XmNset, cur->selected, NULL);
   450           if (val->value && strcmp (val->value, cur->value))
   451             XtVaSetValues (toggle, XmNset, False, NULL);
   452         }
   453     }
   454 
   455   /* The selected was specified by the value slot */
   456   if (val->value)
   457     {
   458       toggle = XtNameToWidget (widget, val->value);
   459       if (toggle)
   460         XtVaSetValues (toggle, XmNset, True, NULL);
   461     }
   462 }
   463 
   464 
   465 /* update a popup menu, pulldown menu or a menubar */
   466 
   467 /* KEEP_FIRST_CHILDREN gives the number of initial children to keep.  */
   468 
   469 static void
   470 make_menu_in_widget (widget_instance* instance,
   471                      Widget widget,
   472                      widget_value* val,
   473                      int keep_first_children)
   474 {
   475   Widget* children = 0;
   476   int num_children;
   477   int child_index;
   478   widget_value* cur;
   479   Widget button = 0;
   480   Widget menu;
   481   Arg al [256];
   482   int ac;
   483   Boolean menubar_p;
   484   unsigned char type;
   485 
   486   Widget* old_children;
   487   unsigned int old_num_children;
   488 
   489   /* Disable drag and drop for labels in menu bar.  */
   490   static char overrideTrans[] = "<Btn2Down>: Noop()";
   491   XtTranslations override = XtParseTranslationTable (overrideTrans);
   492 
   493   old_children = XtCompositeChildren (widget, &old_num_children);
   494 
   495   /* Allocate the children array */
   496   for (num_children = 0, cur = val; cur; num_children++, cur = cur->next)
   497     ;
   498   children = (Widget*)(void*)XtMalloc (num_children * sizeof (Widget));
   499 
   500 #ifndef LESSTIF_VERSION
   501   /* WIDGET should be a RowColumn.  */
   502   if (!XmIsRowColumn (widget))
   503     emacs_abort ();
   504 #endif
   505 
   506   /* Determine whether WIDGET is a menu bar.  */
   507   type = -1;
   508   XtSetArg (al[0], XmNrowColumnType, &type);
   509   XtGetValues (widget, al, 1);
   510   if (type != XmMENU_BAR && type != XmMENU_PULLDOWN && type != XmMENU_POPUP)
   511     emacs_abort ();
   512   menubar_p = type == XmMENU_BAR;
   513 
   514   /* Add a callback to popups and pulldowns that is called when
   515      it is made invisible again.  */
   516   if (!menubar_p)
   517     {
   518       XtAddCallback (XtParent (widget), XmNpopdownCallback,
   519                      xm_pop_down_callback, (XtPointer) instance);
   520       XtAddCallback (XtParent (widget), XmNpopupCallback,
   521                      xm_pop_up_callback, (XtPointer) instance);
   522     }
   523 
   524   /* Preserve the first KEEP_FIRST_CHILDREN old children.  */
   525   for (child_index = 0, cur = val; child_index < keep_first_children;
   526        child_index++, cur = cur->next)
   527     children[child_index] = old_children[child_index];
   528 
   529   /* Check that those are all we have
   530      (the caller should have deleted the rest).  */
   531   if (old_num_children != keep_first_children)
   532     emacs_abort ();
   533 
   534   /* Create the rest.  */
   535   for (child_index = keep_first_children; cur; child_index++, cur = cur->next)
   536     {
   537       enum menu_separator separator;
   538 
   539       ac = 0;
   540       XtSetArg (al[ac], XmNsensitive, cur->enabled); ac++;
   541       XtSetArg (al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
   542       XtSetArg (al[ac], XmNuserData, cur); ac++;
   543 
   544       if (instance->pop_up_p && !cur->contents && !cur->call_data
   545           && !lw_separator_p (cur->name, &separator, 1))
   546         {
   547           ac = 0;
   548           XtSetArg (al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
   549           button = XmCreateLabel (widget, cur->name, al, ac);
   550         }
   551       else if (lw_separator_p (cur->name, &separator, 1))
   552         {
   553           ac = 0;
   554           XtSetArg (al[ac], XmNseparatorType, separator); ++ac;
   555           button = XmCreateSeparator (widget, cur->name, al, ac);
   556         }
   557       else if (!cur->contents)
   558         {
   559           if (menubar_p)
   560             button = XmCreateCascadeButton (widget, cur->name, al, ac);
   561           else if (!cur->call_data)
   562             button = XmCreateLabel (widget, cur->name, al, ac);
   563           else if (cur->button_type == BUTTON_TYPE_TOGGLE
   564                    || cur->button_type == BUTTON_TYPE_RADIO)
   565             {
   566               XtSetArg (al[ac], XmNset, cur->selected); ++ac;
   567               XtSetArg (al[ac], XmNvisibleWhenOff, True); ++ac;
   568               XtSetArg (al[ac], XmNindicatorType,
   569                         (cur->button_type == BUTTON_TYPE_TOGGLE
   570                          ? XmN_OF_MANY : XmONE_OF_MANY));
   571               ++ac;
   572               button = XmCreateToggleButton (widget, cur->name, al, ac);
   573               XtAddCallback (button, XmNarmCallback, xm_arm_callback,
   574                              (XtPointer) instance);
   575               XtAddCallback (button, XmNdisarmCallback, xm_arm_callback,
   576                              (XtPointer) instance);
   577             }
   578           else
   579             {
   580               button = XmCreatePushButton (widget, cur->name, al, ac);
   581               XtAddCallback (button, XmNarmCallback, xm_arm_callback,
   582                              (XtPointer) instance);
   583               XtAddCallback (button, XmNdisarmCallback, xm_arm_callback,
   584                              (XtPointer) instance);
   585             }
   586 
   587           xm_update_label (instance, button, cur);
   588 
   589           /* Add a callback that is called when the button is
   590              selected.  Toggle buttons don't support
   591              XmNactivateCallback, we use XmNvalueChangedCallback in
   592              that case.  Don't add a callback to a simple label.  */
   593           if (cur->button_type)
   594             xm_update_toggle (instance, button, cur);
   595           else if (cur->call_data)
   596             XtAddCallback (button, XmNactivateCallback, xm_generic_callback,
   597                            (XtPointer)instance);
   598         }
   599       else
   600         {
   601           menu = XmCreatePulldownMenu (widget, cur->name, NULL, 0);
   602 
   603           make_menu_in_widget (instance, menu, cur->contents, 0);
   604           XtSetArg (al[ac], XmNsubMenuId, menu); ac++;
   605           button = XmCreateCascadeButton (widget, cur->name, al, ac);
   606 
   607           xm_update_label (instance, button, cur);
   608 
   609           XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
   610                          (XtPointer)instance);
   611           XtOverrideTranslations (button, override);
   612 
   613         }
   614 
   615       children[child_index] = button;
   616     }
   617 
   618   /* Last entry is the help button.  The original comment read "Has to
   619      be done after managing the buttons otherwise the menubar is only
   620      4 pixels high."  This is no longer true, and to make
   621      XmNmenuHelpWidget work, we need to set it before managing the
   622      children.. --gerd.  */
   623   if (button)
   624     XtVaSetValues (widget, XmNmenuHelpWidget, button, NULL);
   625 
   626   if (num_children)
   627     XtManageChildren (children, num_children);
   628 
   629   XtFree ((char *) children);
   630   if (old_children)
   631     XtFree ((char *) old_children);
   632 }
   633 
   634 static void
   635 update_one_menu_entry (widget_instance* instance,
   636                        Widget widget,
   637                        widget_value* val,
   638                        Boolean deep_p)
   639 {
   640   Arg al [256];
   641   int ac;
   642   Widget menu;
   643   widget_value* contents;
   644 
   645   if (val->this_one_change == NO_CHANGE)
   646     return;
   647 
   648   /* update the sensitivity and userdata */
   649   /* Common to all widget types */
   650   XtSetSensitive (widget, val->enabled);
   651   XtVaSetValues (widget, XmNuserData, val, NULL);
   652 
   653   /* update the menu button as a label. */
   654   if (val->this_one_change >= VISIBLE_CHANGE)
   655     {
   656       xm_update_label (instance, widget, val);
   657       if (val->button_type)
   658         xm_update_toggle (instance, widget, val);
   659     }
   660 
   661   /* update the pulldown/pullaside as needed */
   662   ac = 0;
   663   menu = NULL;
   664   XtSetArg (al [ac], XmNsubMenuId, &menu); ac++;
   665   XtGetValues (widget, al, ac);
   666 
   667   contents = val->contents;
   668 
   669   if (!menu)
   670     {
   671       if (contents)
   672         {
   673           unsigned int old_num_children, i;
   674           Widget parent;
   675           Widget *widget_list;
   676 
   677           parent = XtParent (widget);
   678           widget_list = XtCompositeChildren (parent, &old_num_children);
   679 
   680           /* Find the widget position within the parent's widget list.  */
   681           for (i = 0; i < old_num_children; i++)
   682             if (strcmp (XtName (widget_list[i]), XtName (widget)) == 0)
   683               break;
   684           if (i == old_num_children)
   685             emacs_abort ();
   686           if (XmIsCascadeButton (widget_list[i]))
   687             {
   688               menu = XmCreatePulldownMenu (parent, XtName(widget), NULL, 0);
   689               make_menu_in_widget (instance, menu, contents, 0);
   690               ac = 0;
   691               XtSetArg (al [ac], XmNsubMenuId, menu); ac++;
   692               XtSetValues (widget, al, ac);
   693             }
   694           else
   695             {
   696               Widget button;
   697 
   698               /* The current menuitem is a XmPushButtonGadget, it
   699                  needs to be replaced by a CascadeButtonGadget */
   700               XtDestroyWidget (widget_list[i]);
   701               menu = XmCreatePulldownMenu (parent, val->name, NULL, 0);
   702               make_menu_in_widget (instance, menu, contents, 0);
   703               ac = 0;
   704               XtSetArg (al [ac], XmNsubMenuId, menu); ac++;
   705               /* Non-zero values don't work reliably in
   706                  conjunction with Emacs' event loop */
   707               XtSetArg (al [ac], XmNmappingDelay, 0); ac++;
   708 #ifdef XmNpositionIndex /* This is undefined on SCO ODT 2.0.  */
   709               /* Tell Motif to put it in the right place */
   710               XtSetArg (al [ac], XmNpositionIndex , i); ac++;
   711 #endif
   712               button = XmCreateCascadeButton (parent, val->name, al, ac);
   713               xm_update_label (instance, button, val);
   714 
   715               XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
   716                              (XtPointer)instance);
   717               XtManageChild (button);
   718             }
   719 
   720           if (widget_list)
   721             XtFree ((char*) widget_list);
   722         }
   723     }
   724   else if (!contents)
   725     {
   726       ac = 0;
   727       XtSetArg (al [ac], XmNsubMenuId, NULL); ac++;
   728       XtSetValues (widget, al, ac);
   729       XtDestroyWidget (menu);
   730     }
   731   else if (deep_p && contents->change != NO_CHANGE)
   732     xm_update_menu (instance, menu, val, 1);
   733 }
   734 
   735 static void
   736 xm_update_menu (widget_instance* instance,
   737                 Widget widget,
   738                 widget_value* val,
   739                 Boolean deep_p)
   740 {
   741   Widget* children;
   742   unsigned int num_children;
   743   int num_children_to_keep = 0;
   744   int i;
   745   widget_value* cur;
   746 
   747   children = XtCompositeChildren (widget, &num_children);
   748 
   749   /* Widget is a RowColumn widget whose contents have to be updated
   750    * to reflect the list of items in val->contents */
   751 
   752   /* See how many buttons we can keep, and how many we
   753      must completely replace.  */
   754   if (val->contents == 0)
   755     num_children_to_keep = 0;
   756   else if (val->contents->change == STRUCTURAL_CHANGE)
   757     {
   758       if (children)
   759         {
   760           for (i = 0, cur = val->contents;
   761                (i < num_children
   762                 && cur); /* how else to ditch unwanted children ?? - mgd */
   763                i++, cur = cur->next)
   764             {
   765               if (cur->this_one_change == STRUCTURAL_CHANGE)
   766                 break;
   767             }
   768 
   769           num_children_to_keep = i;
   770         }
   771     }
   772   else
   773     num_children_to_keep = num_children;
   774 
   775   /* Update all the buttons of the RowColumn, in order,
   776      except for those we are going to replace entirely.  */
   777   if (children)
   778     {
   779       for (i = 0, cur = val->contents; i < num_children_to_keep; i++)
   780         {
   781           if (!cur)
   782             {
   783               num_children_to_keep = i;
   784               break;
   785             }
   786           if (children [i]->core.being_destroyed
   787               || strcmp (XtName (children [i]), cur->name))
   788             continue;
   789           update_one_menu_entry (instance, children [i], cur, deep_p);
   790           cur = cur->next;
   791         }
   792     }
   793 
   794   /* Now replace from scratch all the buttons after the last
   795      place that the top-level structure changed.  */
   796   if (val->contents && val->contents->change == STRUCTURAL_CHANGE)
   797     {
   798       destroy_all_children (widget, num_children_to_keep);
   799       make_menu_in_widget (instance, widget, val->contents,
   800                            num_children_to_keep);
   801     }
   802 
   803   XtFree ((char *) children);
   804 }
   805 
   806 
   807 /* update text widgets */
   808 
   809 static void
   810 xm_update_text (widget_instance* instance,
   811                 Widget widget,
   812                 widget_value* val)
   813 {
   814   XmTextSetString (widget, val->value ? val->value : "");
   815   XtRemoveAllCallbacks (widget, XmNactivateCallback);
   816   XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
   817   XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
   818   XtAddCallback (widget, XmNvalueChangedCallback,
   819                  xm_internal_update_other_instances, instance);
   820 }
   821 
   822 static void
   823 xm_update_text_field (widget_instance* instance,
   824                       Widget widget,
   825                       widget_value* val)
   826 {
   827   XmTextFieldSetString (widget, val->value ? val->value : "");
   828   XtRemoveAllCallbacks (widget, XmNactivateCallback);
   829   XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
   830   XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
   831   XtAddCallback (widget, XmNvalueChangedCallback,
   832                  xm_internal_update_other_instances, instance);
   833 }
   834 
   835 
   836 /* update a motif widget */
   837 
   838 void
   839 xm_update_one_widget (widget_instance* instance,
   840                       Widget widget,
   841                       widget_value* val,
   842                       Boolean deep_p)
   843 {
   844   WidgetClass class;
   845 
   846   /* Mark as not edited */
   847   val->edited = False;
   848 
   849   /* Common to all widget types */
   850   XtSetSensitive (widget, val->enabled);
   851   XtVaSetValues (widget, XmNuserData, val, NULL);
   852 
   853   /* Common to all label like widgets */
   854   if (XtIsSubclass (widget, xmLabelWidgetClass))
   855     xm_update_label (instance, widget, val);
   856 
   857   class = XtClass (widget);
   858   /* Class specific things */
   859   if (class == xmPushButtonWidgetClass ||
   860       class == xmArrowButtonWidgetClass)
   861     {
   862       xm_update_pushbutton (instance, widget, val);
   863     }
   864   else if (class == xmCascadeButtonWidgetClass)
   865     {
   866       xm_update_cascadebutton (instance, widget, val);
   867     }
   868   else if (class == xmToggleButtonWidgetClass
   869            || class == xmToggleButtonGadgetClass)
   870     {
   871       xm_update_toggle (instance, widget, val);
   872     }
   873   else if (class == xmRowColumnWidgetClass)
   874     {
   875       Boolean radiobox = 0;
   876       int ac = 0;
   877       Arg al [1];
   878 
   879       XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
   880       XtGetValues (widget, al, ac);
   881 
   882       if (radiobox)
   883         xm_update_radiobox (instance, widget, val);
   884       else
   885         xm_update_menu (instance, widget, val, deep_p);
   886     }
   887   else if (class == xmTextWidgetClass)
   888     {
   889       xm_update_text (instance, widget, val);
   890     }
   891   else if (class == xmTextFieldWidgetClass)
   892     {
   893       xm_update_text_field (instance, widget, val);
   894     }
   895   else if (class == xmListWidgetClass)
   896     {
   897       xm_update_list (instance, widget, val);
   898     }
   899 }
   900 
   901 /* getting the value back */
   902 void
   903 xm_update_one_value (widget_instance* instance,
   904                      Widget widget,
   905                      widget_value* val)
   906 {
   907   WidgetClass class = XtClass (widget);
   908   widget_value *old_wv;
   909 
   910   /* copy the call_data slot into the "return" widget_value */
   911   for (old_wv = instance->info->val->contents; old_wv; old_wv = old_wv->next)
   912     if (!strcmp (val->name, old_wv->name))
   913       {
   914         val->call_data = old_wv->call_data;
   915         break;
   916       }
   917 
   918   if (class == xmToggleButtonWidgetClass || class == xmToggleButtonGadgetClass)
   919     {
   920       XtVaGetValues (widget, XmNset, &val->selected, NULL);
   921       val->edited = True;
   922     }
   923   else if (class == xmTextWidgetClass)
   924     {
   925       xfree (val->value);
   926       val->value = XmTextGetString (widget);
   927       val->edited = True;
   928     }
   929   else if (class == xmTextFieldWidgetClass)
   930     {
   931       xfree (val->value);
   932       val->value = XmTextFieldGetString (widget);
   933       val->edited = True;
   934     }
   935   else if (class == xmRowColumnWidgetClass)
   936     {
   937       Boolean radiobox = 0;
   938       int ac = 0;
   939       Arg al [1];
   940 
   941       XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
   942       XtGetValues (widget, al, ac);
   943 
   944       if (radiobox)
   945         {
   946           CompositeWidget radio = (CompositeWidget)widget;
   947           int i;
   948           for (i = 0; i < radio->composite.num_children; i++)
   949             {
   950               int set = False;
   951               Widget toggle = radio->composite.children [i];
   952 
   953               XtVaGetValues (toggle, XmNset, &set, NULL);
   954               if (set)
   955                 dupstring (&val->value, XtName (toggle));
   956             }
   957           val->edited = True;
   958         }
   959     }
   960   else if (class == xmListWidgetClass)
   961     {
   962       int pos_cnt;
   963       int* pos_list;
   964       if (XmListGetSelectedPos (widget, &pos_list, &pos_cnt))
   965         {
   966           int i;
   967           widget_value* cur;
   968           for (cur = val->contents, i = 0; cur; cur = cur->next)
   969             if (cur->value)
   970               {
   971                 int j;
   972                 cur->selected = False;
   973                 i += 1;
   974                 for (j = 0; j < pos_cnt; j++)
   975                   if (pos_list [j] == i)
   976                     {
   977                       cur->selected = True;
   978                       val->value = xstrdup (cur->name);
   979                     }
   980               }
   981           val->edited = 1;
   982           XtFree ((char *) pos_list);
   983         }
   984     }
   985 }
   986 
   987 
   988 /* This function is for activating a button from a program.  It's wrong because
   989    we pass a NULL argument in the call_data which is not Motif compatible.
   990    This is used from the XmNdefaultAction callback of the List widgets to
   991    have a double-click put down a dialog box like the button would do.
   992    I could not find a way to do that with accelerators.
   993  */
   994 static void
   995 activate_button (Widget widget,
   996                  XtPointer closure,
   997                  XtPointer call_data)
   998 {
   999   Widget button = (Widget)closure;
  1000   XtCallCallbacks (button, XmNactivateCallback, NULL);
  1001 }
  1002 
  1003 /* creation functions */
  1004 
  1005 /* Called for key press in dialogs.  Used to pop down dialog on ESC.  */
  1006 static void
  1007 dialog_key_cb (Widget widget,
  1008                XtPointer closure,
  1009                XEvent *event,
  1010                Boolean *continue_to_dispatch)
  1011 {
  1012   KeySym sym = 0;
  1013   Modifiers modif_ret;
  1014 
  1015   XtTranslateKeycode (event->xkey.display, event->xkey.keycode, 0,
  1016                       &modif_ret, &sym);
  1017 
  1018   if (sym == osfXK_Cancel)
  1019     {
  1020       Widget w = *((Widget *) closure);
  1021 
  1022       while (w && ! XtIsShell (w))
  1023         w = XtParent (w);
  1024 
  1025       if (XtIsShell (w)) XtPopdown (w);
  1026     }
  1027 
  1028   *continue_to_dispatch = TRUE;
  1029 }
  1030 
  1031 /* dialogs */
  1032 static Widget
  1033 make_dialog (char* name,
  1034              Widget parent,
  1035              Boolean pop_up_p,
  1036              char* shell_title,
  1037              char* icon_name,
  1038              Boolean text_input_slot,
  1039              Boolean radio_box,
  1040              Boolean list,
  1041              int left_buttons,
  1042              int right_buttons)
  1043 {
  1044   Widget result;
  1045   Widget form;
  1046   Widget row;
  1047   Widget icon;
  1048   Widget icon_separator;
  1049   Widget message_label;
  1050   Widget value = 0;
  1051   Widget separator;
  1052   Widget button = 0;
  1053   Widget children [16];         /* for the final XtManageChildren */
  1054   int    n_children;
  1055   Arg   al[64];                 /* Arg List */
  1056   int   ac;                     /* Arg Count */
  1057   int   i;
  1058 
  1059   if (pop_up_p)
  1060     {
  1061       ac = 0;
  1062       XtSetArg(al[ac], XmNtitle, shell_title); ac++;
  1063       XtSetArg(al[ac], XtNallowShellResize, True); ac++;
  1064       XtSetArg(al[ac], XmNdeleteResponse, XmUNMAP); ac++;
  1065       result = XmCreateDialogShell (parent, "dialog", al, ac);
  1066       ac = 0;
  1067       XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
  1068 /*      XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
  1069       XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
  1070       form = XmCreateForm (result, shell_title, al, ac);
  1071     }
  1072   else
  1073     {
  1074       ac = 0;
  1075       XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
  1076       XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
  1077       form = XmCreateForm (parent, shell_title, al, ac);
  1078       result = form;
  1079     }
  1080 
  1081   n_children = left_buttons + right_buttons + 1;
  1082   ac = 0;
  1083   XtSetArg(al[ac], XmNpacking, n_children == 3?
  1084            XmPACK_COLUMN: XmPACK_TIGHT); ac++;
  1085   XtSetArg(al[ac], XmNorientation, n_children == 3?
  1086            XmVERTICAL: XmHORIZONTAL); ac++;
  1087   XtSetArg(al[ac], XmNnumColumns, left_buttons + right_buttons + 1); ac++;
  1088   XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
  1089   XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
  1090   XtSetArg(al[ac], XmNspacing, 13); ac++;
  1091   XtSetArg(al[ac], XmNadjustLast, False); ac++;
  1092   XtSetArg(al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
  1093   XtSetArg(al[ac], XmNisAligned, True); ac++;
  1094   XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
  1095   XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
  1096   XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
  1097   XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
  1098   XtSetArg(al[ac], XmNleftOffset, 13); ac++;
  1099   XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  1100   XtSetArg(al[ac], XmNrightOffset, 13); ac++;
  1101   row = XmCreateRowColumn (form, "row", al, ac);
  1102 
  1103   n_children = 0;
  1104   for (i = 0; i < left_buttons; i++)
  1105     {
  1106       char button_name [16];
  1107       sprintf (button_name, "button%d", i + 1);
  1108       ac = 0;
  1109       if (i == 0)
  1110         {
  1111           XtSetArg(al[ac], XmNhighlightThickness, 1); ac++;
  1112           XtSetArg(al[ac], XmNshowAsDefault, TRUE); ac++;
  1113         }
  1114       XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
  1115       XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
  1116       children [n_children] = XmCreatePushButton (row, button_name, al, ac);
  1117       XtAddEventHandler (children [n_children],
  1118                          KeyPressMask, False, dialog_key_cb, result);
  1119 
  1120       if (i == 0)
  1121         {
  1122           button = children [n_children];
  1123           ac = 0;
  1124           XtSetArg(al[ac], XmNdefaultButton, button); ac++;
  1125           XtSetValues (row, al, ac);
  1126         }
  1127 
  1128       n_children++;
  1129     }
  1130 
  1131   /* invisible separator button */
  1132   ac = 0;
  1133   XtSetArg (al[ac], XmNmappedWhenManaged, FALSE); ac++;
  1134   children [n_children] = XmCreateLabel (row, "separator_button", al, ac);
  1135   n_children++;
  1136 
  1137   for (i = 0; i < right_buttons; i++)
  1138     {
  1139       char button_name [16];
  1140       sprintf (button_name, "button%d", left_buttons + i + 1);
  1141       ac = 0;
  1142       XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
  1143       XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
  1144       children [n_children] = XmCreatePushButton (row, button_name, al, ac);
  1145       XtAddEventHandler (children [n_children],
  1146                          KeyPressMask, False, dialog_key_cb, result);
  1147 
  1148       if (! button) button = children [n_children];
  1149       n_children++;
  1150     }
  1151 
  1152   XtManageChildren (children, n_children);
  1153 
  1154   ac = 0;
  1155   XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
  1156   XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
  1157   XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
  1158   XtSetArg(al[ac], XmNbottomWidget, row); ac++;
  1159   XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
  1160   XtSetArg(al[ac], XmNleftOffset, 0); ac++;
  1161   XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  1162   XtSetArg(al[ac], XmNrightOffset, 0); ac++;
  1163   separator = XmCreateSeparator (form, "", al, ac);
  1164 
  1165   ac = 0;
  1166   XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
  1167   XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
  1168   XtSetArg(al[ac], XmNtopOffset, 13); ac++;
  1169   XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
  1170   XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
  1171   XtSetArg(al[ac], XmNleftOffset, 13); ac++;
  1172   XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
  1173   icon = XmCreateLabel (form, icon_name, al, ac);
  1174 
  1175   ac = 0;
  1176   XtSetArg(al[ac], XmNmappedWhenManaged, FALSE); ac++;
  1177   XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
  1178   XtSetArg(al[ac], XmNtopOffset, 6); ac++;
  1179   XtSetArg(al[ac], XmNtopWidget, icon); ac++;
  1180   XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
  1181   XtSetArg(al[ac], XmNbottomOffset, 6); ac++;
  1182   XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
  1183   XtSetArg(al[ac], XmNleftAttachment, XmATTACH_NONE); ac++;
  1184   XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
  1185   icon_separator = XmCreateLabel (form, "", al, ac);
  1186 
  1187   if (text_input_slot)
  1188     {
  1189       ac = 0;
  1190       XtSetArg(al[ac], XmNcolumns, 50); ac++;
  1191       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
  1192       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
  1193       XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
  1194       XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
  1195       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  1196       XtSetArg(al[ac], XmNleftOffset, 13); ac++;
  1197       XtSetArg(al[ac], XmNleftWidget, icon); ac++;
  1198       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  1199       XtSetArg(al[ac], XmNrightOffset, 13); ac++;
  1200       value = XmCreateTextField (form, "value", al, ac);
  1201     }
  1202   else if (radio_box)
  1203     {
  1204       Widget radio_butt;
  1205       ac = 0;
  1206       XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
  1207       XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
  1208       XtSetArg(al[ac], XmNspacing, 13); ac++;
  1209       XtSetArg(al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
  1210       XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++;
  1211       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
  1212       XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
  1213       XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
  1214       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  1215       XtSetArg(al[ac], XmNleftOffset, 13); ac++;
  1216       XtSetArg(al[ac], XmNleftWidget, icon); ac++;
  1217       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  1218       XtSetArg(al[ac], XmNrightOffset, 13); ac++;
  1219       value = XmCreateRadioBox (form, "radiobutton1", al, ac);
  1220       ac = 0;
  1221       i = 0;
  1222       radio_butt = XmCreateToggleButtonGadget (value, "radio1", al, ac);
  1223       children [i++] = radio_butt;
  1224       radio_butt = XmCreateToggleButtonGadget (value, "radio2", al, ac);
  1225       children [i++] = radio_butt;
  1226       radio_butt = XmCreateToggleButtonGadget (value, "radio3", al, ac);
  1227       children [i++] = radio_butt;
  1228       XtManageChildren (children, i);
  1229     }
  1230   else if (list)
  1231     {
  1232       ac = 0;
  1233       XtSetArg(al[ac], XmNvisibleItemCount, 5); ac++;
  1234       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
  1235       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
  1236       XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
  1237       XtSetArg(al[ac], XmNbottomWidget, separator); ac++;
  1238       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  1239       XtSetArg(al[ac], XmNleftOffset, 13); ac++;
  1240       XtSetArg(al[ac], XmNleftWidget, icon); ac++;
  1241       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  1242       XtSetArg(al[ac], XmNrightOffset, 13); ac++;
  1243       value = XmCreateScrolledList (form, "list", al, ac);
  1244 
  1245       /* this is the easiest way I found to have the dble click in the
  1246          list activate the default button */
  1247       XtAddCallback (value, XmNdefaultActionCallback, activate_button, button);
  1248     }
  1249 
  1250   ac = 0;
  1251   XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
  1252   XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
  1253   XtSetArg(al[ac], XmNtopOffset, 13); ac++;
  1254   XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
  1255   XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
  1256   XtSetArg(al[ac], XmNbottomWidget,
  1257            text_input_slot || radio_box || list ? value : separator); ac++;
  1258   XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
  1259   XtSetArg(al[ac], XmNleftOffset, 13); ac++;
  1260   XtSetArg(al[ac], XmNleftWidget, icon); ac++;
  1261   XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  1262   XtSetArg(al[ac], XmNrightOffset, 13); ac++;
  1263   message_label = XmCreateLabel (form, "message", al, ac);
  1264 
  1265   if (list)
  1266     XtManageChild (value);
  1267 
  1268   i = 0;
  1269   children [i] = row; i++;
  1270   children [i] = separator; i++;
  1271   if (text_input_slot || radio_box)
  1272     {
  1273       children [i] = value; i++;
  1274     }
  1275   children [i] = message_label; i++;
  1276   children [i] = icon; i++;
  1277   children [i] = icon_separator; i++;
  1278   XtManageChildren (children, i);
  1279 
  1280   if (text_input_slot || list)
  1281     {
  1282       XtInstallAccelerators (value, button);
  1283       XtSetKeyboardFocus (result, value);
  1284     }
  1285   else
  1286     {
  1287       XtInstallAccelerators (form, button);
  1288       XtSetKeyboardFocus (result, button);
  1289     }
  1290 
  1291   return result;
  1292 }
  1293 
  1294 static destroyed_instance*
  1295 find_matching_instance (widget_instance* instance)
  1296 {
  1297   destroyed_instance*   cur;
  1298   destroyed_instance*   prev;
  1299   char* type = instance->info->type;
  1300   char* name = instance->info->name;
  1301 
  1302   for (prev = NULL, cur = all_destroyed_instances;
  1303        cur;
  1304        prev = cur, cur = cur->next)
  1305     {
  1306       if (!strcmp (cur->name, name)
  1307           && !strcmp (cur->type, type)
  1308           && cur->parent == instance->parent
  1309           && cur->pop_up_p == instance->pop_up_p)
  1310         {
  1311           if (prev)
  1312             prev->next = cur->next;
  1313           else
  1314             all_destroyed_instances = cur->next;
  1315           return cur;
  1316         }
  1317       /* do some cleanup */
  1318       else if (!cur->widget)
  1319         {
  1320           if (prev)
  1321             prev->next = cur->next;
  1322           else
  1323             all_destroyed_instances = cur->next;
  1324           free_destroyed_instance (cur);
  1325           cur = prev ? prev : all_destroyed_instances;
  1326         }
  1327     }
  1328   return NULL;
  1329 }
  1330 
  1331 static void
  1332 mark_dead_instance_destroyed (Widget widget,
  1333                               XtPointer closure,
  1334                               XtPointer call_data)
  1335 {
  1336   destroyed_instance* instance = (destroyed_instance*)closure;
  1337   instance->widget = NULL;
  1338 }
  1339 
  1340 static void
  1341 recenter_widget (Widget widget)
  1342 {
  1343   Widget parent = XtParent (widget);
  1344   Screen* screen = XtScreen (widget);
  1345   Dimension screen_width = WidthOfScreen (screen);
  1346   Dimension screen_height = HeightOfScreen (screen);
  1347   Dimension parent_width = 0;
  1348   Dimension parent_height = 0;
  1349   Dimension child_width = 0;
  1350   Dimension child_height = 0;
  1351   Position x;
  1352   Position y;
  1353 
  1354   XtVaGetValues (widget, XtNwidth, &child_width, XtNheight, &child_height, NULL);
  1355   XtVaGetValues (parent, XtNwidth, &parent_width, XtNheight, &parent_height,
  1356                  NULL);
  1357 
  1358   x = (((Position)parent_width) - ((Position)child_width)) / 2;
  1359   y = (((Position)parent_height) - ((Position)child_height)) / 2;
  1360 
  1361   XtTranslateCoords (parent, x, y, &x, &y);
  1362 
  1363   if (x + child_width > screen_width)
  1364     x = screen_width - child_width;
  1365   if (x < 0)
  1366     x = 0;
  1367 
  1368   if (y + child_height > screen_height)
  1369     y = screen_height - child_height;
  1370   if (y < 0)
  1371     y = 0;
  1372 
  1373   XtVaSetValues (widget, XtNx, x, XtNy, y, NULL);
  1374 }
  1375 
  1376 static Widget
  1377 recycle_instance (destroyed_instance* instance)
  1378 {
  1379   Widget widget = instance->widget;
  1380 
  1381   /* widget is NULL if the parent was destroyed. */
  1382   if (widget)
  1383     {
  1384       Widget focus;
  1385       Widget separator;
  1386 
  1387       /* Remove the destroy callback as the instance is not in the list
  1388          anymore */
  1389       XtRemoveCallback (instance->parent, XtNdestroyCallback,
  1390                         mark_dead_instance_destroyed,
  1391                         (XtPointer)instance);
  1392 
  1393       /* Give the focus to the initial item */
  1394       focus = XtNameToWidget (widget, "*value");
  1395       if (!focus)
  1396         focus = XtNameToWidget (widget, "*button1");
  1397       if (focus)
  1398         XtSetKeyboardFocus (widget, focus);
  1399 
  1400       /* shrink the separator label back to their original size */
  1401       separator = XtNameToWidget (widget, "*separator_button");
  1402       if (separator)
  1403         XtVaSetValues (separator, XtNwidth, 5, XtNheight, 5, NULL);
  1404 
  1405       /* Center the dialog in its parent */
  1406       recenter_widget (widget);
  1407     }
  1408   free_destroyed_instance (instance);
  1409   return widget;
  1410 }
  1411 
  1412 Widget
  1413 xm_create_dialog (widget_instance* instance)
  1414 {
  1415   char*         name = instance->info->type;
  1416   Widget        parent = instance->parent;
  1417   Widget        widget;
  1418   Boolean       pop_up_p = instance->pop_up_p;
  1419   char*         shell_name = 0;
  1420   char*         icon_name = 0;
  1421   Boolean       text_input_slot = False;
  1422   Boolean       radio_box = False;
  1423   Boolean       list = False;
  1424   int           total_buttons;
  1425   int           left_buttons = 0;
  1426   int           right_buttons = 1;
  1427   destroyed_instance*   dead_one;
  1428 
  1429   /* try to find a widget to recycle */
  1430   dead_one = find_matching_instance (instance);
  1431   if (dead_one)
  1432     {
  1433       Widget recycled_widget = recycle_instance (dead_one);
  1434       if (recycled_widget)
  1435         return recycled_widget;
  1436     }
  1437 
  1438   switch (name [0]){
  1439   case 'E': case 'e':
  1440     icon_name = "dbox-error";
  1441     shell_name = "Error";
  1442     break;
  1443 
  1444   case 'I': case 'i':
  1445     icon_name = "dbox-info";
  1446     shell_name = "Information";
  1447     break;
  1448 
  1449   case 'L': case 'l':
  1450     list = True;
  1451     icon_name = "dbox-question";
  1452     shell_name = "Prompt";
  1453     break;
  1454 
  1455   case 'P': case 'p':
  1456     text_input_slot = True;
  1457     icon_name = "dbox-question";
  1458     shell_name = "Prompt";
  1459     break;
  1460 
  1461   case 'Q': case 'q':
  1462     icon_name = "dbox-question";
  1463     shell_name = "Question";
  1464     break;
  1465   }
  1466 
  1467   total_buttons = name [1] - '0';
  1468 
  1469   if (name [3] == 'T' || name [3] == 't')
  1470     {
  1471       text_input_slot = False;
  1472       radio_box = True;
  1473     }
  1474   else if (name [3])
  1475     right_buttons = name [4] - '0';
  1476 
  1477   left_buttons = total_buttons - right_buttons;
  1478 
  1479   widget = make_dialog (name, parent, pop_up_p,
  1480                         shell_name, icon_name, text_input_slot, radio_box,
  1481                         list, left_buttons, right_buttons);
  1482 
  1483   XtAddCallback (widget, XmNpopdownCallback, xm_nosel_callback,
  1484                  (XtPointer) instance);
  1485 
  1486   return widget;
  1487 }
  1488 
  1489 /* Create a menu bar.  We turn off the f10 key
  1490    because we have not yet managed to make it work right in Motif.  */
  1491 
  1492 static Widget
  1493 make_menubar (widget_instance* instance)
  1494 {
  1495   Arg al[3];
  1496   int ac;
  1497 
  1498   ac = 0;
  1499   XtSetArg(al[ac], XmNmenuAccelerator, 0); ++ac;
  1500   return XmCreateMenuBar (instance->parent, instance->info->name, al, ac);
  1501 }
  1502 
  1503 static void
  1504 remove_grabs (Widget shell,
  1505               XtPointer closure,
  1506               XtPointer call_data)
  1507 {
  1508   Widget menu = (Widget) closure;
  1509   XmRemoveFromPostFromList (menu, XtParent (XtParent (menu)));
  1510 }
  1511 
  1512 static Widget
  1513 make_popup_menu (widget_instance* instance)
  1514 {
  1515   Widget parent = instance->parent;
  1516   Window parent_window = parent->core.window;
  1517   Widget result;
  1518 
  1519   /* sets the parent window to 0 to fool Motif into not generating a grab */
  1520   parent->core.window = 0;
  1521   result = XmCreatePopupMenu (parent, instance->info->name, NULL, 0);
  1522   XtAddCallback (XtParent (result), XmNpopdownCallback, remove_grabs,
  1523                  (XtPointer)result);
  1524   parent->core.window = parent_window;
  1525   return result;
  1526 }
  1527 
  1528 static Widget
  1529 make_main (widget_instance* instance)
  1530 {
  1531   Widget parent = instance->parent;
  1532   Widget result;
  1533   Arg al[2];
  1534   int ac;
  1535 
  1536   ac = 0;
  1537   XtSetArg (al[ac], XtNborderWidth, 0); ac++;
  1538   XtSetArg (al[ac], XmNspacing, 0); ac++;
  1539   result = XmCreateMainWindow (parent, instance->info->name, al, ac);
  1540   return result;
  1541 }
  1542 
  1543 /* Table of functions to create widgets */
  1544 
  1545 #ifdef ENERGIZE
  1546 
  1547 /* interface with the XDesigner generated functions */
  1548 typedef Widget (*widget_maker) (Widget);
  1549 extern Widget create_project_p_sheet (Widget parent);
  1550 extern Widget create_debugger_p_sheet (Widget parent);
  1551 extern Widget create_breaklist_p_sheet (Widget parent);
  1552 extern Widget create_le_browser_p_sheet (Widget parent);
  1553 extern Widget create_class_browser_p_sheet (Widget parent);
  1554 extern Widget create_call_browser_p_sheet (Widget parent);
  1555 extern Widget create_build_dialog (Widget parent);
  1556 extern Widget create_editmode_dialog (Widget parent);
  1557 extern Widget create_search_dialog (Widget parent);
  1558 extern Widget create_project_display_dialog (Widget parent);
  1559 
  1560 static Widget
  1561 make_one (widget_instance* instance, widget_maker fn)
  1562 {
  1563   Widget result;
  1564   Arg   al [64];
  1565   int   ac = 0;
  1566 
  1567   if (instance->pop_up_p)
  1568     {
  1569       XtSetArg (al [ac], XmNallowShellResize, TRUE); ac++;
  1570       result = XmCreateDialogShell (instance->parent, "dialog", NULL, 0);
  1571       XtAddCallback (result, XmNpopdownCallback, &xm_nosel_callback,
  1572                      (XtPointer) instance);
  1573       (*fn) (result);
  1574     }
  1575   else
  1576     {
  1577       result = (*fn) (instance->parent);
  1578       XtRealizeWidget (result);
  1579     }
  1580   return result;
  1581 }
  1582 
  1583 static Widget
  1584 make_project_p_sheet (widget_instance* instance)
  1585 {
  1586   return make_one (instance, create_project_p_sheet);
  1587 }
  1588 
  1589 static Widget
  1590 make_debugger_p_sheet (widget_instance* instance)
  1591 {
  1592   return make_one (instance, create_debugger_p_sheet);
  1593 }
  1594 
  1595 static Widget
  1596 make_breaklist_p_sheet (widget_instance* instance)
  1597 {
  1598   return make_one (instance, create_breaklist_p_sheet);
  1599 }
  1600 
  1601 static Widget
  1602 make_le_browser_p_sheet (widget_instance* instance)
  1603 {
  1604   return make_one (instance, create_le_browser_p_sheet);
  1605 }
  1606 
  1607 static Widget
  1608 make_class_browser_p_sheet (widget_instance* instance)
  1609 {
  1610   return make_one (instance, create_class_browser_p_sheet);
  1611 }
  1612 
  1613 static Widget
  1614 make_call_browser_p_sheet (widget_instance* instance)
  1615 {
  1616   return make_one (instance, create_call_browser_p_sheet);
  1617 }
  1618 
  1619 static Widget
  1620 make_build_dialog (widget_instance* instance)
  1621 {
  1622   return make_one (instance, create_build_dialog);
  1623 }
  1624 
  1625 static Widget
  1626 make_editmode_dialog (widget_instance* instance)
  1627 {
  1628   return make_one (instance, create_editmode_dialog);
  1629 }
  1630 
  1631 static Widget
  1632 make_search_dialog (widget_instance* instance)
  1633 {
  1634   return make_one (instance, create_search_dialog);
  1635 }
  1636 
  1637 static Widget
  1638 make_project_display_dialog (widget_instance* instance)
  1639 {
  1640   return make_one (instance, create_project_display_dialog);
  1641 }
  1642 
  1643 #endif /* ENERGIZE */
  1644 
  1645 widget_creation_entry
  1646 xm_creation_table [] =
  1647 {
  1648   {"menubar",                   make_menubar},
  1649   {"popup",                     make_popup_menu},
  1650   {"main",                      make_main},
  1651 #ifdef ENERGIZE
  1652   {"project_p_sheet",           make_project_p_sheet},
  1653   {"debugger_p_sheet",          make_debugger_p_sheet},
  1654   {"breaklist_psheet",          make_breaklist_p_sheet},
  1655   {"leb_psheet",                make_le_browser_p_sheet},
  1656   {"class_browser_psheet",      make_class_browser_p_sheet},
  1657   {"ctree_browser_psheet",      make_call_browser_p_sheet},
  1658   {"build",                     make_build_dialog},
  1659   {"editmode",                  make_editmode_dialog},
  1660   {"search",                    make_search_dialog},
  1661   {"project_display",           make_project_display_dialog},
  1662 #endif /* ENERGIZE */
  1663   {NULL, NULL}
  1664 };
  1665 
  1666 /* Destruction of instances */
  1667 void
  1668 xm_destroy_instance ( widget_instance* instance)
  1669 {
  1670   Widget widget = instance->widget;
  1671   /* recycle the dialog boxes */
  1672   /* Disable the recycling until we can find a way to have the dialog box
  1673      get reasonable layout after we modify its contents. */
  1674   if (0
  1675       && XtClass (widget) == xmDialogShellWidgetClass)
  1676     {
  1677       destroyed_instance* dead_instance =
  1678         make_destroyed_instance (instance->info->name,
  1679                                  instance->info->type,
  1680                                  instance->widget,
  1681                                  instance->parent,
  1682                                  instance->pop_up_p);
  1683       dead_instance->next = all_destroyed_instances;
  1684       all_destroyed_instances = dead_instance;
  1685       XtUnmanageChild (first_child (instance->widget));
  1686       XFlush (XtDisplay (instance->widget));
  1687       XtAddCallback (instance->parent, XtNdestroyCallback,
  1688                      mark_dead_instance_destroyed, (XtPointer)dead_instance);
  1689     }
  1690   else
  1691     {
  1692       /* This might not be necessary now that the nosel is attached to
  1693          popdown instead of destroy, but it can't hurt. */
  1694       XtRemoveCallback (instance->widget, XtNdestroyCallback,
  1695                         xm_nosel_callback, (XtPointer)instance);
  1696       XtDestroyWidget (instance->widget);
  1697     }
  1698 }
  1699 
  1700 /* popup utility */
  1701 void
  1702 xm_popup_menu (Widget widget, XEvent *event)
  1703 {
  1704   XButtonPressedEvent dummy;
  1705 
  1706   if (event == 0)
  1707     {
  1708       dummy.type = ButtonPress;
  1709       dummy.serial = 0;
  1710       dummy.send_event = 0;
  1711       dummy.display = XtDisplay (widget);
  1712       dummy.window = XtWindow (XtParent (widget));
  1713       dummy.time = 0;
  1714       dummy.button = 0;
  1715       XQueryPointer (dummy.display, dummy.window, &dummy.root,
  1716                      &dummy.subwindow, &dummy.x_root, &dummy.y_root,
  1717                      &dummy.x, &dummy.y, &dummy.state);
  1718       event = (XEvent *) &dummy;
  1719     }
  1720 
  1721   if (event->type == ButtonPress || event->type == ButtonRelease)
  1722     {
  1723       /* Setting the menuPost resource only required by Motif 1.1 and
  1724          LessTif 0.84 and earlier.  With later versions of LessTif,
  1725          setting menuPost is unnecessary and may cause problems, so
  1726          don't do it.  */
  1727 #if XmVersion < 1002 || (defined LESSTIF_VERSION && LESSTIF_VERSION < 84)
  1728         {
  1729           /* This is so totally ridiculous: there's NO WAY to tell Motif
  1730              that *any* button can select a menu item.  Only one button
  1731              can have that honor.  */
  1732 
  1733           char *trans = 0;
  1734           if      (event->xbutton.state & Button5Mask) trans = "<Btn5Down>";
  1735           else if (event->xbutton.state & Button4Mask) trans = "<Btn4Down>";
  1736           else if (event->xbutton.state & Button3Mask) trans = "<Btn3Down>";
  1737           else if (event->xbutton.state & Button2Mask) trans = "<Btn2Down>";
  1738           else if (event->xbutton.state & Button1Mask) trans = "<Btn1Down>";
  1739           if (trans) XtVaSetValues (widget, XmNmenuPost, trans, NULL);
  1740         }
  1741 #endif
  1742 
  1743       XmMenuPosition (widget, (XButtonPressedEvent *) event);
  1744     }
  1745 
  1746   XtManageChild (widget);
  1747 }
  1748 
  1749 static void
  1750 set_min_dialog_size (Widget w)
  1751 {
  1752   short width;
  1753   short height;
  1754   XtVaGetValues (w, XmNwidth, &width, XmNheight, &height, NULL);
  1755   XtVaSetValues (w, XmNminWidth, width, XmNminHeight, height, NULL);
  1756 }
  1757 
  1758 void
  1759 xm_pop_instance (widget_instance* instance, Boolean up)
  1760 {
  1761   Widget widget = instance->widget;
  1762 
  1763   if (XtClass (widget) == xmDialogShellWidgetClass)
  1764     {
  1765       Widget widget_to_manage = first_child (widget);
  1766       if (up)
  1767         {
  1768           XtManageChild (widget_to_manage);
  1769           set_min_dialog_size (widget);
  1770           XtSetKeyboardFocus (instance->parent, widget);
  1771         }
  1772       else
  1773         XtUnmanageChild (widget_to_manage);
  1774     }
  1775   else
  1776     {
  1777       if (up)
  1778         XtManageChild (widget);
  1779       else
  1780         XtUnmanageChild (widget);
  1781     }
  1782 }
  1783 
  1784 
  1785 /* motif callback */
  1786 
  1787 static void
  1788 do_call (Widget widget,
  1789          XtPointer closure,
  1790          enum do_call_type type)
  1791 {
  1792   Arg al [256];
  1793   int ac;
  1794   XtPointer user_data;
  1795   widget_instance* instance = (widget_instance*)closure;
  1796   widget_value *wv;
  1797   Widget instance_widget;
  1798   LWLIB_ID id;
  1799 
  1800   if (!instance)
  1801     return;
  1802   if (widget->core.being_destroyed)
  1803     return;
  1804 
  1805   instance_widget = instance->widget;
  1806   if (!instance_widget)
  1807     return;
  1808 
  1809   id = instance->info->id;
  1810   ac = 0;
  1811   user_data = NULL;
  1812   XtSetArg (al [ac], XmNuserData, &user_data); ac++;
  1813   XtGetValues (widget, al, ac);
  1814   wv = user_data;
  1815 
  1816   switch (type)
  1817     {
  1818     case pre_activate:
  1819       if (instance->info->pre_activate_cb)
  1820         instance->info->pre_activate_cb (widget, id, wv ? wv->call_data : NULL);
  1821       break;
  1822 
  1823     case selection:
  1824       if (instance->info->selection_cb)
  1825         instance->info->selection_cb (widget, id, wv ? wv->call_data : NULL);
  1826       break;
  1827 
  1828     case no_selection:
  1829       if (instance->info->selection_cb)
  1830         instance->info->selection_cb (widget, id, (XtPointer) -1);
  1831       break;
  1832 
  1833     case post_activate:
  1834       if (instance->info->post_activate_cb)
  1835         instance->info->post_activate_cb (widget, id, wv ? wv->call_data : NULL);
  1836       break;
  1837 
  1838     default:
  1839       emacs_abort ();
  1840     }
  1841 }
  1842 
  1843 /* Like lw_internal_update_other_instances except that it does not do
  1844    anything if its shell parent is not managed.  This is to protect
  1845    lw_internal_update_other_instances to dereference freed memory
  1846    if the widget was ``destroyed'' by caching it in the all_destroyed_instances
  1847    list */
  1848 static void
  1849 xm_internal_update_other_instances (Widget widget,
  1850                                     XtPointer closure,
  1851                                     XtPointer call_data)
  1852 {
  1853   Widget parent;
  1854   for (parent = widget; parent; parent = XtParent (parent))
  1855     if (XtIsShell (parent))
  1856       break;
  1857     else if (!XtIsManaged (parent))
  1858       return;
  1859    lw_internal_update_other_instances (widget, closure, call_data);
  1860 }
  1861 
  1862 static void
  1863 xm_generic_callback (Widget widget,
  1864                      XtPointer closure,
  1865                      XtPointer call_data)
  1866 {
  1867   lw_internal_update_other_instances (widget, closure, call_data);
  1868   do_call (widget, closure, selection);
  1869 }
  1870 
  1871 static void
  1872 xm_nosel_callback (Widget widget,
  1873                    XtPointer closure,
  1874                    XtPointer call_data)
  1875 {
  1876   /* This callback is only called when a dialog box is dismissed with
  1877      the wm's destroy button (WM_DELETE_WINDOW.)  We want the dialog
  1878      box to be destroyed in that case, not just unmapped, so that it
  1879      releases its keyboard grabs.  But there are problems with running
  1880      our callbacks while the widget is in the process of being
  1881      destroyed, so we set XmNdeleteResponse to XmUNMAP instead of
  1882      XmDESTROY and then destroy it ourself after having run the
  1883      callback.  */
  1884   do_call (widget, closure, no_selection);
  1885   XtDestroyWidget (widget);
  1886 }
  1887 
  1888 static void
  1889 xm_pull_down_callback (Widget widget,
  1890                        XtPointer closure,
  1891                        XtPointer call_data)
  1892 {
  1893   Widget parent = XtParent (widget);
  1894 
  1895   if (XmIsRowColumn (parent))
  1896     {
  1897       unsigned char type = 0xff;
  1898       XtVaGetValues (parent, XmNrowColumnType, &type, NULL);
  1899       if (type == XmMENU_BAR)
  1900         do_call (widget, closure, pre_activate);
  1901     }
  1902 }
  1903 
  1904 
  1905 /* XmNpopdownCallback for MenuShell widgets.  WIDGET is the MenuShell,
  1906    CLOSURE is a pointer to the widget_instance of the shell,
  1907 
  1908    Note that this callback is called for each cascade button in a
  1909    menu, whether or not its submenu is visible.  */
  1910 
  1911 static void
  1912 xm_pop_down_callback (Widget widget,
  1913                       XtPointer closure,
  1914                       XtPointer call_data)
  1915 {
  1916   widget_instance *instance = (widget_instance *) closure;
  1917 
  1918   if ((!instance->pop_up_p && XtParent (widget) == instance->widget)
  1919       || XtParent (widget) == instance->parent)
  1920     do_call (widget, closure, post_activate);
  1921 }
  1922 
  1923 static void
  1924 xm_pop_up_callback (Widget widget,
  1925                     XtPointer closure,
  1926                     XtPointer call_data)
  1927 {
  1928   widget_instance *instance = (widget_instance *) closure;
  1929 
  1930   if ((!instance->pop_up_p && XtParent (widget) == instance->widget)
  1931       || XtParent (widget) == instance->parent)
  1932     do_call (widget, closure, pre_activate);
  1933 }
  1934 
  1935 
  1936 /* set the keyboard focus */
  1937 void
  1938 xm_set_keyboard_focus (Widget parent, Widget w)
  1939 {
  1940   XmProcessTraversal (w, 0);
  1941   XtSetKeyboardFocus (parent, w);
  1942 }
  1943 
  1944 /* Motif hack to set the main window areas. */
  1945 void
  1946 xm_set_main_areas (Widget parent,
  1947                    Widget menubar,
  1948                    Widget work_area)
  1949 {
  1950   XmMainWindowSetAreas (parent,
  1951                         menubar,        /* menubar (maybe 0) */
  1952                         0,              /* command area (psheets) */
  1953                         0,              /* horizontal scroll */
  1954                         0,              /* vertical scroll */
  1955                         work_area);     /* work area */
  1956 }
  1957 
  1958 /* Motif hack to control resizing on the menubar. */
  1959 void
  1960 xm_manage_resizing (Widget w, Boolean flag)
  1961 {
  1962   XtVaSetValues (w, XtNallowShellResize, flag, NULL);
  1963 }

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