]> code.delx.au - gnu-emacs/blobdiff - lwlib/lwlib-Xm.c
Make `initials' completion work for /hh -> /home/horn again (bug#5524).
[gnu-emacs] / lwlib / lwlib-Xm.c
index 16c8a947a4a9a81fa4088c6ef1147245362679c2..ed203e26bf42f198e6fca84c2bf8096570c091e0 100644 (file)
@@ -1,22 +1,25 @@
 /* The lwlib interface to Motif widgets.
 /* The lwlib interface to Motif widgets.
+   Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
+                 2004, 2005, 2006, 2007, 2008, 2009, 2010
+                 Free Software Foundation, Inc.
    Copyright (C) 1992 Lucid, Inc.
 
 This file is part of the Lucid Widget Library.
 
    Copyright (C) 1992 Lucid, Inc.
 
 This file is part of the Lucid Widget Library.
 
-The Lucid Widget Library is free software; you can redistribute it and/or 
+The Lucid Widget Library is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 1, or (at your option)
 any later version.
 
 The Lucid Widget Library is distributed in the hope that it will be useful,
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 1, or (at your option)
 any later version.
 
 The Lucid Widget Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of 
+but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -24,6 +27,7 @@ Boston, MA 02111-1307, USA.  */
 
 #include <unistd.h>
 #include <stdio.h>
 
 #include <unistd.h>
 #include <stdio.h>
+#include <setjmp.h>
 
 #include <X11/StringDefs.h>
 #include <X11/IntrinsicP.h>
 
 #include <X11/StringDefs.h>
 #include <X11/IntrinsicP.h>
@@ -31,6 +35,8 @@ Boston, MA 02111-1307, USA.  */
 #include <X11/CoreP.h>
 #include <X11/CompositeP.h>
 
 #include <X11/CoreP.h>
 #include <X11/CompositeP.h>
 
+#include "../src/lisp.h"
+
 #include "lwlib-Xm.h"
 #include "lwlib-utils.h"
 
 #include "lwlib-Xm.h"
 #include "lwlib-utils.h"
 
@@ -59,6 +65,7 @@ Boston, MA 02111-1307, USA.  */
 #include <Xm/DialogS.h>
 #include <Xm/Form.h>
 
 #include <Xm/DialogS.h>
 #include <Xm/Form.h>
 
+#undef P_
 #if defined __STDC__ || defined PROTOTYPES
 #define P_(X) X
 #else
 #if defined __STDC__ || defined PROTOTYPES
 #define P_(X) X
 #else
@@ -69,7 +76,7 @@ enum do_call_type { pre_activate, selection, no_selection, post_activate };
 
 
 \f/* Structures to keep destroyed instances */
 
 
 \f/* Structures to keep destroyed instances */
-typedef struct _destroyed_instance 
+typedef struct _destroyed_instance
 {
   char*                name;
   char*                type;
 {
   char*                name;
   char*                type;
@@ -125,7 +132,6 @@ static void xm_generic_callback P_ ((Widget, XtPointer, XtPointer));
 static void xm_nosel_callback P_ ((Widget, XtPointer, XtPointer));
 static void xm_pull_down_callback P_ ((Widget, XtPointer, XtPointer));
 static void xm_pop_down_callback P_ ((Widget, XtPointer, XtPointer));
 static void xm_nosel_callback P_ ((Widget, XtPointer, XtPointer));
 static void xm_pull_down_callback P_ ((Widget, XtPointer, XtPointer));
 static void xm_pop_down_callback P_ ((Widget, XtPointer, XtPointer));
-static void xm_unmap_callback P_ ((Widget, XtPointer, XtPointer));
 void xm_set_keyboard_focus P_ ((Widget, Widget));
 void xm_set_main_areas P_ ((Widget, Widget, Widget));
 static void xm_internal_update_other_instances P_ ((Widget, XtPointer,
 void xm_set_keyboard_focus P_ ((Widget, Widget));
 void xm_set_main_areas P_ ((Widget, Widget, Widget));
 static void xm_internal_update_other_instances P_ ((Widget, XtPointer,
@@ -140,6 +146,32 @@ void xm_manage_resizing P_ ((Widget, Boolean));
 #endif
 
 
 #endif
 
 
+#if 0
+
+/* Print the complete X resource name of widget WIDGET to stderr.
+   This is sometimes handy to have available.  */
+
+void
+x_print_complete_resource_name (widget)
+     Widget widget;
+{
+  int i;
+  String names[100];
+
+  for (i = 0; i < 100 && widget != NULL; ++i)
+    {
+      names[i] = XtName (widget);
+      widget = XtParent (widget);
+    }
+
+  for (--i; i >= 1; --i)
+    fprintf (stderr, "%s.", names[i]);
+  fprintf (stderr, "%s\n", names[0]);
+}
+
+#endif /* 0 */
+
+
 static destroyed_instance *all_destroyed_instances = NULL;
 
 static destroyed_instance*
 static destroyed_instance *all_destroyed_instances = NULL;
 
 static destroyed_instance*
@@ -160,7 +192,7 @@ make_destroyed_instance (name, type, widget, parent, pop_up_p)
   instance->next = NULL;
   return instance;
 }
   instance->next = NULL;
   return instance;
 }
-                        
+
 static void
 free_destroyed_instance (instance)
      destroyed_instance* instance;
 static void
 free_destroyed_instance (instance)
      destroyed_instance* instance;
@@ -182,7 +214,7 @@ Boolean
 lw_motif_widget_p (widget)
      Widget widget;
 {
 lw_motif_widget_p (widget)
      Widget widget;
 {
-  return 
+  return
     XtClass (widget) == xmDialogShellWidgetClass
       || XmIsPrimitive (widget) || XmIsManager (widget) || XmIsGadget (widget);
 }
     XtClass (widget) == xmDialogShellWidgetClass
       || XmIsPrimitive (widget) || XmIsManager (widget) || XmIsGadget (widget);
 }
@@ -194,7 +226,7 @@ resource_motif_string (widget, name)
 {
   XtResource resource;
   XmString result = 0;
 {
   XtResource resource;
   XmString result = 0;
-  
+
   resource.resource_name = name;
   resource.resource_class = XmCXmString;
   resource.resource_type = XmRXmString;
   resource.resource_name = name;
   resource.resource_class = XmCXmString;
   resource.resource_type = XmRXmString;
@@ -226,7 +258,7 @@ destroy_all_children (widget, first_child_to_destroy)
       XtUnmanageChildren (children + first_child_to_destroy,
                          number - first_child_to_destroy);
 
       XtUnmanageChildren (children + first_child_to_destroy,
                          number - first_child_to_destroy);
 
-      /* Unmanage all children and destroy them.  They will only be 
+      /* Unmanage all children and destroy them.  They will only be
         really destroyed when we get out of DispatchEvent.  */
       for (i = first_child_to_destroy; i < number; i++)
        {
         really destroyed when we get out of DispatchEvent.  */
       for (i = first_child_to_destroy; i < number; i++)
        {
@@ -237,10 +269,13 @@ destroy_all_children (widget, first_child_to_destroy)
             XtCompositeChildren.  So get it out of the cascade button
             and free it.  If this child is not a cascade button,
             then submenu should remain unchanged.  */
             XtCompositeChildren.  So get it out of the cascade button
             and free it.  If this child is not a cascade button,
             then submenu should remain unchanged.  */
-         XtSetArg (al[0], XmNsubMenuId, &submenu); 
+         XtSetArg (al[0], XmNsubMenuId, &submenu);
          XtGetValues (children[i], al, 1);
          if (submenu)
          XtGetValues (children[i], al, 1);
          if (submenu)
-           XtDestroyWidget (submenu);
+            {
+              destroy_all_children (submenu, 0);
+              XtDestroyWidget (submenu);
+            }
          XtDestroyWidget (children[i]);
        }
 
          XtDestroyWidget (children[i]);
        }
 
@@ -266,7 +301,7 @@ xm_arm_callback (w, client_data, call_data)
   widget_instance *instance;
 
   /* Get the id of the menu bar or popup menu this widget is in.  */
   widget_instance *instance;
 
   /* Get the id of the menu bar or popup menu this widget is in.  */
-  while (w != None)
+  while (w != NULL)
     {
       if (XmIsRowColumn (w))
        {
     {
       if (XmIsRowColumn (w))
        {
@@ -280,7 +315,7 @@ xm_arm_callback (w, client_data, call_data)
       w = XtParent (w);
     }
 
       w = XtParent (w);
     }
 
-  if (w != None)
+  if (w != NULL)
     {
       instance = lw_get_widget_instance (w);
       if (instance && instance->info->highlight_cb)
     {
       instance = lw_get_widget_instance (w);
       if (instance && instance->info->highlight_cb)
@@ -298,7 +333,7 @@ xm_arm_callback (w, client_data, call_data)
    the value to update.
 
    Menus:
    the value to update.
 
    Menus:
-   
+
    Emacs fills VAL->name with the text to display in the menu, and
    sets VAL->value to null.  Function make_menu_in_widget creates
    widgets with VAL->name as resource name.  This works because the
    Emacs fills VAL->name with the text to display in the menu, and
    sets VAL->value to null.  Function make_menu_in_widget creates
    widgets with VAL->name as resource name.  This works because the
@@ -337,16 +372,16 @@ xm_update_label (instance, widget, val)
       else
        {
          built_string =
       else
        {
          built_string =
-           XmStringCreateLtoR (val->value, XmSTRING_DEFAULT_CHARSET);
+           XmStringCreateLocalized (val->value);
          XtSetArg (al [ac], XmNlabelString, built_string); ac++;
        }
          XtSetArg (al [ac], XmNlabelString, built_string); ac++;
        }
-      
+
       XtSetArg (al [ac], XmNlabelType, XmSTRING); ac++;
     }
       XtSetArg (al [ac], XmNlabelType, XmSTRING); ac++;
     }
-  
+
   if (val->key)
     {
   if (val->key)
     {
-      key_string = XmStringCreateLtoR (val->key, XmSTRING_DEFAULT_CHARSET);
+      key_string = XmStringCreateLocalized (val->key);
       XtSetArg (al [ac], XmNacceleratorText, key_string); ac++;
     }
 
       XtSetArg (al [ac], XmNacceleratorText, key_string); ac++;
     }
 
@@ -375,7 +410,7 @@ xm_update_list (instance, widget, val)
   for (cur = val->contents, i = 0; cur; cur = cur->next)
     if (cur->value)
       {
   for (cur = val->contents, i = 0; cur; cur = cur->next)
     if (cur->value)
       {
-       XmString xmstr = XmStringCreate (cur->value, XmSTRING_DEFAULT_CHARSET);
+       XmString xmstr = XmStringCreateLocalized (cur->value);
        i += 1;
        XmListAddItem (widget, xmstr, 0);
        if (cur->selected)
        i += 1;
        XmListAddItem (widget, xmstr, 0);
        if (cur->selected)
@@ -491,10 +526,15 @@ make_menu_in_widget (instance, widget, val, keep_first_children)
   Widget* old_children;
   unsigned int old_num_children;
 
   Widget* old_children;
   unsigned int old_num_children;
 
+  /* Disable drag and drop for labels in menu bar.  */
+  static char overrideTrans[] = "<Btn2Down>: Noop()";
+  XtTranslations override = XtParseTranslationTable (overrideTrans);
+
   old_children = XtCompositeChildren (widget, &old_num_children);
 
   /* Allocate the children array */
   old_children = XtCompositeChildren (widget, &old_num_children);
 
   /* Allocate the children array */
-  for (num_children = 0, cur = val; cur; num_children++, cur = cur->next);
+  for (num_children = 0, cur = val; cur; num_children++, cur = cur->next)
+    ;
   children = (Widget*)XtMalloc (num_children * sizeof (Widget));
 
   /* WIDGET should be a RowColumn.  */
   children = (Widget*)XtMalloc (num_children * sizeof (Widget));
 
   /* WIDGET should be a RowColumn.  */
@@ -509,18 +549,11 @@ make_menu_in_widget (instance, widget, val, keep_first_children)
     abort ();
   menubar_p = type == XmMENU_BAR;
 
     abort ();
   menubar_p = type == XmMENU_BAR;
 
-#if 0 /* This can't be used in LessTif as of 2000-01-24 because it's
-        impossible to decide from this plus the cascading callback if a
-        popup is still posted or not.  When selecting cascade button A,
-        then B, then clicking on the frame, the sequence of callbacks is
-        `cascading A', cascading B', `popdown for all cascade buttons in
-        the menu bar.  */
   /* Add a callback to popups and pulldowns that is called when
      it is made invisible again.  */
   if (!menubar_p)
     XtAddCallback (XtParent (widget), XmNpopdownCallback,
                   xm_pop_down_callback, (XtPointer)instance);
   /* Add a callback to popups and pulldowns that is called when
      it is made invisible again.  */
   if (!menubar_p)
     XtAddCallback (XtParent (widget), XmNpopdownCallback,
                   xm_pop_down_callback, (XtPointer)instance);
-#endif
 
   /* Preserve the first KEEP_FIRST_CHILDREN old children.  */
   for (child_index = 0, cur = val; child_index < keep_first_children;
 
   /* Preserve the first KEEP_FIRST_CHILDREN old children.  */
   for (child_index = 0, cur = val; child_index < keep_first_children;
@@ -541,7 +574,7 @@ make_menu_in_widget (instance, widget, val, keep_first_children)
       XtSetArg (al[ac], XmNsensitive, cur->enabled); ac++;
       XtSetArg (al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
       XtSetArg (al[ac], XmNuserData, cur->call_data); ac++;
       XtSetArg (al[ac], XmNsensitive, cur->enabled); ac++;
       XtSetArg (al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
       XtSetArg (al[ac], XmNuserData, cur->call_data); ac++;
-      
+
       if (instance->pop_up_p && !cur->contents && !cur->call_data
          && !lw_separator_p (cur->name, &separator, 1))
        {
       if (instance->pop_up_p && !cur->contents && !cur->call_data
          && !lw_separator_p (cur->name, &separator, 1))
        {
@@ -580,9 +613,9 @@ make_menu_in_widget (instance, widget, val, keep_first_children)
              XtAddCallback (button, XmNarmCallback, xm_arm_callback, cur);
              XtAddCallback (button, XmNdisarmCallback, xm_arm_callback, cur);
            }
              XtAddCallback (button, XmNarmCallback, xm_arm_callback, cur);
              XtAddCallback (button, XmNdisarmCallback, xm_arm_callback, cur);
            }
-         
+
          xm_update_label (instance, button, cur);
          xm_update_label (instance, button, cur);
-         
+
          /* Add a callback that is called when the button is
             selected.  Toggle buttons don't support
             XmNactivateCallback, we use XmNvalueChangedCallback in
          /* Add a callback that is called when the button is
             selected.  Toggle buttons don't support
             XmNactivateCallback, we use XmNvalueChangedCallback in
@@ -597,12 +630,6 @@ make_menu_in_widget (instance, widget, val, keep_first_children)
        {
          menu = XmCreatePulldownMenu (widget, cur->name, NULL, 0);
 
        {
          menu = XmCreatePulldownMenu (widget, cur->name, NULL, 0);
 
-         /* XmNpopdownCallback is working strangely under LessTif.
-            Using XmNunmapCallback is the only way to go there.  */
-         if (menubar_p)
-           XtAddCallback (menu, XmNunmapCallback, xm_unmap_callback,
-                          (XtPointer) instance);
-         
          make_menu_in_widget (instance, menu, cur->contents, 0);
           XtSetArg (al[ac], XmNsubMenuId, menu); ac++;
          button = XmCreateCascadeButton (widget, cur->name, al, ac);
          make_menu_in_widget (instance, menu, cur->contents, 0);
           XtSetArg (al[ac], XmNsubMenuId, menu); ac++;
          button = XmCreateCascadeButton (widget, cur->name, al, ac);
@@ -611,6 +638,8 @@ make_menu_in_widget (instance, widget, val, keep_first_children)
 
          XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
                         (XtPointer)instance);
 
          XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
                         (XtPointer)instance);
+          XtOverrideTranslations (button, override);
+
        }
 
       children[child_index] = button;
        }
 
       children[child_index] = button;
@@ -624,12 +653,6 @@ make_menu_in_widget (instance, widget, val, keep_first_children)
   if (button)
     XtVaSetValues (widget, XmNmenuHelpWidget, button, NULL);
 
   if (button)
     XtVaSetValues (widget, XmNmenuHelpWidget, button, NULL);
 
-  /* LessTif apparently doesn't recompute centered text when more
-     widgets are added.  So, do it after all widgets have been
-     created.  */
-  if (title)
-    XtVaSetValues (title, XmNalignment, XmALIGNMENT_CENTER, NULL);
-
   if (num_children)
     XtManageChildren (children, num_children);
 
   if (num_children)
     XtManageChildren (children, num_children);
 
@@ -671,7 +694,7 @@ update_one_menu_entry (instance, widget, val, deep_p)
   menu = NULL;
   XtSetArg (al [ac], XmNsubMenuId, &menu); ac++;
   XtGetValues (widget, al, ac);
   menu = NULL;
   XtSetArg (al [ac], XmNsubMenuId, &menu); ac++;
   XtGetValues (widget, al, ac);
-  
+
   contents = val->contents;
 
   if (!menu)
   contents = val->contents;
 
   if (!menu)
@@ -702,8 +725,8 @@ update_one_menu_entry (instance, widget, val, deep_p)
          else
            {
              Widget button;
          else
            {
              Widget button;
-             
-             /* The current menuitem is a XmPushButtonGadget, it 
+
+             /* The current menuitem is a XmPushButtonGadget, it
                 needs to be replaced by a CascadeButtonGadget */
              XtDestroyWidget (widget_list[i]);
              menu = XmCreatePulldownMenu (parent, val->name, NULL, 0);
                 needs to be replaced by a CascadeButtonGadget */
              XtDestroyWidget (widget_list[i]);
              menu = XmCreatePulldownMenu (parent, val->name, NULL, 0);
@@ -719,11 +742,14 @@ update_one_menu_entry (instance, widget, val, deep_p)
 #endif
              button = XmCreateCascadeButton (parent, val->name, al, ac);
              xm_update_label (instance, button, val);
 #endif
              button = XmCreateCascadeButton (parent, val->name, al, ac);
              xm_update_label (instance, button, val);
-             
+
              XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
                             (XtPointer)instance);
              XtManageChild (button);
            }
              XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
                             (XtPointer)instance);
              XtManageChild (button);
            }
+
+          if (widget_list)
+            XtFree ((char*) widget_list);
        }
     }
   else if (!contents)
        }
     }
   else if (!contents)
@@ -763,7 +789,7 @@ xm_update_menu (instance, widget, val, deep_p)
     {
       if (children)
        {
     {
       if (children)
        {
-         for (i = 0, cur = val->contents; 
+         for (i = 0, cur = val->contents;
                (i < num_children
                && cur); /* how else to ditch unwanted children ?? - mgd */
               i++, cur = cur->next)
                (i < num_children
                && cur); /* how else to ditch unwanted children ?? - mgd */
               i++, cur = cur->next)
@@ -803,7 +829,7 @@ xm_update_menu (instance, widget, val, deep_p)
     {
       destroy_all_children (widget, num_children_to_keep);
       make_menu_in_widget (instance, widget, val->contents,
     {
       destroy_all_children (widget, num_children_to_keep);
       make_menu_in_widget (instance, widget, val->contents,
-                          num_children_to_keep);
+                           num_children_to_keep);
     }
 
   XtFree ((char *) children);
     }
 
   XtFree ((char *) children);
@@ -851,18 +877,18 @@ xm_update_one_widget (instance, widget, val, deep_p)
      Boolean deep_p;
 {
   WidgetClass class;
      Boolean deep_p;
 {
   WidgetClass class;
-  
+
   /* Mark as not edited */
   val->edited = False;
 
   /* Common to all widget types */
   XtSetSensitive (widget, val->enabled);
   XtVaSetValues (widget, XmNuserData, val->call_data, NULL);
   /* Mark as not edited */
   val->edited = False;
 
   /* Common to all widget types */
   XtSetSensitive (widget, val->enabled);
   XtVaSetValues (widget, XmNuserData, val->call_data, NULL);
-  
+
   /* Common to all label like widgets */
   if (XtIsSubclass (widget, xmLabelWidgetClass))
     xm_update_label (instance, widget, val);
   /* Common to all label like widgets */
   if (XtIsSubclass (widget, xmLabelWidgetClass))
     xm_update_label (instance, widget, val);
-  
+
   class = XtClass (widget);
   /* Class specific things */
   if (class == xmPushButtonWidgetClass ||
   class = XtClass (widget);
   /* Class specific things */
   if (class == xmPushButtonWidgetClass ||
@@ -884,10 +910,10 @@ xm_update_one_widget (instance, widget, val, deep_p)
       Boolean radiobox = 0;
       int ac = 0;
       Arg al [1];
       Boolean radiobox = 0;
       int ac = 0;
       Arg al [1];
-      
+
       XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
       XtGetValues (widget, al, ac);
       XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
       XtGetValues (widget, al, ac);
-      
+
       if (radiobox)
        xm_update_radiobox (instance, widget, val);
       else
       if (radiobox)
        xm_update_radiobox (instance, widget, val);
       else
@@ -924,7 +950,7 @@ xm_update_one_value (instance, widget, val)
        val->call_data = old_wv->call_data;
        break;
       }
        val->call_data = old_wv->call_data;
        break;
       }
-  
+
   if (class == xmToggleButtonWidgetClass || class == xmToggleButtonGadgetClass)
     {
       XtVaGetValues (widget, XmNset, &val->selected, NULL);
   if (class == xmToggleButtonWidgetClass || class == xmToggleButtonGadgetClass)
     {
       XtVaGetValues (widget, XmNset, &val->selected, NULL);
@@ -932,15 +958,13 @@ xm_update_one_value (instance, widget, val)
     }
   else if (class == xmTextWidgetClass)
     {
     }
   else if (class == xmTextWidgetClass)
     {
-      if (val->value)
-       free (val->value);
+      free (val->value);
       val->value = XmTextGetString (widget);
       val->edited = True;
     }
   else if (class == xmTextFieldWidgetClass)
     {
       val->value = XmTextGetString (widget);
       val->edited = True;
     }
   else if (class == xmTextFieldWidgetClass)
     {
-      if (val->value)
-       free (val->value);
+      free (val->value);
       val->value = XmTextFieldGetString (widget);
       val->edited = True;
     }
       val->value = XmTextFieldGetString (widget);
       val->edited = True;
     }
@@ -949,10 +973,10 @@ xm_update_one_value (instance, widget, val)
       Boolean radiobox = 0;
       int ac = 0;
       Arg al [1];
       Boolean radiobox = 0;
       int ac = 0;
       Arg al [1];
-      
+
       XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
       XtGetValues (widget, al, ac);
       XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
       XtGetValues (widget, al, ac);
-      
+
       if (radiobox)
        {
          CompositeWidget radio = (CompositeWidget)widget;
       if (radiobox)
        {
          CompositeWidget radio = (CompositeWidget)widget;
@@ -961,12 +985,11 @@ xm_update_one_value (instance, widget, val)
            {
              int set = False;
              Widget toggle = radio->composite.children [i];
            {
              int set = False;
              Widget toggle = radio->composite.children [i];
-             
+
              XtVaGetValues (toggle, XmNset, &set, NULL);
              if (set)
                {
              XtVaGetValues (toggle, XmNset, &set, NULL);
              if (set)
                {
-                 if (val->value)
-                   free (val->value);
+                 free (val->value);
                  val->value = safe_strdup (XtName (toggle));
                }
            }
                  val->value = safe_strdup (XtName (toggle));
                }
            }
@@ -1004,7 +1027,7 @@ xm_update_one_value (instance, widget, val)
 /* This function is for activating a button from a program.  It's wrong because
    we pass a NULL argument in the call_data which is not Motif compatible.
    This is used from the XmNdefaultAction callback of the List widgets to
 /* This function is for activating a button from a program.  It's wrong because
    we pass a NULL argument in the call_data which is not Motif compatible.
    This is used from the XmNdefaultAction callback of the List widgets to
-   have a double-click put down a dialog box like the button would do. 
+   have a double-click put down a dialog box like the button would do.
    I could not find a way to do that with accelerators.
  */
 static void
    I could not find a way to do that with accelerators.
  */
 static void
@@ -1019,6 +1042,33 @@ activate_button (widget, closure, call_data)
 
 /* creation functions */
 
 
 /* creation functions */
 
+/* Called for key press in dialogs.  Used to pop down dialog on ESC.  */
+static void
+dialog_key_cb (widget, closure, event, continue_to_dispatch)
+     Widget widget;
+     XtPointer closure;
+     XEvent *event;
+     Boolean *continue_to_dispatch;
+{
+  KeySym sym = 0;
+  Modifiers modif_ret;
+  
+  XtTranslateKeycode (event->xkey.display, event->xkey.keycode, 0,
+                      &modif_ret, &sym);
+                      
+  if (sym == osfXK_Cancel)
+    {
+      Widget w = *((Widget *) closure);
+
+      while (w && ! XtIsShell (w))
+        w = XtParent (w);
+
+      if (XtIsShell (w)) XtPopdown (w);
+    }
+
+  *continue_to_dispatch = TRUE;
+}
+
 /* dialogs */
 static Widget
 make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
 /* dialogs */
 static Widget
 make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
@@ -1048,7 +1098,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
   Arg  al[64];                 /* Arg List */
   int  ac;                     /* Arg Count */
   int  i;
   Arg  al[64];                 /* Arg List */
   int  ac;                     /* Arg Count */
   int  i;
-  
+
   if (pop_up_p)
     {
       ac = 0;
   if (pop_up_p)
     {
       ac = 0;
@@ -1073,9 +1123,9 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
 
   n_children = left_buttons + right_buttons + 1;
   ac = 0;
 
   n_children = left_buttons + right_buttons + 1;
   ac = 0;
-  XtSetArg(al[ac], XmNpacking, n_children == 3? 
+  XtSetArg(al[ac], XmNpacking, n_children == 3?
           XmPACK_COLUMN: XmPACK_TIGHT); ac++;
           XmPACK_COLUMN: XmPACK_TIGHT); ac++;
-  XtSetArg(al[ac], XmNorientation, n_children == 3? 
+  XtSetArg(al[ac], XmNorientation, n_children == 3?
           XmVERTICAL: XmHORIZONTAL); ac++;
   XtSetArg(al[ac], XmNnumColumns, left_buttons + right_buttons + 1); ac++;
   XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
           XmVERTICAL: XmHORIZONTAL); ac++;
   XtSetArg(al[ac], XmNnumColumns, left_buttons + right_buttons + 1); ac++;
   XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
@@ -1092,7 +1142,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
   XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
   XtSetArg(al[ac], XmNrightOffset, 13); ac++;
   row = XmCreateRowColumn (form, "row", al, ac);
   XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
   XtSetArg(al[ac], XmNrightOffset, 13); ac++;
   row = XmCreateRowColumn (form, "row", al, ac);
-  
+
   n_children = 0;
   for (i = 0; i < left_buttons; i++)
     {
   n_children = 0;
   for (i = 0; i < left_buttons; i++)
     {
@@ -1107,6 +1157,8 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
       XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
       XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
       children [n_children] = XmCreatePushButton (row, button_name, al, ac);
       XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
       XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
       children [n_children] = XmCreatePushButton (row, button_name, al, ac);
+      XtAddEventHandler (children [n_children],
+                         KeyPressMask, False, dialog_key_cb, result);
 
       if (i == 0)
        {
 
       if (i == 0)
        {
@@ -1124,7 +1176,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
   XtSetArg (al[ac], XmNmappedWhenManaged, FALSE); ac++;
   children [n_children] = XmCreateLabel (row, "separator_button", al, ac);
   n_children++;
   XtSetArg (al[ac], XmNmappedWhenManaged, FALSE); ac++;
   children [n_children] = XmCreateLabel (row, "separator_button", al, ac);
   n_children++;
-  
+
   for (i = 0; i < right_buttons; i++)
     {
       char button_name [16];
   for (i = 0; i < right_buttons; i++)
     {
       char button_name [16];
@@ -1133,12 +1185,15 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
       XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
       XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
       children [n_children] = XmCreatePushButton (row, button_name, al, ac);
       XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
       XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
       children [n_children] = XmCreatePushButton (row, button_name, al, ac);
+      XtAddEventHandler (children [n_children],
+                         KeyPressMask, False, dialog_key_cb, result);
+
       if (! button) button = children [n_children];
       n_children++;
     }
       if (! button) button = children [n_children];
       n_children++;
     }
-  
+
   XtManageChildren (children, n_children);
   XtManageChildren (children, n_children);
-  
+
   ac = 0;
   XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
   XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
   ac = 0;
   XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
   XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
@@ -1234,7 +1289,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
         list activate the default button */
       XtAddCallback (value, XmNdefaultActionCallback, activate_button, button);
     }
         list activate the default button */
       XtAddCallback (value, XmNdefaultActionCallback, activate_button, button);
     }
-  
+
   ac = 0;
   XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
   XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
   ac = 0;
   XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
   XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
@@ -1249,7 +1304,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
   XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
   XtSetArg(al[ac], XmNrightOffset, 13); ac++;
   message = XmCreateLabel (form, "message", al, ac);
   XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
   XtSetArg(al[ac], XmNrightOffset, 13); ac++;
   message = XmCreateLabel (form, "message", al, ac);
-  
+
   if (list)
     XtManageChild (value);
 
   if (list)
     XtManageChild (value);
 
@@ -1264,7 +1319,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
   children [i] = icon; i++;
   children [i] = icon_separator; i++;
   XtManageChildren (children, i);
   children [i] = icon; i++;
   children [i] = icon_separator; i++;
   XtManageChildren (children, i);
-  
+
   if (text_input_slot || list)
     {
       XtInstallAccelerators (value, button);
   if (text_input_slot || list)
     {
       XtInstallAccelerators (value, button);
@@ -1275,7 +1330,7 @@ make_dialog (name, parent, pop_up_p, shell_title, icon_name, text_input_slot,
       XtInstallAccelerators (form, button);
       XtSetKeyboardFocus (result, button);
     }
       XtInstallAccelerators (form, button);
       XtSetKeyboardFocus (result, button);
     }
-  
+
   return result;
 }
 
   return result;
 }
 
@@ -1348,7 +1403,7 @@ recenter_widget (widget)
 
   x = (((Position)parent_width) - ((Position)child_width)) / 2;
   y = (((Position)parent_height) - ((Position)child_height)) / 2;
 
   x = (((Position)parent_width) - ((Position)child_width)) / 2;
   y = (((Position)parent_height) - ((Position)child_height)) / 2;
-  
+
   XtTranslateCoords (parent, x, y, &x, &y);
 
   if (x + child_width > screen_width)
   XtTranslateCoords (parent, x, y, &x, &y);
 
   if (x + child_width > screen_width)
@@ -1388,7 +1443,7 @@ recycle_instance (instance)
        focus = XtNameToWidget (widget, "*button1");
       if (focus)
        XtSetKeyboardFocus (widget, focus);
        focus = XtNameToWidget (widget, "*button1");
       if (focus)
        XtSetKeyboardFocus (widget, focus);
-      
+
       /* shrink the separator label back to their original size */
       separator = XtNameToWidget (widget, "*separator_button");
       if (separator)
       /* shrink the separator label back to their original size */
       separator = XtNameToWidget (widget, "*separator_button");
       if (separator)
@@ -1456,7 +1511,7 @@ xm_create_dialog (instance)
     shell_name = "Question";
     break;
   }
     shell_name = "Question";
     break;
   }
-  
+
   total_buttons = name [1] - '0';
 
   if (name [3] == 'T' || name [3] == 't')
   total_buttons = name [1] - '0';
 
   if (name [3] == 'T' || name [3] == 't')
@@ -1466,15 +1521,16 @@ xm_create_dialog (instance)
     }
   else if (name [3])
     right_buttons = name [4] - '0';
     }
   else if (name [3])
     right_buttons = name [4] - '0';
-  
+
   left_buttons = total_buttons - right_buttons;
   left_buttons = total_buttons - right_buttons;
-  
+
   widget = make_dialog (name, parent, pop_up_p,
                        shell_name, icon_name, text_input_slot, radio_box,
                        list, left_buttons, right_buttons);
 
   XtAddCallback (widget, XmNpopdownCallback, xm_nosel_callback,
                 (XtPointer) instance);
   widget = make_dialog (name, parent, pop_up_p,
                        shell_name, icon_name, text_input_slot, radio_box,
                        list, left_buttons, right_buttons);
 
   XtAddCallback (widget, XmNpopdownCallback, xm_nosel_callback,
                 (XtPointer) instance);
+
   return widget;
 }
 
   return widget;
 }
 
@@ -1490,15 +1546,6 @@ make_menubar (instance)
 
   ac = 0;
   XtSetArg(al[ac], XmNmenuAccelerator, 0); ++ac;
 
   ac = 0;
   XtSetArg(al[ac], XmNmenuAccelerator, 0); ++ac;
-
-#if 0
-  /* As of 2000-01-17, the LessTif menu bar resizes to height 0 when
-     all its children are removed, causing an annoying flickering
-     behavior.  Prevent that by not allowing resizing.  */
-  XtSetArg(al[ac], XmNresizeHeight, False); ++ac;
-  XtSetArg(al[ac], XmNresizeWidth, False); ++ac;
-#endif
-  
   return XmCreateMenuBar (instance->parent, instance->info->name, al, ac);
 }
 
   return XmCreateMenuBar (instance->parent, instance->info->name, al, ac);
 }
 
@@ -1648,7 +1695,7 @@ make_project_display_dialog (widget_instance* instance)
 #endif /* ENERGIZE */
 
 widget_creation_entry
 #endif /* ENERGIZE */
 
 widget_creation_entry
-xm_creation_table [] = 
+xm_creation_table [] =
 {
   {"menubar",                  make_menubar},
   {"popup",                    make_popup_menu},
 {
   {"menubar",                  make_menubar},
   {"popup",                    make_popup_menu},
@@ -1728,19 +1775,29 @@ xm_popup_menu (widget, event)
 
   if (event->type == ButtonPress || event->type == ButtonRelease)
     {
 
   if (event->type == ButtonPress || event->type == ButtonRelease)
     {
-      /* This is so totally ridiculous: there's NO WAY to tell Motif
-        that *any* button can select a menu item.  Only one button
-        can have that honor.
-       */
-      char *trans = 0;
-      if      (event->xbutton.state & Button5Mask) trans = "<Btn5Down>";
-      else if (event->xbutton.state & Button4Mask) trans = "<Btn4Down>";
-      else if (event->xbutton.state & Button3Mask) trans = "<Btn3Down>";
-      else if (event->xbutton.state & Button2Mask) trans = "<Btn2Down>";
-      else if (event->xbutton.state & Button1Mask) trans = "<Btn1Down>";
-      if (trans) XtVaSetValues (widget, XmNmenuPost, trans, NULL);
+      /* Setting the menuPost resource only required by Motif 1.1 and
+        LessTif 0.84 and earlier.  With later versions of LessTif,
+        setting menuPost is unnecessary and may cause problems, so
+        don't do it.  */
+#if XmVersion < 1002 || (defined LESSTIF_VERSION && LESSTIF_VERSION < 84)
+       {
+         /* This is so totally ridiculous: there's NO WAY to tell Motif
+            that *any* button can select a menu item.  Only one button
+            can have that honor.  */
+
+         char *trans = 0;
+         if      (event->xbutton.state & Button5Mask) trans = "<Btn5Down>";
+         else if (event->xbutton.state & Button4Mask) trans = "<Btn4Down>";
+         else if (event->xbutton.state & Button3Mask) trans = "<Btn3Down>";
+         else if (event->xbutton.state & Button2Mask) trans = "<Btn2Down>";
+         else if (event->xbutton.state & Button1Mask) trans = "<Btn1Down>";
+         if (trans) XtVaSetValues (widget, XmNmenuPost, trans, NULL);
+       }
+#endif
+
       XmMenuPosition (widget, (XButtonPressedEvent *) event);
     }
       XmMenuPosition (widget, (XButtonPressedEvent *) event);
     }
+
   XtManageChild (widget);
 }
 
   XtManageChild (widget);
 }
 
@@ -1778,12 +1835,12 @@ xm_pop_instance (instance, up)
       if (up)
        XtManageChild (widget);
       else
       if (up)
        XtManageChild (widget);
       else
-       XtUnmanageChild (widget);       
+       XtUnmanageChild (widget);
     }
 }
 
 \f
     }
 }
 
 \f
-/* motif callback */ 
+/* motif callback */
 
 static void
 do_call (widget, closure, type)
 
 static void
 do_call (widget, closure, type)
@@ -1812,31 +1869,36 @@ do_call (widget, closure, type)
   user_data = NULL;
   XtSetArg (al [ac], XmNuserData, &user_data); ac++;
   XtGetValues (widget, al, ac);
   user_data = NULL;
   XtSetArg (al [ac], XmNuserData, &user_data); ac++;
   XtGetValues (widget, al, ac);
+
   switch (type)
     {
     case pre_activate:
       if (instance->info->pre_activate_cb)
        instance->info->pre_activate_cb (widget, id, user_data);
       break;
   switch (type)
     {
     case pre_activate:
       if (instance->info->pre_activate_cb)
        instance->info->pre_activate_cb (widget, id, user_data);
       break;
+
     case selection:
       if (instance->info->selection_cb)
        instance->info->selection_cb (widget, id, user_data);
       break;
     case selection:
       if (instance->info->selection_cb)
        instance->info->selection_cb (widget, id, user_data);
       break;
+
     case no_selection:
       if (instance->info->selection_cb)
        instance->info->selection_cb (widget, id, (XtPointer) -1);
       break;
     case no_selection:
       if (instance->info->selection_cb)
        instance->info->selection_cb (widget, id, (XtPointer) -1);
       break;
+
     case post_activate:
       if (instance->info->post_activate_cb)
        instance->info->post_activate_cb (widget, id, user_data);
       break;
     case post_activate:
       if (instance->info->post_activate_cb)
        instance->info->post_activate_cb (widget, id, user_data);
       break;
+
     default:
       abort ();
     }
 }
 
 /* Like lw_internal_update_other_instances except that it does not do
     default:
       abort ();
     }
 }
 
 /* Like lw_internal_update_other_instances except that it does not do
-   anything if its shell parent is not managed.  This is to protect 
+   anything if its shell parent is not managed.  This is to protect
    lw_internal_update_other_instances to dereference freed memory
    if the widget was ``destroyed'' by caching it in the all_destroyed_instances
    list */
    lw_internal_update_other_instances to dereference freed memory
    if the widget was ``destroyed'' by caching it in the all_destroyed_instances
    list */
@@ -1871,14 +1933,14 @@ xm_nosel_callback (widget, closure, call_data)
      XtPointer closure;
      XtPointer call_data;
 {
      XtPointer closure;
      XtPointer call_data;
 {
-  /* This callback is only called when a dialog box is dismissed with the wm's
-     destroy button (WM_DELETE_WINDOW.)  We want the dialog box to be destroyed
-     in that case, not just unmapped, so that it releases its keyboard grabs.
-     But there are problems with running our callbacks while the widget is in
-     the process of being destroyed, so we set XmNdeleteResponse to XmUNMAP
-     instead of XmDESTROY and then destroy it ourself after having run the
-     callback.
-   */
+  /* This callback is only called when a dialog box is dismissed with
+     the wm's destroy button (WM_DELETE_WINDOW.)  We want the dialog
+     box to be destroyed in that case, not just unmapped, so that it
+     releases its keyboard grabs.  But there are problems with running
+     our callbacks while the widget is in the process of being
+     destroyed, so we set XmNdeleteResponse to XmUNMAP instead of
+     XmDESTROY and then destroy it ourself after having run the
+     callback.  */
   do_call (widget, closure, no_selection);
   XtDestroyWidget (widget);
 }
   do_call (widget, closure, no_selection);
   XtDestroyWidget (widget);
 }
@@ -1902,11 +1964,10 @@ xm_pull_down_callback (widget, closure, call_data)
 
 
 /* XmNpopdownCallback for MenuShell widgets.  WIDGET is the MenuShell,
 
 
 /* XmNpopdownCallback for MenuShell widgets.  WIDGET is the MenuShell,
-   CLOSURE is a pointer to the widget_instance of the shell, CALL_DATA
-   is always null under LessTif.
+   CLOSURE is a pointer to the widget_instance of the shell,
 
 
-   2000-01-23: This callback is called for each cascade button in 
-   menu, whether or not its submenu is visible.  */
+   Note that this callback is called for each cascade button in a
+   menu, whether or not its submenu is visible.  */
 
 static void
 xm_pop_down_callback (widget, closure, call_data)
 
 static void
 xm_pop_down_callback (widget, closure, call_data)
@@ -1916,19 +1977,8 @@ xm_pop_down_callback (widget, closure, call_data)
 {
   widget_instance *instance = (widget_instance *) closure;
 
 {
   widget_instance *instance = (widget_instance *) closure;
 
-  if ((!instance->pop_up_p && (XtParent (widget) == instance->widget))
-      || (XtParent (widget) == instance->parent))
-    do_call (widget, closure, post_activate);
-}
-
-static void
-xm_unmap_callback (widget, closure, call_data)
-     Widget widget;
-     XtPointer closure;
-     XtPointer call_data;
-{
-  widget_instance *instance = (widget_instance *) closure;
-  if (!instance->pop_up_p)
+  if ((!instance->pop_up_p && XtParent (widget) == instance->widget)
+      || XtParent (widget) == instance->parent)
     do_call (widget, closure, post_activate);
 }
 
     do_call (widget, closure, post_activate);
 }
 
@@ -1966,3 +2016,6 @@ xm_manage_resizing (w, flag)
 {
   XtVaSetValues (w, XtNallowShellResize, flag, NULL);
 }
 {
   XtVaSetValues (w, XtNallowShellResize, flag, NULL);
 }
+
+/* arch-tag: 73976f64-73b2-4600-aa13-d9ede20ee965
+   (do not change this comment) */