]> code.delx.au - gnu-emacs/blobdiff - lwlib/xlwmenu.c
New file, from the Calc distribution (with Stephen Gildea's email address
[gnu-emacs] / lwlib / xlwmenu.c
index cadd02584af65d9976fe146a9d6c4162f242f5c5..8c2d5c8b5f1d9e47490d6fd387acb2f5c5241776 100644 (file)
@@ -1,15 +1,15 @@
-/* Implements a lightweight menubar widget.  
+/* Implements a lightweight menubar widget.
    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 2, 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 2, 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.
 
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
@@ -27,21 +27,60 @@ Boston, MA 02111-1307, USA.  */
 #include <stdio.h>
 
 #include <sys/types.h>
 #include <stdio.h>
 
 #include <sys/types.h>
+#if (defined __sun) && !(defined SUNOS41)
+#define SUNOS41
 #include <X11/Xos.h>
 #include <X11/Xos.h>
+#undef SUNOS41
+#else
+#include <X11/Xos.h>
+#endif
 #include <X11/IntrinsicP.h>
 #include <X11/ObjectP.h>
 #include <X11/StringDefs.h>
 #include <X11/cursorfont.h>
 #include <X11/IntrinsicP.h>
 #include <X11/ObjectP.h>
 #include <X11/StringDefs.h>
 #include <X11/cursorfont.h>
-#include <X11/bitmaps/gray>
 #include "xlwmenuP.h"
 
 #include "xlwmenuP.h"
 
+#ifdef emacs
+
+/* Defined in xfns.c.  When config.h defines `static' as empty, we get
+   redefinition errors when gray_bitmap is included more than once, so
+   we're referring to the one include in xfns.c here.  */
+
+extern int gray_bitmap_width;
+extern int gray_bitmap_height;
+extern char *gray_bitmap_bits;
+
+/* Defined in xterm.c.  */
+extern int x_alloc_nearest_color_for_widget __P ((Widget, Colormap, XColor*));
+extern int x_alloc_lighter_color_for_widget __P ((Widget, Display*, Colormap,
+                                                 unsigned long *,
+                                                 double, int));
+extern int x_catch_errors __P ((Display*));
+extern int x_uncatch_errors __P ((Display*, int));
+extern int x_had_errors_p __P ((Display*));
+extern int x_clear_errors __P ((Display*));
+extern unsigned long x_copy_dpy_color __P ((Display *, Colormap,
+                                           unsigned long));
+
+/* Defined in xfaces.c.  */
+extern void x_free_dpy_colors __P ((Display *, Screen *, Colormap,
+                                   unsigned long *pixels, int npixels));
+#else /* not emacs */
+
+#include <X11/bitmaps/gray>
+#define gray_bitmap_width      gray_width
+#define gray_bitmap_height     gray_height
+#define gray_bitmap_bits       gray_bits
+
+#endif /* not emacs */
+
 static int pointer_grabbed;
 static XEvent menu_post_event;
 
 XFontStruct *xlwmenu_default_font;
 
 static int pointer_grabbed;
 static XEvent menu_post_event;
 
 XFontStruct *xlwmenu_default_font;
 
-static char 
-xlwMenuTranslations [] = 
+static char
+xlwMenuTranslations [] =
 "<BtnDown>:      start()\n\
 <Motion>:        drag()\n\
 <BtnUp>:         select()\n\
 "<BtnDown>:      start()\n\
 <Motion>:        drag()\n\
 <BtnUp>:         select()\n\
@@ -78,9 +117,9 @@ xlwMenuTranslations [] =
 ";
 
 #define offset(field) XtOffset(XlwMenuWidget, field)
 ";
 
 #define offset(field) XtOffset(XlwMenuWidget, field)
-static XtResource 
+static XtResource
 xlwMenuResources[] =
 xlwMenuResources[] =
-{ 
+{
   {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
      offset(menu.font),XtRString, "XtDefaultFont"},
   {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
   {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
      offset(menu.font),XtRString, "XtDefaultFont"},
   {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
@@ -108,10 +147,12 @@ xlwMenuResources[] =
   {XmNbottomShadowPixmap, XmCBottomShadowPixmap, XtRPixmap, sizeof (Pixmap),
      offset (menu.bottom_shadow_pixmap), XtRImmediate, (XtPointer)None},
 
   {XmNbottomShadowPixmap, XmCBottomShadowPixmap, XtRPixmap, sizeof (Pixmap),
      offset (menu.bottom_shadow_pixmap), XtRImmediate, (XtPointer)None},
 
-  {XtNopen, XtCCallback, XtRCallback, sizeof(XtPointer), 
+  {XtNopen, XtCCallback, XtRCallback, sizeof(XtPointer),
      offset(menu.open), XtRCallback, (XtPointer)NULL},
      offset(menu.open), XtRCallback, (XtPointer)NULL},
-  {XtNselect, XtCCallback, XtRCallback, sizeof(XtPointer), 
+  {XtNselect, XtCCallback, XtRCallback, sizeof(XtPointer),
      offset(menu.select), XtRCallback, (XtPointer)NULL},
      offset(menu.select), XtRCallback, (XtPointer)NULL},
+  {XtNhighlightCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
+     offset(menu.highlight), XtRCallback, (XtPointer)NULL},
   {XtNmenu, XtCMenu, XtRPointer, sizeof(XtPointer),
      offset(menu.contents), XtRImmediate, (XtPointer)NULL},
   {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
   {XtNmenu, XtCMenu, XtRPointer, sizeof(XtPointer),
      offset(menu.contents), XtRImmediate, (XtPointer)NULL},
   {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
@@ -136,7 +177,7 @@ static void Key();
 static void Nothing();
 static int separator_height ();
 
 static void Nothing();
 static int separator_height ();
 
-static XtActionsRec 
+static XtActionsRec
 xlwMenuActionsList [] =
 {
   {"start",            Start},
 xlwMenuActionsList [] =
 {
   {"start",            Start},
@@ -151,7 +192,7 @@ xlwMenuActionsList [] =
 XlwMenuClassRec xlwMenuClassRec =
 {
   {  /* CoreClass fields initialization */
 XlwMenuClassRec xlwMenuClassRec =
 {
   {  /* CoreClass fields initialization */
-    (WidgetClass) SuperClass,          /* superclass             */    
+    (WidgetClass) SuperClass,          /* superclass             */
     "XlwMenu",                         /* class_name             */
     sizeof(XlwMenuRec),                        /* size                   */
     XlwMenuClassInitialize,            /* class_initialize       */
     "XlwMenu",                         /* class_name             */
     sizeof(XlwMenuRec),                        /* size                   */
     XlwMenuClassInitialize,            /* class_initialize       */
@@ -272,7 +313,7 @@ string_width (mw, s)
 {
   XCharStruct xcs;
   int drop;
 {
   XCharStruct xcs;
   int drop;
-  
+
   XTextExtents (mw->menu.font, s, strlen (s), &drop, &drop, &drop, &xcs);
   return xcs.width;
 }
   XTextExtents (mw->menu.font, s, strlen (s), &drop, &drop, &drop, &xcs);
   return xcs.width;
 }
@@ -306,7 +347,7 @@ radio_button_width (mw)
 
 static XtResource
 nameResource[] =
 
 static XtResource
 nameResource[] =
-{ 
+{
   {"labelString",  "LabelString", XtRString, sizeof(String),
      0, XtRImmediate, 0},
 };
   {"labelString",  "LabelString", XtRString, sizeof(String),
      0, XtRImmediate, 0},
 };
@@ -361,7 +402,7 @@ size_menu_item (mw, val, horizontal_p, label_width, rest_width, button_width,
      int* height;
 {
   enum menu_separator separator;
      int* height;
 {
   enum menu_separator separator;
-  
+
   if (lw_separator_p (val->name, &separator, 0))
     {
       *height = separator_height (separator);
   if (lw_separator_p (val->name, &separator, 0))
     {
       *height = separator_height (separator);
@@ -374,11 +415,11 @@ size_menu_item (mw, val, horizontal_p, label_width, rest_width, button_width,
       *height =
        mw->menu.font->ascent + mw->menu.font->descent
          + 2 * mw->menu.vertical_spacing + 2 * mw->menu.shadow_thickness;
       *height =
        mw->menu.font->ascent + mw->menu.font->descent
          + 2 * mw->menu.vertical_spacing + 2 * mw->menu.shadow_thickness;
-      
+
       *label_width =
        string_width (mw, resource_widget_value (mw, val))
          + mw->menu.horizontal_spacing + mw->menu.shadow_thickness;
       *label_width =
        string_width (mw, resource_widget_value (mw, val))
          + mw->menu.horizontal_spacing + mw->menu.shadow_thickness;
-      
+
       *rest_width =  mw->menu.horizontal_spacing + mw->menu.shadow_thickness;
       if (!horizontal_p)
        {
       *rest_width =  mw->menu.horizontal_spacing + mw->menu.shadow_thickness;
       if (!horizontal_p)
        {
@@ -418,7 +459,7 @@ size_menu (mw, level)
   if (level >= mw->menu.old_depth)
     abort_gracefully ((Widget) mw);
 
   if (level >= mw->menu.old_depth)
     abort_gracefully ((Widget) mw);
 
-  ws = &mw->menu.windows [level];  
+  ws = &mw->menu.windows [level];
   ws->width = 0;
   ws->height = 0;
   ws->label_width = 0;
   ws->width = 0;
   ws->height = 0;
   ws->label_width = 0;
@@ -445,7 +486,7 @@ size_menu (mw, level)
          ws->height += height;
        }
     }
          ws->height += height;
        }
     }
-  
+
   if (horizontal_p)
     ws->label_width = ws->button_width = 0;
   else
   if (horizontal_p)
     ws->label_width = ws->button_width = 0;
   else
@@ -487,9 +528,9 @@ draw_arrow (mw, window, gc, x, y, width, down_p)
      factor = (1 + sin (alpha)) / cos (alpha) */
   double factor = 1.62;
   int thickness2 = thickness * factor;
      factor = (1 + sin (alpha)) / cos (alpha) */
   double factor = 1.62;
   int thickness2 = thickness * factor;
-  
+
   y += (mw->menu.font->ascent + mw->menu.font->descent - height) / 2;
   y += (mw->menu.font->ascent + mw->menu.font->descent - height) / 2;
-  
+
   if (down_p)
     {
       GC temp;
   if (down_p)
     {
       GC temp;
@@ -507,7 +548,7 @@ draw_arrow (mw, window, gc, x, y, width, down_p)
   pt[3].x = x;
   pt[3].y = y;
   XFillPolygon (dpy, window, top_gc, pt, 4, Convex, CoordModeOrigin);
   pt[3].x = x;
   pt[3].y = y;
   XFillPolygon (dpy, window, top_gc, pt, 4, Convex, CoordModeOrigin);
-  
+
   pt[0].x = x;
   pt[0].y = y;
   pt[1].x = x + thickness;
   pt[0].x = x;
   pt[0].y = y;
   pt[1].x = x + thickness;
@@ -517,7 +558,7 @@ draw_arrow (mw, window, gc, x, y, width, down_p)
   pt[3].x = x + width;
   pt[3].y = y + height / 2;
   XFillPolygon (dpy, window, top_gc, pt, 4, Convex, CoordModeOrigin);
   pt[3].x = x + width;
   pt[3].y = y + height / 2;
   XFillPolygon (dpy, window, top_gc, pt, 4, Convex, CoordModeOrigin);
-  
+
   pt[0].x = x;
   pt[0].y = y + height;
   pt[1].x = x + thickness;
   pt[0].x = x;
   pt[0].y = y + height;
   pt[1].x = x + thickness;
@@ -555,7 +596,7 @@ draw_shadow_rectangle (mw, window, x, y, width, height, erase_p, down_p)
       top_gc = bottom_gc;
       bottom_gc = temp;
     }
       top_gc = bottom_gc;
       bottom_gc = temp;
     }
-  
+
   points [0].x = x;
   points [0].y = y;
   points [1].x = x + width;
   points [0].x = x;
   points [0].y = y;
   points [1].x = x + width;
@@ -611,7 +652,6 @@ draw_shadow_rhombus (mw, window, x, y, width, height, erase_p, down_p)
   GC bottom_gc = !erase_p ? mw->menu.shadow_bottom_gc : mw->menu.background_gc;
   int thickness = mw->menu.shadow_thickness;
   XPoint points [4];
   GC bottom_gc = !erase_p ? mw->menu.shadow_bottom_gc : mw->menu.background_gc;
   int thickness = mw->menu.shadow_thickness;
   XPoint points [4];
-  double sqrt2 = 1.4142;
 
   if (!erase_p && down_p)
     {
 
   if (!erase_p && down_p)
     {
@@ -718,17 +758,17 @@ draw_separator (mw, window, x, y, width, type)
     {
     case SEPARATOR_NO_LINE:
       break;
     {
     case SEPARATOR_NO_LINE:
       break;
-      
+
     case SEPARATOR_SINGLE_LINE:
       XDrawLine (dpy, window, mw->menu.foreground_gc,
                 x, y, x + width, y);
       break;
     case SEPARATOR_SINGLE_LINE:
       XDrawLine (dpy, window, mw->menu.foreground_gc,
                 x, y, x + width, y);
       break;
-      
+
     case SEPARATOR_DOUBLE_LINE:
       draw_separator (mw, window, x, y, width, SEPARATOR_SINGLE_LINE);
       draw_separator (mw, window, x, y + 2, width, SEPARATOR_SINGLE_LINE);
       break;
     case SEPARATOR_DOUBLE_LINE:
       draw_separator (mw, window, x, y, width, SEPARATOR_SINGLE_LINE);
       draw_separator (mw, window, x, y + 2, width, SEPARATOR_SINGLE_LINE);
       break;
-      
+
     case SEPARATOR_SINGLE_DASHED_LINE:
       xgcv.line_style = LineOnOffDash;
       XChangeGC (dpy, mw->menu.foreground_gc, GCLineStyle, &xgcv);
     case SEPARATOR_SINGLE_DASHED_LINE:
       xgcv.line_style = LineOnOffDash;
       XChangeGC (dpy, mw->menu.foreground_gc, GCLineStyle, &xgcv);
@@ -737,14 +777,14 @@ draw_separator (mw, window, x, y, width, type)
       xgcv.line_style = LineSolid;
       XChangeGC (dpy, mw->menu.foreground_gc, GCLineStyle, &xgcv);
       break;
       xgcv.line_style = LineSolid;
       XChangeGC (dpy, mw->menu.foreground_gc, GCLineStyle, &xgcv);
       break;
-      
+
     case SEPARATOR_DOUBLE_DASHED_LINE:
       draw_separator (mw, window, x, y, width,
                      SEPARATOR_SINGLE_DASHED_LINE);
       draw_separator (mw, window, x, y + 2, width,
                      SEPARATOR_SINGLE_DASHED_LINE);
       break;
     case SEPARATOR_DOUBLE_DASHED_LINE:
       draw_separator (mw, window, x, y, width,
                      SEPARATOR_SINGLE_DASHED_LINE);
       draw_separator (mw, window, x, y + 2, width,
                      SEPARATOR_SINGLE_DASHED_LINE);
       break;
-      
+
     case SEPARATOR_SHADOW_ETCHED_IN:
       XDrawLine (dpy, window, mw->menu.shadow_bottom_gc,
                 x, y, x + width, y);
     case SEPARATOR_SHADOW_ETCHED_IN:
       XDrawLine (dpy, window, mw->menu.shadow_bottom_gc,
                 x, y, x + width, y);
@@ -758,22 +798,22 @@ draw_separator (mw, window, x, y, width, type)
       XDrawLine (dpy, window, mw->menu.shadow_bottom_gc,
                 x, y + 1, x + width, y + 1);
       break;
       XDrawLine (dpy, window, mw->menu.shadow_bottom_gc,
                 x, y + 1, x + width, y + 1);
       break;
-      
+
     case SEPARATOR_SHADOW_ETCHED_IN_DASH:
       xgcv.line_style = LineOnOffDash;
       XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
       XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
     case SEPARATOR_SHADOW_ETCHED_IN_DASH:
       xgcv.line_style = LineOnOffDash;
       XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
       XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
-      draw_separator (mw, window, x, y, SEPARATOR_SHADOW_ETCHED_IN);
+      draw_separator (mw, window, x, y, width, SEPARATOR_SHADOW_ETCHED_IN);
       xgcv.line_style = LineSolid;
       XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
       XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
       break;
       xgcv.line_style = LineSolid;
       XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
       XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
       break;
-      
+
     case SEPARATOR_SHADOW_ETCHED_OUT_DASH:
       xgcv.line_style = LineOnOffDash;
       XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
       XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
     case SEPARATOR_SHADOW_ETCHED_OUT_DASH:
       xgcv.line_style = LineOnOffDash;
       XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
       XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
-      draw_separator (mw, window, x, y, SEPARATOR_SHADOW_ETCHED_OUT);
+      draw_separator (mw, window, x, y, width, SEPARATOR_SHADOW_ETCHED_OUT);
       xgcv.line_style = LineSolid;
       XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
       XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
       xgcv.line_style = LineSolid;
       XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
       XChangeGC (dpy, mw->menu.shadow_top_gc, GCLineStyle, &xgcv);
@@ -783,14 +823,14 @@ draw_separator (mw, window, x, y, width, type)
       draw_separator (mw, window, x, y, width, SEPARATOR_SHADOW_ETCHED_IN);
       draw_separator (mw, window, x, y + 3, width, SEPARATOR_SHADOW_ETCHED_IN);
       break;
       draw_separator (mw, window, x, y, width, SEPARATOR_SHADOW_ETCHED_IN);
       draw_separator (mw, window, x, y + 3, width, SEPARATOR_SHADOW_ETCHED_IN);
       break;
-      
+
     case SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT:
       draw_separator (mw, window, x, y, width,
                      SEPARATOR_SHADOW_ETCHED_OUT);
       draw_separator (mw, window, x, y + 3, width,
                      SEPARATOR_SHADOW_ETCHED_OUT);
       break;
     case SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT:
       draw_separator (mw, window, x, y, width,
                      SEPARATOR_SHADOW_ETCHED_OUT);
       draw_separator (mw, window, x, y + 3, width,
                      SEPARATOR_SHADOW_ETCHED_OUT);
       break;
-      
+
     case SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH:
       xgcv.line_style = LineOnOffDash;
       XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
     case SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH:
       xgcv.line_style = LineOnOffDash;
       XChangeGC (dpy, mw->menu.shadow_bottom_gc, GCLineStyle, &xgcv);
@@ -829,27 +869,27 @@ separator_height (separator)
     {
     case SEPARATOR_NO_LINE:
       return 2;
     {
     case SEPARATOR_NO_LINE:
       return 2;
-      
+
     case SEPARATOR_SINGLE_LINE:
     case SEPARATOR_SINGLE_DASHED_LINE:
       return 1;
     case SEPARATOR_SINGLE_LINE:
     case SEPARATOR_SINGLE_DASHED_LINE:
       return 1;
-      
+
     case SEPARATOR_DOUBLE_LINE:
     case SEPARATOR_DOUBLE_DASHED_LINE:
       return 3;
     case SEPARATOR_DOUBLE_LINE:
     case SEPARATOR_DOUBLE_DASHED_LINE:
       return 3;
-      
+
     case SEPARATOR_SHADOW_ETCHED_IN:
     case SEPARATOR_SHADOW_ETCHED_OUT:
     case SEPARATOR_SHADOW_ETCHED_IN_DASH:
     case SEPARATOR_SHADOW_ETCHED_OUT_DASH:
       return 2;
     case SEPARATOR_SHADOW_ETCHED_IN:
     case SEPARATOR_SHADOW_ETCHED_OUT:
     case SEPARATOR_SHADOW_ETCHED_IN_DASH:
     case SEPARATOR_SHADOW_ETCHED_OUT_DASH:
       return 2;
-      
+
     case SEPARATOR_SHADOW_DOUBLE_ETCHED_IN:
     case SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT:
     case SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH:
     case SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH:
       return 5;
     case SEPARATOR_SHADOW_DOUBLE_ETCHED_IN:
     case SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT:
     case SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH:
     case SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH:
       return 5;
-      
+
     default:
       abort ();
     }
     default:
       abort ();
     }
@@ -927,7 +967,7 @@ display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p,
        {
          draw_separator (mw, ws->window, x, y, width, separator);
        }
        {
          draw_separator (mw, ws->window, x, y, width, separator);
        }
-      else 
+      else
        {
          int x_offset = x + h_spacing + shadow;
          char* display_string = resource_widget_value (mw, val);
        {
          int x_offset = x + h_spacing + shadow;
          char* display_string = resource_widget_value (mw, val);
@@ -944,12 +984,12 @@ display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p,
            }
          else if (!horizontal_p && ws->button_width)
            x_offset += ws->button_width;
            }
          else if (!horizontal_p && ws->button_width)
            x_offset += ws->button_width;
-         
-         
+
+
           XDrawString (XtDisplay (mw), ws->window, text_gc, x_offset,
                       y + v_spacing + shadow + font_ascent,
                       display_string, strlen (display_string));
           XDrawString (XtDisplay (mw), ws->window, text_gc, x_offset,
                       y + v_spacing + shadow + font_ascent,
                       display_string, strlen (display_string));
-         
+
          if (!horizontal_p)
            {
              if (val->button_type == BUTTON_TYPE_TOGGLE)
          if (!horizontal_p)
            {
              if (val->button_type == BUTTON_TYPE_TOGGLE)
@@ -958,13 +998,13 @@ display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p,
              else if (val->button_type == BUTTON_TYPE_RADIO)
                draw_radio (mw, ws->window, x, y + v_spacing + shadow,
                            val->selected);
              else if (val->button_type == BUTTON_TYPE_RADIO)
                draw_radio (mw, ws->window, x, y + v_spacing + shadow,
                            val->selected);
-             
+
              if (val->contents)
                {
                  int a_w = arrow_width (mw);
                  draw_arrow (mw, ws->window, deco_gc,
                              x + width - a_w
              if (val->contents)
                {
                  int a_w = arrow_width (mw);
                  draw_arrow (mw, ws->window, deco_gc,
                              x + width - a_w
-                             - mw->menu.horizontal_spacing 
+                             - mw->menu.horizontal_spacing
                              - mw->menu.shadow_thickness,
                              y + v_spacing + shadow, a_w,
                              highlighted_p);
                              - mw->menu.shadow_thickness,
                              y + v_spacing + shadow, a_w,
                              highlighted_p);
@@ -979,7 +1019,7 @@ display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p,
            }
          else
            {
            }
          else
            {
-             XDrawRectangle (XtDisplay (mw), ws->window, 
+             XDrawRectangle (XtDisplay (mw), ws->window,
                              mw->menu.background_gc,
                              x + shadow, y + shadow,
                              label_width + h_spacing - 1,
                              mw->menu.background_gc,
                              x + shadow, y + shadow,
                              label_width + h_spacing - 1,
@@ -993,7 +1033,7 @@ display_menu_item (mw, val, ws, where, highlighted_p, horizontal_p,
                                   False);
        }
     }
                                   False);
        }
     }
-  
+
   where->x += width;
   where->y += height;
 }
   where->x += width;
   where->y += height;
 }
@@ -1027,7 +1067,7 @@ display_menu (mw, level, just_compute_p, highlighted_pos, hit, hit_return,
 
   if (level < mw->menu.old_depth - 1)
     following_item = mw->menu.old_stack [level + 1];
 
   if (level < mw->menu.old_depth - 1)
     following_item = mw->menu.old_stack [level + 1];
-  else 
+  else
     following_item = NULL;
 
   if (hit)
     following_item = NULL;
 
   if (hit)
@@ -1047,7 +1087,7 @@ display_menu (mw, level, just_compute_p, highlighted_pos, hit, hit_return,
          else
            highlighted_pos->y = where.y;
        }
          else
            highlighted_pos->y = where.y;
        }
-      
+
       just_compute_this_one_p =
        just_compute_p || ((this || that) && val != this &&  val != that);
 
       just_compute_this_one_p =
        just_compute_p || ((this || that) && val != this &&  val != that);
 
@@ -1079,7 +1119,7 @@ display_menu (mw, level, just_compute_p, highlighted_pos, hit, hit_return,
       else
        where.x = 0;
     }
       else
        where.x = 0;
     }
-  
+
   if (!just_compute_p)
     draw_shadow_rectangle (mw, ws->window, 0, 0, ws->width, ws->height,
                           False, False);
   if (!just_compute_p)
     draw_shadow_rectangle (mw, ws->window, 0, 0, ws->width, ws->height,
                           False, False);
@@ -1093,7 +1133,7 @@ set_new_state (mw, val, level)
      int level;
 {
   int i;
      int level;
 {
   int i;
-  
+
   mw->menu.new_depth = 0;
   for (i = 0; i < level; i++)
     push_new_stack (mw, mw->menu.old_stack [i]);
   mw->menu.new_depth = 0;
   for (i = 0; i < level; i++)
     push_new_stack (mw, mw->menu.old_stack [i]);
@@ -1111,7 +1151,7 @@ make_windows_if_needed (mw, n)
   int mask;
   Window root = RootWindowOfScreen (DefaultScreenOfDisplay (XtDisplay (mw)));
   window_state* windows;
   int mask;
   Window root = RootWindowOfScreen (DefaultScreenOfDisplay (XtDisplay (mw)));
   window_state* windows;
-  
+
   if (mw->menu.windows_length >= n)
     return;
 
   if (mw->menu.windows_length >= n)
     return;
 
@@ -1125,7 +1165,7 @@ make_windows_if_needed (mw, n)
   xswa.cursor = mw->menu.cursor_shape;
   mask = CWSaveUnder | CWOverrideRedirect | CWBackPixel | CWBorderPixel
     | CWEventMask | CWCursor;
   xswa.cursor = mw->menu.cursor_shape;
   mask = CWSaveUnder | CWOverrideRedirect | CWBackPixel | CWBorderPixel
     | CWEventMask | CWCursor;
-  
+
   if (!mw->menu.windows)
     {
       mw->menu.windows =
   if (!mw->menu.windows)
     {
       mw->menu.windows =
@@ -1155,6 +1195,23 @@ make_windows_if_needed (mw, n)
   }
 }
 
   }
 }
 
+/* Value is non-zero if WINDOW is part of menu bar widget W.  */
+
+int
+xlwmenu_window_p (w, window)
+     Widget w;
+     Window window;
+{
+  XlwMenuWidget mw = (XlwMenuWidget) w;
+  int i;
+  
+  for (i = 0; i < mw->menu.windows_length; ++i)
+    if (window == mw->menu.windows[i].window)
+      break;
+
+  return i < mw->menu.windows_length;
+}
+
 /* Make the window fit in the screen */
 static void
 fit_to_screen (mw, ws, previous_ws, horizontal_p)
 /* Make the window fit in the screen */
 static void
 fit_to_screen (mw, ws, previous_ws, horizontal_p)
@@ -1174,7 +1231,11 @@ fit_to_screen (mw, ws, previous_ws, horizontal_p)
   else if (ws->x + ws->width > screen_width)
     {
       if (!horizontal_p)
   else if (ws->x + ws->width > screen_width)
     {
       if (!horizontal_p)
-       ws->x = previous_ws->x - ws->width;
+       /* The addition of shadow-thickness for a sub-menu's position is
+          to reflect a similar adjustment when the menu is displayed to
+          the right of the invoking menu-item; it makes the sub-menu
+          look more `attached' to the menu-item.  */
+       ws->x = previous_ws->x - ws->width + mw->menu.shadow_thickness;
       else
        ws->x = screen_width - ws->width;
       if (ws->x < 0)
       else
        ws->x = screen_width - ws->width;
       if (ws->x < 0)
@@ -1204,7 +1265,7 @@ fit_to_screen (mw, ws, previous_ws, horizontal_p)
        ws->y = previous_ws->y - ws->height;
       else
        ws->y = screen_height - ws->height;
        ws->y = previous_ws->y - ws->height;
       else
        ws->y = screen_height - ws->height;
-      if (ws->y < 0) 
+      if (ws->y < 0)
         ws->y = 0;
     }
 }
         ws->y = 0;
     }
 }
@@ -1246,6 +1307,11 @@ remap_menubar (mw)
   if (new_selection && !new_selection->enabled)
     new_selection = NULL;
 
   if (new_selection && !new_selection->enabled)
     new_selection = NULL;
 
+  /* Call callback when the hightlighted item changes.  */
+  if (old_selection || new_selection)
+    XtCallCallbackList ((Widget)mw, mw->menu.highlight,
+                       (XtPointer) new_selection);
+
   /* updates old_state from new_state.  It has to be done now because
      display_menu (called below) uses the old_stack to know what to display. */
   for (i = last_same + 1; i < new_depth; i++)
   /* updates old_state from new_state.  It has to be done now because
      display_menu (called below) uses the old_stack to know what to display. */
   for (i = last_same + 1; i < new_depth; i++)
@@ -1266,17 +1332,17 @@ remap_menubar (mw)
 
       ws->x = (previous_ws->x + selection_position.x
               + mw->menu.shadow_thickness);
 
       ws->x = (previous_ws->x + selection_position.x
               + mw->menu.shadow_thickness);
-      if (i == 1)
+      if (mw->menu.horizontal && i == 1)
        ws->x += mw->menu.margin;
 
 #if 0
       if (!mw->menu.horizontal || i > 1)
        ws->x += mw->menu.shadow_thickness;
 #endif
        ws->x += mw->menu.margin;
 
 #if 0
       if (!mw->menu.horizontal || i > 1)
        ws->x += mw->menu.shadow_thickness;
 #endif
-      
+
       ws->y = (previous_ws->y + selection_position.y
               + mw->menu.shadow_thickness);
       ws->y = (previous_ws->y + selection_position.y
               + mw->menu.shadow_thickness);
-      if (i == 1)
+      if (mw->menu.horizontal && i == 1)
        ws->y += mw->menu.margin;
 
       size_menu (mw, i);
        ws->y += mw->menu.margin;
 
       size_menu (mw, i);
@@ -1325,7 +1391,7 @@ map_event_to_widget_value (mw, ev, val, level)
   window_state*        ws;
 
   *val = NULL;
   window_state*        ws;
 
   *val = NULL;
-  
+
   /* Find the window */
   for (i = mw->menu.old_depth - 1; i >= 0; i--)
     {
   /* Find the window */
   for (i = mw->menu.old_depth - 1; i >= 0; i--)
     {
@@ -1357,14 +1423,14 @@ make_drawing_gcs (mw)
   mw->menu.foreground_gc = XtGetGC ((Widget)mw,
                                    GCFont | GCForeground | GCBackground,
                                    &xgcv);
   mw->menu.foreground_gc = XtGetGC ((Widget)mw,
                                    GCFont | GCForeground | GCBackground,
                                    &xgcv);
-  
+
   xgcv.font = mw->menu.font->fid;
   xgcv.foreground = mw->menu.button_foreground;
   xgcv.background = mw->core.background_pixel;
   mw->menu.button_gc = XtGetGC ((Widget)mw,
                                GCFont | GCForeground | GCBackground,
                                &xgcv);
   xgcv.font = mw->menu.font->fid;
   xgcv.foreground = mw->menu.button_foreground;
   xgcv.background = mw->core.background_pixel;
   mw->menu.button_gc = XtGetGC ((Widget)mw,
                                GCFont | GCForeground | GCBackground,
                                &xgcv);
-  
+
   xgcv.font = mw->menu.font->fid;
   xgcv.foreground = mw->menu.foreground;
   xgcv.background = mw->core.background_pixel;
   xgcv.font = mw->menu.font->fid;
   xgcv.foreground = mw->menu.foreground;
   xgcv.background = mw->core.background_pixel;
@@ -1373,7 +1439,7 @@ make_drawing_gcs (mw)
   mw->menu.inactive_gc = XtGetGC ((Widget)mw,
                                  (GCFont | GCForeground | GCBackground
                                   | GCFillStyle | GCStipple), &xgcv);
   mw->menu.inactive_gc = XtGetGC ((Widget)mw,
                                  (GCFont | GCForeground | GCBackground
                                   | GCFillStyle | GCStipple), &xgcv);
-  
+
   xgcv.font = mw->menu.font->fid;
   xgcv.foreground = mw->menu.button_foreground;
   xgcv.background = mw->core.background_pixel;
   xgcv.font = mw->menu.font->fid;
   xgcv.foreground = mw->menu.button_foreground;
   xgcv.background = mw->core.background_pixel;
@@ -1382,7 +1448,7 @@ make_drawing_gcs (mw)
   mw->menu.inactive_button_gc = XtGetGC ((Widget)mw,
                                  (GCFont | GCForeground | GCBackground
                                   | GCFillStyle | GCStipple), &xgcv);
   mw->menu.inactive_button_gc = XtGetGC ((Widget)mw,
                                  (GCFont | GCForeground | GCBackground
                                   | GCFillStyle | GCStipple), &xgcv);
-  
+
   xgcv.font = mw->menu.font->fid;
   xgcv.foreground = mw->core.background_pixel;
   xgcv.background = mw->menu.foreground;
   xgcv.font = mw->menu.font->fid;
   xgcv.foreground = mw->core.background_pixel;
   xgcv.background = mw->menu.foreground;
@@ -1419,31 +1485,42 @@ make_shadow_gcs (mw)
   unsigned long pm = 0;
   Display *dpy = XtDisplay ((Widget) mw);
   Screen *screen = XtScreen ((Widget) mw);
   unsigned long pm = 0;
   Display *dpy = XtDisplay ((Widget) mw);
   Screen *screen = XtScreen ((Widget) mw);
-  Colormap cmap = DefaultColormapOfScreen (screen);
+  Colormap cmap = mw->core.colormap;
   XColor topc, botc;
   int top_frobbed = 0, bottom_frobbed = 0;
 
   XColor topc, botc;
   int top_frobbed = 0, bottom_frobbed = 0;
 
+  mw->menu.free_top_shadow_color_p = 0;
+  mw->menu.free_bottom_shadow_color_p = 0;
+
   if (mw->menu.top_shadow_color == -1)
     mw->menu.top_shadow_color = mw->core.background_pixel;
   if (mw->menu.top_shadow_color == -1)
     mw->menu.top_shadow_color = mw->core.background_pixel;
+  else
+    mw->menu.top_shadow_color = mw->menu.top_shadow_color;
+
   if (mw->menu.bottom_shadow_color == -1)
     mw->menu.bottom_shadow_color = mw->menu.foreground;
   if (mw->menu.bottom_shadow_color == -1)
     mw->menu.bottom_shadow_color = mw->menu.foreground;
+  else
+    mw->menu.bottom_shadow_color = mw->menu.bottom_shadow_color;
 
   if (mw->menu.top_shadow_color == mw->core.background_pixel ||
       mw->menu.top_shadow_color == mw->menu.foreground)
     {
       topc.pixel = mw->core.background_pixel;
 
   if (mw->menu.top_shadow_color == mw->core.background_pixel ||
       mw->menu.top_shadow_color == mw->menu.foreground)
     {
       topc.pixel = mw->core.background_pixel;
+#ifdef emacs
+      if (x_alloc_lighter_color_for_widget ((Widget) mw, dpy, cmap,
+                                           &topc.pixel,
+                                           1.2, 0x8000))
+#else
       XQueryColor (dpy, cmap, &topc);
       /* don't overflow/wrap! */
       topc.red   = MINL (65535, topc.red   * 1.2);
       topc.green = MINL (65535, topc.green * 1.2);
       topc.blue  = MINL (65535, topc.blue  * 1.2);
       XQueryColor (dpy, cmap, &topc);
       /* don't overflow/wrap! */
       topc.red   = MINL (65535, topc.red   * 1.2);
       topc.green = MINL (65535, topc.green * 1.2);
       topc.blue  = MINL (65535, topc.blue  * 1.2);
-#ifdef emacs
-      if (x_alloc_nearest_color_for_widget (mw, cmap, &topc))
-#else
       if (XAllocColor (dpy, cmap, &topc))
 #endif
        {
          mw->menu.top_shadow_color = topc.pixel;
       if (XAllocColor (dpy, cmap, &topc))
 #endif
        {
          mw->menu.top_shadow_color = topc.pixel;
+         mw->menu.free_top_shadow_color_p = 1;
          top_frobbed = 1;
        }
     }
          top_frobbed = 1;
        }
     }
@@ -1451,37 +1528,48 @@ make_shadow_gcs (mw)
       mw->menu.bottom_shadow_color == mw->core.background_pixel)
     {
       botc.pixel = mw->core.background_pixel;
       mw->menu.bottom_shadow_color == mw->core.background_pixel)
     {
       botc.pixel = mw->core.background_pixel;
+#ifdef emacs
+      if (x_alloc_lighter_color_for_widget ((Widget) mw, dpy, cmap,
+                                           &botc.pixel,
+                                           0.6, 0x4000))
+#else
       XQueryColor (dpy, cmap, &botc);
       botc.red   *= 0.6;
       botc.green *= 0.6;
       botc.blue  *= 0.6;
       XQueryColor (dpy, cmap, &botc);
       botc.red   *= 0.6;
       botc.green *= 0.6;
       botc.blue  *= 0.6;
-#ifdef emacs
-      if (x_alloc_nearest_color_for_widget (mw, cmap, &botc))
-#else
       if (XAllocColor (dpy, cmap, &botc))
 #endif
        {
          mw->menu.bottom_shadow_color = botc.pixel;
       if (XAllocColor (dpy, cmap, &botc))
 #endif
        {
          mw->menu.bottom_shadow_color = botc.pixel;
+         mw->menu.free_bottom_shadow_color_p = 1;
          bottom_frobbed = 1;
        }
     }
 
   if (top_frobbed && bottom_frobbed)
     {
          bottom_frobbed = 1;
        }
     }
 
   if (top_frobbed && bottom_frobbed)
     {
-      int top_avg = ((topc.red / 3) + (topc.green / 3) + (topc.blue / 3));
-      int bot_avg = ((botc.red / 3) + (botc.green / 3) + (botc.blue / 3));
-      if (bot_avg > top_avg)
-       {
-         Pixel tmp = mw->menu.top_shadow_color;
-         mw->menu.top_shadow_color = mw->menu.bottom_shadow_color;
-         mw->menu.bottom_shadow_color = tmp;
-       }
-      else if (topc.pixel == botc.pixel)
+      if (topc.pixel == botc.pixel)
        {
          if (botc.pixel == mw->menu.foreground)
        {
          if (botc.pixel == mw->menu.foreground)
-           mw->menu.top_shadow_color = mw->core.background_pixel;
+           {
+             if (mw->menu.free_top_shadow_color_p)
+               {
+                 x_free_dpy_colors (dpy, screen, cmap,
+                                    &mw->menu.top_shadow_color, 1);
+                 mw->menu.free_top_shadow_color_p = 0;
+               }
+             mw->menu.top_shadow_color = mw->core.background_pixel;
+           }
          else
          else
-           mw->menu.bottom_shadow_color = mw->menu.foreground;
+           {
+             if (mw->menu.free_bottom_shadow_color_p)
+               {
+                 x_free_dpy_colors (dpy, screen, cmap,
+                                    &mw->menu.bottom_shadow_color, 1);
+                 mw->menu.free_bottom_shadow_color_p = 0;
+               }
+             mw->menu.bottom_shadow_color = mw->menu.foreground;
+           }
        }
     }
 
        }
     }
 
@@ -1489,12 +1577,23 @@ make_shadow_gcs (mw)
       mw->menu.top_shadow_color == mw->core.background_pixel)
     {
       mw->menu.top_shadow_pixmap = mw->menu.gray_pixmap;
       mw->menu.top_shadow_color == mw->core.background_pixel)
     {
       mw->menu.top_shadow_pixmap = mw->menu.gray_pixmap;
+      if (mw->menu.free_top_shadow_color_p)
+       {
+         x_free_dpy_colors (dpy, screen, cmap, &mw->menu.top_shadow_color, 1);
+         mw->menu.free_top_shadow_color_p = 0;
+       }
       mw->menu.top_shadow_color = mw->menu.foreground;
     }
   if (!mw->menu.bottom_shadow_pixmap &&
       mw->menu.bottom_shadow_color == mw->core.background_pixel)
     {
       mw->menu.bottom_shadow_pixmap = mw->menu.gray_pixmap;
       mw->menu.top_shadow_color = mw->menu.foreground;
     }
   if (!mw->menu.bottom_shadow_pixmap &&
       mw->menu.bottom_shadow_color == mw->core.background_pixel)
     {
       mw->menu.bottom_shadow_pixmap = mw->menu.gray_pixmap;
+      if (mw->menu.free_bottom_shadow_color_p)
+       {
+         x_free_dpy_colors (dpy, screen, cmap,
+                            &mw->menu.bottom_shadow_color, 1);
+         mw->menu.free_bottom_shadow_color_p = 0;
+       }
       mw->menu.bottom_shadow_color = mw->menu.foreground;
     }
 
       mw->menu.bottom_shadow_color = mw->menu.foreground;
     }
 
@@ -1515,6 +1614,19 @@ static void
 release_shadow_gcs (mw)
      XlwMenuWidget mw;
 {
 release_shadow_gcs (mw)
      XlwMenuWidget mw;
 {
+  Display *dpy = XtDisplay ((Widget) mw);
+  Screen *screen = XtScreen ((Widget) mw);
+  Colormap cmap = mw->core.colormap;
+  Pixel px[2];
+  int i = 0;
+
+  if (mw->menu.free_top_shadow_color_p)
+    px[i++] = mw->menu.top_shadow_color;
+  if (mw->menu.free_bottom_shadow_color_p)
+    px[i++] = mw->menu.bottom_shadow_color;
+  if (i > 0)
+    x_free_dpy_colors (dpy, screen, cmap, px, i);
+
   XtReleaseGC ((Widget) mw, mw->menu.shadow_top_gc);
   XtReleaseGC ((Widget) mw, mw->menu.shadow_bottom_gc);
 }
   XtReleaseGC ((Widget) mw, mw->menu.shadow_top_gc);
   XtReleaseGC ((Widget) mw, mw->menu.shadow_bottom_gc);
 }
@@ -1529,10 +1641,10 @@ XlwMenuInitialize (request, mw, args, num_args)
   /* Get the GCs and the widget size */
   XSetWindowAttributes xswa;
   int mask;
   /* Get the GCs and the widget size */
   XSetWindowAttributes xswa;
   int mask;
-  
+
   Window window = RootWindowOfScreen (DefaultScreenOfDisplay (XtDisplay (mw)));
   Display* display = XtDisplay (mw);
   Window window = RootWindowOfScreen (DefaultScreenOfDisplay (XtDisplay (mw)));
   Display* display = XtDisplay (mw);
-  
+
 #if 0
   widget_value *tem = (widget_value *) XtMalloc (sizeof (widget_value));
 
 #if 0
   widget_value *tem = (widget_value *) XtMalloc (sizeof (widget_value));
 
@@ -1544,12 +1656,12 @@ XlwMenuInitialize (request, mw, args, num_args)
 
 /*  mw->menu.cursor = XCreateFontCursor (display, mw->menu.cursor_shape); */
   mw->menu.cursor = mw->menu.cursor_shape;
 
 /*  mw->menu.cursor = XCreateFontCursor (display, mw->menu.cursor_shape); */
   mw->menu.cursor = mw->menu.cursor_shape;
-  
+
   mw->menu.gray_pixmap
   mw->menu.gray_pixmap
-    = XCreatePixmapFromBitmapData (display, window, gray_bits,
-                                  gray_width, gray_height,
+    = XCreatePixmapFromBitmapData (display, window, gray_bitmap_bits,
+                                  gray_bitmap_width, gray_bitmap_height,
                                   (unsigned long)1, (unsigned long)0, 1);
                                   (unsigned long)1, (unsigned long)0, 1);
-  
+
   /* I don't understand why this ends up 0 sometimes,
      but it does.  This kludge works around it.
      Can anyone find a real fix?   -- rms.  */
   /* I don't understand why this ends up 0 sometimes,
      but it does.  This kludge works around it.
      Can anyone find a real fix?   -- rms.  */
@@ -1558,23 +1670,23 @@ XlwMenuInitialize (request, mw, args, num_args)
 
   make_drawing_gcs (mw);
   make_shadow_gcs (mw);
 
   make_drawing_gcs (mw);
   make_shadow_gcs (mw);
-  
+
   xswa.background_pixel = mw->core.background_pixel;
   xswa.border_pixel = mw->core.border_pixel;
   mask = CWBackPixel | CWBorderPixel;
   xswa.background_pixel = mw->core.background_pixel;
   xswa.border_pixel = mw->core.border_pixel;
   mask = CWBackPixel | CWBorderPixel;
-  
+
   mw->menu.popped_up = False;
   mw->menu.popped_up = False;
-  
+
   mw->menu.old_depth = 1;
   mw->menu.old_stack = (widget_value**)XtMalloc (sizeof (widget_value*));
   mw->menu.old_stack_length = 1;
   mw->menu.old_stack [0] = mw->menu.contents;
   mw->menu.old_depth = 1;
   mw->menu.old_stack = (widget_value**)XtMalloc (sizeof (widget_value*));
   mw->menu.old_stack_length = 1;
   mw->menu.old_stack [0] = mw->menu.contents;
-  
+
   mw->menu.new_depth = 0;
   mw->menu.new_stack = 0;
   mw->menu.new_stack_length = 0;
   push_new_stack (mw, mw->menu.contents);
   mw->menu.new_depth = 0;
   mw->menu.new_stack = 0;
   mw->menu.new_stack_length = 0;
   push_new_stack (mw, mw->menu.contents);
-  
+
   mw->menu.windows = (window_state*)XtMalloc (sizeof (window_state));
   mw->menu.windows_length = 1;
   mw->menu.windows [0].x = 0;
   mw->menu.windows = (window_state*)XtMalloc (sizeof (window_state));
   mw->menu.windows_length = 1;
   mw->menu.windows [0].x = 0;
@@ -1582,7 +1694,7 @@ XlwMenuInitialize (request, mw, args, num_args)
   mw->menu.windows [0].width = 0;
   mw->menu.windows [0].height = 0;
   size_menu (mw, 0);
   mw->menu.windows [0].width = 0;
   mw->menu.windows [0].height = 0;
   size_menu (mw, 0);
-  
+
   mw->core.width = mw->menu.windows [0].width;
   mw->core.height = mw->menu.windows [0].height;
 }
   mw->core.width = mw->menu.windows [0].width;
   mw->core.height = mw->menu.windows [0].height;
 }
@@ -1620,7 +1732,7 @@ XlwMenuRealize (w, valueMask, attributes)
 /* Only the toplevel menubar/popup is a widget so it's the only one that
    receives expose events through Xt.  So we repaint all the other panes
    when receiving an Expose event. */
 /* Only the toplevel menubar/popup is a widget so it's the only one that
    receives expose events through Xt.  So we repaint all the other panes
    when receiving an Expose event. */
-static void 
+static void
 XlwMenuRedisplay (w, ev, region)
      Widget w;
      XEvent* ev;
 XlwMenuRedisplay (w, ev, region)
      Widget w;
      XEvent* ev;
@@ -1641,7 +1753,18 @@ XlwMenuRedisplay (w, ev, region)
     display_menu (mw, i, False, NULL, NULL, NULL, NULL, NULL);
 }
 
     display_menu (mw, i, False, NULL, NULL, NULL, NULL, NULL);
 }
 
-static void 
+
+/* Part of a hack to make the menu redisplay when a tooltip frame
+   over a menu item is unmapped.  */
+
+void
+xlwmenu_redisplay (w)
+     Widget w;
+{
+  XlwMenuRedisplay (w, NULL, None);
+}
+
+static void
 XlwMenuDestroy (w)
      Widget w;
 {
 XlwMenuDestroy (w)
      Widget w;
 {
@@ -1692,7 +1815,7 @@ XlwMenuDestroy (w)
     XtFree ((char *) mw->menu.windows);
 }
 
     XtFree ((char *) mw->menu.windows);
 }
 
-static Boolean 
+static Boolean
 XlwMenuSetValues (current, request, new)
      Widget current;
      Widget request;
 XlwMenuSetValues (current, request, new)
      Widget current;
      Widget request;
@@ -1719,23 +1842,32 @@ XlwMenuSetValues (current, request, new)
     {
       release_drawing_gcs (newmw);
       make_drawing_gcs (newmw);
     {
       release_drawing_gcs (newmw);
       make_drawing_gcs (newmw);
+
+      release_shadow_gcs (newmw);
+      /* Cause the shadow colors to be recalculated.  */
+      newmw->menu.top_shadow_color = -1;
+      newmw->menu.bottom_shadow_color = -1;
+      make_shadow_gcs (newmw);
+
       redisplay = True;
       redisplay = True;
-      
-      for (i = 0; i < oldmw->menu.windows_length; i++)
-       {
-         XSetWindowBackground (XtDisplay (oldmw),
-                               oldmw->menu.windows [i].window,
-                               newmw->core.background_pixel);
-         /* clear windows and generate expose events */
-         XClearArea (XtDisplay (oldmw), oldmw->menu.windows[i].window,
-                     0, 0, 0, 0, True);
-       }
+
+      if (XtIsRealized (current))
+       /* If the menu is currently displayed, change the display.  */
+       for (i = 0; i < oldmw->menu.windows_length; i++)
+         {
+           XSetWindowBackground (XtDisplay (oldmw),
+                                 oldmw->menu.windows [i].window,
+                                 newmw->core.background_pixel);
+           /* clear windows and generate expose events */
+           XClearArea (XtDisplay (oldmw), oldmw->menu.windows[i].window,
+                       0, 0, 0, 0, True);
+         }
     }
 
   return redisplay;
 }
 
     }
 
   return redisplay;
 }
 
-static void 
+static void
 XlwMenuResize (w)
      Widget w;
 {
 XlwMenuResize (w)
      Widget w;
 {
@@ -1770,7 +1902,7 @@ handle_single_motion_event (mw, ev)
   else
     set_new_state (mw, val, level);
   remap_menubar (mw);
   else
     set_new_state (mw, val, level);
   remap_menubar (mw);
-  
+
   /* Sync with the display.  Makes it feel better on X terms. */
   XSync (XtDisplay (mw), False);
 }
   /* Sync with the display.  Makes it feel better on X terms. */
   XSync (XtDisplay (mw), False);
 }
@@ -1798,7 +1930,7 @@ handle_motion_event (mw, ev)
     handle_single_motion_event (mw, ev);
 }
 
     handle_single_motion_event (mw, ev);
 }
 
-static void 
+static void
 Start (w, ev, params, num_params)
      Widget w;
      XEvent *ev;
 Start (w, ev, params, num_params)
      Widget w;
      XEvent *ev;
@@ -1810,7 +1942,7 @@ Start (w, ev, params, num_params)
   if (!mw->menu.popped_up)
     {
       menu_post_event = *ev;
   if (!mw->menu.popped_up)
     {
       menu_post_event = *ev;
-      pop_up_menu (mw, ev);
+      pop_up_menu (mw, (XButtonPressedEvent*) ev);
     }
   else
     {
     }
   else
     {
@@ -1827,7 +1959,7 @@ Start (w, ev, params, num_params)
     }
 }
 
     }
 }
 
-static void 
+static void
 Drag (w, ev, params, num_params)
      Widget w;
      XEvent *ev;
 Drag (w, ev, params, num_params)
      Widget w;
      XEvent *ev;
@@ -1891,7 +2023,7 @@ Select (w, ev, params, num_params)
 {
   XlwMenuWidget mw = (XlwMenuWidget)w;
   widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1];
 {
   XlwMenuWidget mw = (XlwMenuWidget)w;
   widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1];
-  
+
   /* If user releases the button quickly, without selecting anything,
      after the initial down-click that brought the menu up,
      do nothing.  */
   /* If user releases the button quickly, without selecting anything,
      after the initial down-click that brought the menu up,
      do nothing.  */