Fix menu bar activation with click for Motif/Lesstif.
[bpt/emacs.git] / src / xmenu.c
index ad0ec34..4b99297 100644 (file)
@@ -1,13 +1,13 @@
 /* X Communication module for terminals which understand the X protocol.
    Copyright (C) 1986, 1988, 1993, 1994, 1996, 1999, 2000, 2001, 2002, 2003,
-                 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs 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 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,9 +15,7 @@ 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., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* X pop-up deck-of-cards menu facility for GNU Emacs.
  *
@@ -39,6 +37,7 @@ Boston, MA 02110-1301, USA.  */
 #endif
 
 #include <stdio.h>
+#include <setjmp.h>
 
 #include "lisp.h"
 #include "keyboard.h"
@@ -82,6 +81,8 @@ Boston, MA 02110-1301, USA.  */
 #include <X11/StringDefs.h>
 #include <X11/Shell.h>
 #ifdef USE_LUCID
+#include "xsettings.h"
+#include "../lwlib/xlwmenu.h"
 #ifdef HAVE_XAW3D
 #include <X11/Xaw3d/Paned.h>
 #else /* !HAVE_XAW3D */
@@ -96,6 +97,12 @@ Boston, MA 02110-1301, USA.  */
 #endif /* not USE_X_TOOLKIT */
 #endif /* HAVE_X_WINDOWS */
 
+#ifdef USE_GTK
+#include "gtkutil.h"
+#endif
+
+#include "menu.h"
+
 #ifndef TRUE
 #define TRUE 1
 #define FALSE 0
@@ -103,8 +110,6 @@ Boston, MA 02110-1301, USA.  */
 
 Lisp_Object Qdebug_on_next_call;
 
-extern Lisp_Object Vmenu_updating_frame;
-
 extern Lisp_Object Qmenu_bar;
 
 extern Lisp_Object QCtoggle, QCradio;
@@ -117,133 +122,42 @@ extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 extern Lisp_Object Qmenu_bar_update_hook;
 
 #ifdef USE_X_TOOLKIT
-extern void set_frame_menubar P_ ((FRAME_PTR, int, int));
+extern void set_frame_menubar (FRAME_PTR, int, int);
 extern XtAppContext Xt_app_con;
 
-static Lisp_Object xdialog_show P_ ((FRAME_PTR, int, Lisp_Object, Lisp_Object,
-                                    char **));
-static void popup_get_selection P_ ((XEvent *, struct x_display_info *,
-                                     LWLIB_ID, int));
-
-/* Define HAVE_BOXES if menus can handle radio and toggle buttons.  */
-
-#define HAVE_BOXES 1
+static Lisp_Object xdialog_show (FRAME_PTR, int, Lisp_Object, Lisp_Object,
+                                 char **);
+static void popup_get_selection (XEvent *, struct x_display_info *,
+                                 LWLIB_ID, int);
 #endif /* USE_X_TOOLKIT */
 
 #ifdef USE_GTK
-#include "gtkutil.h"
-#define HAVE_BOXES 1
-extern void set_frame_menubar P_ ((FRAME_PTR, int, int));
-static Lisp_Object xdialog_show P_ ((FRAME_PTR, int, Lisp_Object, Lisp_Object,
-                                    char **));
+extern void set_frame_menubar (FRAME_PTR, int, int);
+static Lisp_Object xdialog_show (FRAME_PTR, int, Lisp_Object, Lisp_Object,
+                                 char **);
 #endif
 
-/* This is how to deal with multibyte text if HAVE_MULTILINGUAL_MENU
-   isn't defined.  The use of HAVE_MULTILINGUAL_MENU could probably be
-   confined to an extended version of this with sections of code below
-   using it unconditionally.  */
-#ifdef USE_GTK
-/* gtk just uses utf-8.  */
-# define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str)
-#elif defined HAVE_X_I18N
-# define ENCODE_MENU_STRING(str) ENCODE_SYSTEM (str)
-#else
-# define ENCODE_MENU_STRING(str) string_make_unibyte (str)
-#endif
-
-static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
-                               Lisp_Object, Lisp_Object, Lisp_Object,
-                               Lisp_Object, Lisp_Object));
-static int update_frame_menubar P_ ((struct frame *));
-static Lisp_Object xmenu_show P_ ((struct frame *, int, int, int, int,
-                                  Lisp_Object, char **));
-static void keymap_panes P_ ((Lisp_Object *, int, int));
-static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
-                                    int, int));
-static void list_of_panes P_ ((Lisp_Object));
-static void list_of_items P_ ((Lisp_Object));
-
+static int update_frame_menubar (struct frame *);
 \f
-/* This holds a Lisp vector that holds the results of decoding
-   the keymaps or alist-of-alists that specify a menu.
-
-   It describes the panes and items within the panes.
-
-   Each pane is described by 3 elements in the vector:
-   t, the pane name, the pane's prefix key.
-   Then follow the pane's items, with 5 elements per item:
-   the item string, the enable flag, the item's value,
-   the definition, and the equivalent keyboard key's description string.
-
-   In some cases, multiple levels of menus may be described.
-   A single vector slot containing nil indicates the start of a submenu.
-   A single vector slot containing lambda indicates the end of a submenu.
-   The submenu follows a menu item which is the way to reach the submenu.
-
-   A single vector slot containing quote indicates that the
-   following items should appear on the right of a dialog box.
-
-   Using a Lisp vector to hold this information while we decode it
-   takes care of protecting all the data from GC.  */
-
-#define MENU_ITEMS_PANE_NAME 1
-#define MENU_ITEMS_PANE_PREFIX 2
-#define MENU_ITEMS_PANE_LENGTH 3
-
-enum menu_item_idx
-{
-  MENU_ITEMS_ITEM_NAME = 0,
-  MENU_ITEMS_ITEM_ENABLE,
-  MENU_ITEMS_ITEM_VALUE,
-  MENU_ITEMS_ITEM_EQUIV_KEY,
-  MENU_ITEMS_ITEM_DEFINITION,
-  MENU_ITEMS_ITEM_TYPE,
-  MENU_ITEMS_ITEM_SELECTED,
-  MENU_ITEMS_ITEM_HELP,
-  MENU_ITEMS_ITEM_LENGTH
-};
-
-static Lisp_Object menu_items;
-
-/* If non-nil, means that the global vars defined here are already in use.
-   Used to detect cases where we try to re-enter this non-reentrant code.  */
-static Lisp_Object menu_items_inuse;
-
-/* Number of slots currently allocated in menu_items.  */
-static int menu_items_allocated;
-
-/* This is the index in menu_items of the first empty slot.  */
-static int menu_items_used;
-
-/* The number of panes currently recorded in menu_items,
-   excluding those within submenus.  */
-static int menu_items_n_panes;
-
-/* Current depth within submenus.  */
-static int menu_items_submenu_depth;
-
 /* Flag which when set indicates a dialog or menu has been posted by
    Xt on behalf of one of the widget sets.  */
 static int popup_activated_flag;
 
 static int next_menubar_widget_id;
 
-/* This is set nonzero after the user activates the menu bar, and set
-   to zero again after the menu bars are redisplayed by prepare_menu_bar.
-   While it is nonzero, all calls to set_frame_menubar go deep.
-
-   I don't understand why this is needed, but it does seem to be
-   needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>.  */
+/* For NS and NTGUI, these prototypes are defined in keyboard.h.  */
+#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
+extern widget_value *xmalloc_widget_value (void);
+extern widget_value *digest_single_submenu (int, int, int);
+#endif
 
-int pending_menu_activation;
 \f
 #ifdef USE_X_TOOLKIT
 
 /* Return the frame whose ->output_data.x->id equals ID, or 0 if none.  */
 
 static struct frame *
-menubar_id_to_frame (id)
-     LWLIB_ID id;
+menubar_id_to_frame (LWLIB_ID id)
 {
   Lisp_Object tail, frame;
   FRAME_PTR f;
@@ -264,463 +178,6 @@ menubar_id_to_frame (id)
 
 #endif
 \f
-/* Initialize the menu_items structure if we haven't already done so.
-   Also mark it as currently empty.  */
-
-static void
-init_menu_items ()
-{
-  if (!NILP (menu_items_inuse))
-    error ("Trying to use a menu from within a menu-entry");
-
-  if (NILP (menu_items))
-    {
-      menu_items_allocated = 60;
-      menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
-    }
-
-  menu_items_inuse = Qt;
-  menu_items_used = 0;
-  menu_items_n_panes = 0;
-  menu_items_submenu_depth = 0;
-}
-
-/* Call at the end of generating the data in menu_items.  */
-
-static void
-finish_menu_items ()
-{
-}
-
-static Lisp_Object
-unuse_menu_items (dummy)
-     Lisp_Object dummy;
-{
-  return menu_items_inuse = Qnil;
-}
-
-/* Call when finished using the data for the current menu
-   in menu_items.  */
-
-static void
-discard_menu_items ()
-{
-  /* Free the structure if it is especially large.
-     Otherwise, hold on to it, to save time.  */
-  if (menu_items_allocated > 200)
-    {
-      menu_items = Qnil;
-      menu_items_allocated = 0;
-    }
-  xassert (NILP (menu_items_inuse));
-}
-
-/* This undoes save_menu_items, and it is called by the specpdl unwind
-   mechanism.  */
-
-static Lisp_Object
-restore_menu_items (saved)
-     Lisp_Object saved;
-{
-  menu_items = XCAR (saved);
-  menu_items_inuse = (! NILP (menu_items) ? Qt : Qnil);
-  menu_items_allocated = (VECTORP (menu_items) ? ASIZE (menu_items) : 0);
-  saved = XCDR (saved);
-  menu_items_used = XINT (XCAR (saved));
-  saved = XCDR (saved);
-  menu_items_n_panes = XINT (XCAR (saved));
-  saved = XCDR (saved);
-  menu_items_submenu_depth = XINT (XCAR (saved));
-  return Qnil;
-}
-
-/* Push the whole state of menu_items processing onto the specpdl.
-   It will be restored when the specpdl is unwound.  */
-
-static void
-save_menu_items ()
-{
-  Lisp_Object saved = list4 (!NILP (menu_items_inuse) ? menu_items : Qnil,
-                            make_number (menu_items_used),
-                            make_number (menu_items_n_panes),
-                            make_number (menu_items_submenu_depth));
-  record_unwind_protect (restore_menu_items, saved);
-  menu_items_inuse = Qnil;
-  menu_items = Qnil;
-}
-\f
-/* Make the menu_items vector twice as large.  */
-
-static void
-grow_menu_items ()
-{
-  menu_items_allocated *= 2;
-  menu_items = larger_vector (menu_items, menu_items_allocated, Qnil);
-}
-
-/* Begin a submenu.  */
-
-static void
-push_submenu_start ()
-{
-  if (menu_items_used + 1 > menu_items_allocated)
-    grow_menu_items ();
-
-  XVECTOR (menu_items)->contents[menu_items_used++] = Qnil;
-  menu_items_submenu_depth++;
-}
-
-/* End a submenu.  */
-
-static void
-push_submenu_end ()
-{
-  if (menu_items_used + 1 > menu_items_allocated)
-    grow_menu_items ();
-
-  XVECTOR (menu_items)->contents[menu_items_used++] = Qlambda;
-  menu_items_submenu_depth--;
-}
-
-/* Indicate boundary between left and right.  */
-
-static void
-push_left_right_boundary ()
-{
-  if (menu_items_used + 1 > menu_items_allocated)
-    grow_menu_items ();
-
-  XVECTOR (menu_items)->contents[menu_items_used++] = Qquote;
-}
-
-/* Start a new menu pane in menu_items.
-   NAME is the pane name.  PREFIX_VEC is a prefix key for this pane.  */
-
-static void
-push_menu_pane (name, prefix_vec)
-     Lisp_Object name, prefix_vec;
-{
-  if (menu_items_used + MENU_ITEMS_PANE_LENGTH > menu_items_allocated)
-    grow_menu_items ();
-
-  if (menu_items_submenu_depth == 0)
-    menu_items_n_panes++;
-  XVECTOR (menu_items)->contents[menu_items_used++] = Qt;
-  XVECTOR (menu_items)->contents[menu_items_used++] = name;
-  XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec;
-}
-
-/* Push one menu item into the current pane.  NAME is the string to
-   display.  ENABLE if non-nil means this item can be selected.  KEY
-   is the key generated by choosing this item, or nil if this item
-   doesn't really have a definition.  DEF is the definition of this
-   item.  EQUIV is the textual description of the keyboard equivalent
-   for this item (or nil if none).  TYPE is the type of this menu
-   item, one of nil, `toggle' or `radio'. */
-
-static void
-push_menu_item (name, enable, key, def, equiv, type, selected, help)
-     Lisp_Object name, enable, key, def, equiv, type, selected, help;
-{
-  if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
-    grow_menu_items ();
-
-  XVECTOR (menu_items)->contents[menu_items_used++] = name;
-  XVECTOR (menu_items)->contents[menu_items_used++] = enable;
-  XVECTOR (menu_items)->contents[menu_items_used++] = key;
-  XVECTOR (menu_items)->contents[menu_items_used++] = equiv;
-  XVECTOR (menu_items)->contents[menu_items_used++] = def;
-  XVECTOR (menu_items)->contents[menu_items_used++] = type;
-  XVECTOR (menu_items)->contents[menu_items_used++] = selected;
-  XVECTOR (menu_items)->contents[menu_items_used++] = help;
-}
-\f
-/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
-   and generate menu panes for them in menu_items.
-   If NOTREAL is nonzero,
-   don't bother really computing whether an item is enabled.  */
-
-static void
-keymap_panes (keymaps, nmaps, notreal)
-     Lisp_Object *keymaps;
-     int nmaps;
-     int notreal;
-{
-  int mapno;
-
-  init_menu_items ();
-
-  /* Loop over the given keymaps, making a pane for each map.
-     But don't make a pane that is empty--ignore that map instead.
-     P is the number of panes we have made so far.  */
-  for (mapno = 0; mapno < nmaps; mapno++)
-    single_keymap_panes (keymaps[mapno],
-                        Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10);
-
-  finish_menu_items ();
-}
-
-/* Args passed between single_keymap_panes and single_menu_item.  */
-struct skp
-  {
-     Lisp_Object pending_maps;
-     int maxdepth, notreal;
-     int notbuttons;
-  };
-
-static void single_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
-                                 void *));
-
-/* This is a recursive subroutine of keymap_panes.
-   It handles one keymap, KEYMAP.
-   The other arguments are passed along
-   or point to local variables of the previous function.
-   If NOTREAL is nonzero, only check for equivalent key bindings, don't
-   evaluate expressions in menu items and don't make any menu.
-
-   If we encounter submenus deeper than MAXDEPTH levels, ignore them.  */
-
-static void
-single_keymap_panes (keymap, pane_name, prefix, notreal, maxdepth)
-     Lisp_Object keymap;
-     Lisp_Object pane_name;
-     Lisp_Object prefix;
-     int notreal;
-     int maxdepth;
-{
-  struct skp skp;
-  struct gcpro gcpro1;
-
-  skp.pending_maps = Qnil;
-  skp.maxdepth = maxdepth;
-  skp.notreal = notreal;
-  skp.notbuttons = 0;
-
-  if (maxdepth <= 0)
-    return;
-
-  push_menu_pane (pane_name, prefix);
-
-#ifndef HAVE_BOXES
-  /* Remember index for first item in this pane so we can go back and
-     add a prefix when (if) we see the first button.  After that, notbuttons
-     is set to 0, to mark that we have seen a button and all non button
-     items need a prefix.  */
-  skp.notbuttons = menu_items_used;
-#endif
-
-  GCPRO1 (skp.pending_maps);
-  map_keymap (keymap, single_menu_item, Qnil, &skp, 1);
-  UNGCPRO;
-
-  /* Process now any submenus which want to be panes at this level.  */
-  while (CONSP (skp.pending_maps))
-    {
-      Lisp_Object elt, eltcdr, string;
-      elt = XCAR (skp.pending_maps);
-      eltcdr = XCDR (elt);
-      string = XCAR (eltcdr);
-      /* We no longer discard the @ from the beginning of the string here.
-        Instead, we do this in xmenu_show.  */
-      single_keymap_panes (Fcar (elt), string,
-                          XCDR (eltcdr), notreal, maxdepth - 1);
-      skp.pending_maps = XCDR (skp.pending_maps);
-    }
-}
-\f
-/* This is a subroutine of single_keymap_panes that handles one
-   keymap entry.
-   KEY is a key in a keymap and ITEM is its binding.
-   SKP->PENDING_MAPS_PTR is a list of keymaps waiting to be made into
-   separate panes.
-   If SKP->NOTREAL is nonzero, only check for equivalent key bindings, don't
-   evaluate expressions in menu items and don't make any menu.
-   If we encounter submenus deeper than SKP->MAXDEPTH levels, ignore them.
-   SKP->NOTBUTTONS is only used when simulating toggle boxes and radio
-   buttons.  It keeps track of if we have seen a button in this menu or
-   not.  */
-
-static void
-single_menu_item (key, item, dummy, skp_v)
-     Lisp_Object key, item, dummy;
-     void *skp_v;
-{
-  Lisp_Object map, item_string, enabled;
-  struct gcpro gcpro1, gcpro2;
-  int res;
-  struct skp *skp = skp_v;
-
-  /* Parse the menu item and leave the result in item_properties.  */
-  GCPRO2 (key, item);
-  res = parse_menu_item (item, skp->notreal, 0);
-  UNGCPRO;
-  if (!res)
-    return;                    /* Not a menu item.  */
-
-  map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];
-
-  if (skp->notreal)
-    {
-      /* We don't want to make a menu, just traverse the keymaps to
-        precompute equivalent key bindings.  */
-      if (!NILP (map))
-       single_keymap_panes (map, Qnil, key, 1, skp->maxdepth - 1);
-      return;
-    }
-
-  enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE];
-  item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];
-
-  if (!NILP (map) && SREF (item_string, 0) == '@')
-    {
-      if (!NILP (enabled))
-       /* An enabled separate pane. Remember this to handle it later.  */
-       skp->pending_maps = Fcons (Fcons (map, Fcons (item_string, key)),
-                                  skp->pending_maps);
-      return;
-    }
-
-#ifndef HAVE_BOXES
-  /* Simulate radio buttons and toggle boxes by putting a prefix in
-     front of them.  */
-  {
-    Lisp_Object prefix = Qnil;
-    Lisp_Object type = XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE];
-    if (!NILP (type))
-      {
-       Lisp_Object selected
-         = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED];
-
-       if (skp->notbuttons)
-         /* The first button. Line up previous items in this menu.  */
-         {
-           int index = skp->notbuttons; /* Index for first item this menu.  */
-           int submenu = 0;
-           Lisp_Object tem;
-           while (index < menu_items_used)
-             {
-               tem
-                 = XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME];
-               if (NILP (tem))
-                 {
-                   index++;
-                   submenu++;          /* Skip sub menu.  */
-                 }
-               else if (EQ (tem, Qlambda))
-                 {
-                   index++;
-                   submenu--;          /* End sub menu.  */
-                 }
-               else if (EQ (tem, Qt))
-                 index += 3;           /* Skip new pane marker. */
-               else if (EQ (tem, Qquote))
-                 index++;              /* Skip a left, right divider. */
-               else
-                 {
-                   if (!submenu && SREF (tem, 0) != '\0'
-                       && SREF (tem, 0) != '-')
-                     XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME]
-                       = concat2 (build_string ("    "), tem);
-                   index += MENU_ITEMS_ITEM_LENGTH;
-                 }
-             }
-           skp->notbuttons = 0;
-         }
-
-       /* Calculate prefix, if any, for this item.  */
-       if (EQ (type, QCtoggle))
-         prefix = build_string (NILP (selected) ? "[ ] " : "[X] ");
-       else if (EQ (type, QCradio))
-         prefix = build_string (NILP (selected) ? "( ) " : "(*) ");
-      }
-    /* Not a button. If we have earlier buttons, then we need a prefix.  */
-    else if (!skp->notbuttons && SREF (item_string, 0) != '\0'
-            && SREF (item_string, 0) != '-')
-      prefix = build_string ("    ");
-
-    if (!NILP (prefix))
-      item_string = concat2 (prefix, item_string);
-  }
-#endif /* not HAVE_BOXES */
-
-#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
-  if (!NILP (map))
-    /* Indicate visually that this is a submenu.  */
-    item_string = concat2 (item_string, build_string (" >"));
-#endif
-
-  push_menu_item (item_string, enabled, key,
-                 XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF],
-                 XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ],
-                 XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE],
-                 XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
-                 XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
-
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
-  /* Display a submenu using the toolkit.  */
-  if (! (NILP (map) || NILP (enabled)))
-    {
-      push_submenu_start ();
-      single_keymap_panes (map, Qnil, key, 0, skp->maxdepth - 1);
-      push_submenu_end ();
-    }
-#endif
-}
-\f
-/* Push all the panes and items of a menu described by the
-   alist-of-alists MENU.
-   This handles old-fashioned calls to x-popup-menu.  */
-
-static void
-list_of_panes (menu)
-     Lisp_Object menu;
-{
-  Lisp_Object tail;
-
-  init_menu_items ();
-
-  for (tail = menu; CONSP (tail); tail = XCDR (tail))
-    {
-      Lisp_Object elt, pane_name, pane_data;
-      elt = XCAR (tail);
-      pane_name = Fcar (elt);
-      CHECK_STRING (pane_name);
-      push_menu_pane (ENCODE_MENU_STRING (pane_name), Qnil);
-      pane_data = Fcdr (elt);
-      CHECK_CONS (pane_data);
-      list_of_items (pane_data);
-    }
-
-  finish_menu_items ();
-}
-
-/* Push the items in a single pane defined by the alist PANE.  */
-
-static void
-list_of_items (pane)
-     Lisp_Object pane;
-{
-  Lisp_Object tail, item, item1;
-
-  for (tail = pane; CONSP (tail); tail = XCDR (tail))
-    {
-      item = XCAR (tail);
-      if (STRINGP (item))
-       push_menu_item (ENCODE_MENU_STRING (item), Qnil, Qnil, Qt,
-                       Qnil, Qnil, Qnil, Qnil);
-      else if (CONSP (item))
-       {
-         item1 = XCAR (item);
-         CHECK_STRING (item1);
-         push_menu_item (ENCODE_MENU_STRING (item1), Qt, XCDR (item),
-                         Qt, Qnil, Qnil, Qnil, Qnil);
-       }
-      else
-       push_left_right_boundary ();
-
-    }
-}
-\f
 #ifdef HAVE_X_WINDOWS
 /* Return the mouse position in *X and *Y.  The coordinates are window
    relative for the edit window in frame F.
@@ -729,11 +186,8 @@ list_of_items (pane)
    for the window where the mouse is in.  This could be the menu bar,
    the scroll bar or the edit window.  Fx_popup_menu needs to be
    sure it is the edit window.  */
-static void
-mouse_position_for_popup (f, x, y)
-     FRAME_PTR f;
-     int *x;
-     int *y;
+void
+mouse_position_for_popup (FRAME_PTR f, int *x, int *y)
 {
   Window root, dummy_window;
   int dummy;
@@ -772,275 +226,6 @@ mouse_position_for_popup (f, x, y)
 
 #endif /* HAVE_X_WINDOWS */
 
-DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
-       doc: /* Pop up a deck-of-cards menu and return user's selection.
-POSITION is a position specification.  This is either a mouse button event
-or a list ((XOFFSET YOFFSET) WINDOW)
-where XOFFSET and YOFFSET are positions in pixels from the top left
-corner of WINDOW.  (WINDOW may be a window or a frame object.)
-This controls the position of the top left of the menu as a whole.
-If POSITION is t, it means to use the current mouse position.
-
-MENU is a specifier for a menu.  For the simplest case, MENU is a keymap.
-The menu items come from key bindings that have a menu string as well as
-a definition; actually, the "definition" in such a key binding looks like
-\(STRING . REAL-DEFINITION).  To give the menu a title, put a string into
-the keymap as a top-level element.
-
-If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.
-Otherwise, REAL-DEFINITION should be a valid key binding definition.
-
-You can also use a list of keymaps as MENU.
-  Then each keymap makes a separate pane.
-
-When MENU is a keymap or a list of keymaps, the return value is the
-list of events corresponding to the user's choice. Note that
-`x-popup-menu' does not actually execute the command bound to that
-sequence of events.
-
-Alternatively, you can specify a menu of multiple panes
-  with a list of the form (TITLE PANE1 PANE2...),
-where each pane is a list of form (TITLE ITEM1 ITEM2...).
-Each ITEM is normally a cons cell (STRING . VALUE);
-but a string can appear as an item--that makes a nonselectable line
-in the menu.
-With this form of menu, the return value is VALUE from the chosen item.
-
-If POSITION is nil, don't display the menu at all, just precalculate the
-cached information about equivalent key sequences.
-
-If the user gets rid of the menu without making a valid choice, for
-instance by clicking the mouse away from a valid choice or by typing
-keyboard input, then this normally results in a quit and
-`x-popup-menu' does not return.  But if POSITION is a mouse button
-event (indicating that the user invoked the menu with the mouse) then
-no quit occurs and `x-popup-menu' returns nil.  */)
-     (position, menu)
-     Lisp_Object position, menu;
-{
-  Lisp_Object keymap, tem;
-  int xpos = 0, ypos = 0;
-  Lisp_Object title;
-  char *error_name = NULL;
-  Lisp_Object selection = Qnil;
-  FRAME_PTR f = NULL;
-  Lisp_Object x, y, window;
-  int keymaps = 0;
-  int for_click = 0;
-  int specpdl_count = SPECPDL_INDEX ();
-  struct gcpro gcpro1;
-
-#ifdef HAVE_MENUS
-  if (! NILP (position))
-    {
-      int get_current_pos_p = 0;
-      check_x ();
-
-      /* Decode the first argument: find the window and the coordinates.  */
-      if (EQ (position, Qt)
-         || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
-                                  || EQ (XCAR (position), Qtool_bar))))
-       {
-          get_current_pos_p = 1;
-        }
-      else
-       {
-         tem = Fcar (position);
-         if (CONSP (tem))
-           {
-             window = Fcar (Fcdr (position));
-             x = XCAR (tem);
-             y = Fcar (XCDR (tem));
-           }
-         else
-           {
-             for_click = 1;
-             tem = Fcar (Fcdr (position));  /* EVENT_START (position) */
-             window = Fcar (tem);           /* POSN_WINDOW (tem) */
-             tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
-             x = Fcar (tem);
-             y = Fcdr (tem);
-           }
-
-          /* If a click happens in an external tool bar or a detached
-             tool bar, x and y is NIL.  In that case, use the current
-             mouse position.  This happens for the help button in the
-             tool bar.  Ideally popup-menu should pass NIL to
-             this function, but it doesn't.  */
-          if (NILP (x) && NILP (y))
-            get_current_pos_p = 1;
-       }
-
-      if (get_current_pos_p)
-        {
-         /* Use the mouse's current position.  */
-         FRAME_PTR new_f = SELECTED_FRAME ();
-#ifdef HAVE_X_WINDOWS
-          /* Can't use mouse_position_hook for X since it returns
-             coordinates relative to the window the mouse is in,
-             we need coordinates relative to the edit widget always.  */
-          if (new_f != 0)
-            {
-              int cur_x, cur_y;
-
-              mouse_position_for_popup (new_f, &cur_x, &cur_y);
-              /* cur_x/y may be negative, so use make_number.  */
-              x = make_number (cur_x);
-              y = make_number (cur_y);
-            }
-
-#else /* not HAVE_X_WINDOWS */
-         Lisp_Object bar_window;
-         enum scroll_bar_part part;
-         unsigned long time;
-
-         if (mouse_position_hook)
-           (*mouse_position_hook) (&new_f, 1, &bar_window,
-                                   &part, &x, &y, &time);
-#endif /* not HAVE_X_WINDOWS */
-
-         if (new_f != 0)
-           XSETFRAME (window, new_f);
-         else
-           {
-             window = selected_window;
-             XSETFASTINT (x, 0);
-             XSETFASTINT (y, 0);
-           }
-       }
-
-      CHECK_NUMBER (x);
-      CHECK_NUMBER (y);
-
-      /* Decode where to put the menu.  */
-
-      if (FRAMEP (window))
-       {
-         f = XFRAME (window);
-         xpos = 0;
-         ypos = 0;
-       }
-      else if (WINDOWP (window))
-       {
-         CHECK_LIVE_WINDOW (window);
-         f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
-
-         xpos = WINDOW_LEFT_EDGE_X (XWINDOW (window));
-         ypos = WINDOW_TOP_EDGE_Y (XWINDOW (window));
-       }
-      else
-       /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
-          but I don't want to make one now.  */
-       CHECK_WINDOW (window);
-
-      xpos += XINT (x);
-      ypos += XINT (y);
-
-      if (! FRAME_X_P (f))
-        error ("Can not put X menu on non-X terminal");
-
-      XSETFRAME (Vmenu_updating_frame, f);
-    }
-  else
-    Vmenu_updating_frame = Qnil;
-#endif /* HAVE_MENUS */
-
-  record_unwind_protect (unuse_menu_items, Qnil);
-  title = Qnil;
-  GCPRO1 (title);
-
-  /* Decode the menu items from what was specified.  */
-
-  keymap = get_keymap (menu, 0, 0);
-  if (CONSP (keymap))
-    {
-      /* We were given a keymap.  Extract menu info from the keymap.  */
-      Lisp_Object prompt;
-
-      /* Extract the detailed info to make one pane.  */
-      keymap_panes (&menu, 1, NILP (position));
-
-      /* Search for a string appearing directly as an element of the keymap.
-        That string is the title of the menu.  */
-      prompt = Fkeymap_prompt (keymap);
-      if (NILP (title) && !NILP (prompt))
-       title = prompt;
-
-      /* Make that be the pane title of the first pane.  */
-      if (!NILP (prompt) && menu_items_n_panes >= 0)
-       XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = prompt;
-
-      keymaps = 1;
-    }
-  else if (CONSP (menu) && KEYMAPP (XCAR (menu)))
-    {
-      /* We were given a list of keymaps.  */
-      int nmaps = XFASTINT (Flength (menu));
-      Lisp_Object *maps
-       = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
-      int i;
-
-      title = Qnil;
-
-      /* The first keymap that has a prompt string
-        supplies the menu title.  */
-      for (tem = menu, i = 0; CONSP (tem); tem = XCDR (tem))
-       {
-         Lisp_Object prompt;
-
-         maps[i++] = keymap = get_keymap (XCAR (tem), 1, 0);
-
-         prompt = Fkeymap_prompt (keymap);
-         if (NILP (title) && !NILP (prompt))
-           title = prompt;
-       }
-
-      /* Extract the detailed info to make one pane.  */
-      keymap_panes (maps, nmaps, NILP (position));
-
-      /* Make the title be the pane title of the first pane.  */
-      if (!NILP (title) && menu_items_n_panes >= 0)
-       XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title;
-
-      keymaps = 1;
-    }
-  else
-    {
-      /* We were given an old-fashioned menu.  */
-      title = Fcar (menu);
-      CHECK_STRING (title);
-
-      list_of_panes (Fcdr (menu));
-
-      keymaps = 0;
-    }
-
-  unbind_to (specpdl_count, Qnil);
-
-  if (NILP (position))
-    {
-      discard_menu_items ();
-      UNGCPRO;
-      return Qnil;
-    }
-
-#ifdef HAVE_MENUS
-  /* Display them in a menu.  */
-  BLOCK_INPUT;
-
-  selection = xmenu_show (f, xpos, ypos, for_click,
-                         keymaps, title, &error_name);
-  UNBLOCK_INPUT;
-
-  discard_menu_items ();
-
-  UNGCPRO;
-#endif /* HAVE_MENUS */
-
-  if (error_name) error (error_name);
-  return selection;
-}
-
 #ifdef HAVE_MENUS
 
 DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
@@ -1066,8 +251,7 @@ otherwise it is "Question".
 If the user gets rid of the dialog box without making a valid choice,
 for instance using the window manager, then this produces a quit and
 `x-popup-dialog' does not return.  */)
-     (position, contents, header)
-     Lisp_Object position, contents, header;
+  (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
 {
   FRAME_PTR f = NULL;
   Lisp_Object window;
@@ -1127,8 +311,19 @@ for instance using the window manager, then this produces a quit and
        but I don't want to make one now.  */
     CHECK_WINDOW (window);
 
-  if (! FRAME_X_P (f))
-    error ("Can not put X dialog on non-X terminal");
+  if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f))
+    error ("Can not put X dialog on this terminal");
+
+  /* Force a redisplay before showing the dialog.  If a frame is created
+     just before showing the dialog, its contents may not have been fully
+     drawn, as this depends on timing of events from the X server.  Redisplay
+     is not done when a dialog is shown.  If redisplay could be done in the
+     X event loop (i.e. the X event loop does not run in a signal handler)
+     this would not be needed.
+
+     Do this before creating the widget value that points to Lisp
+     string contents, because Fredisplay may GC and relocate them.  */
+  Fredisplay (Qt);
 
 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
   /* Display a menu with these alternatives
@@ -1183,8 +378,7 @@ for instance using the window manager, then this produces a quit and
 /* Set menu_items_inuse so no other popup menu or dialog is created.  */
 
 void
-x_menu_set_in_use (in_use)
-     int in_use;
+x_menu_set_in_use (int in_use)
 {
   menu_items_inuse = in_use ? Qt : Qnil;
   popup_activated_flag = in_use;
@@ -1199,8 +393,6 @@ x_menu_set_in_use (in_use)
 void
 x_menu_wait_for_event (void *data)
 {
-  extern EMACS_TIME timer_check P_ ((int));
-
   /* Another way to do this is to register a timer callback, that can be
      done in GTK and Xt.  But we have to do it like this when using only X
      anyway, and with callbacks we would have three variants for timer handling
@@ -1216,7 +408,7 @@ x_menu_wait_for_event (void *data)
 #endif
          )
     {
-      EMACS_TIME next_time = timer_check (1);
+      EMACS_TIME next_time = timer_check (1), *ntp;
       long secs = EMACS_SECS (next_time);
       long usecs = EMACS_USECS (next_time);
       SELECT_TYPE read_fds;
@@ -1229,17 +421,15 @@ x_menu_wait_for_event (void *data)
           int fd = ConnectionNumber (dpyinfo->display);
           FD_SET (fd, &read_fds);
           if (fd > n) n = fd;
+          XFlush (dpyinfo->display);
         }
 
-      if (secs < 0 || (secs == 0 && usecs == 0))
-        {
-          /* Sometimes timer_check returns -1 (no timers) even if there are
-             timers.  So do a timeout anyway.  */
-          EMACS_SET_SECS (next_time, 1);
-          EMACS_SET_USECS (next_time, 0);
-        }
+      if (secs < 0 && usecs < 0)
+        ntp = 0;
+      else
+        ntp = &next_time;
 
-      select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, &next_time);
+      select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp);
     }
 }
 #endif /* ! MSDOS */
@@ -1257,11 +447,7 @@ x_menu_wait_for_event (void *data)
    with BLOCK_INPUT, UNBLOCK_INPUT wrappers.  */
 
 static void
-popup_get_selection (initial_event, dpyinfo, id, do_timers)
-     XEvent *initial_event;
-     struct x_display_info *dpyinfo;
-     LWLIB_ID id;
-     int do_timers;
+popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo, LWLIB_ID id, int do_timers)
 {
   XEvent event;
 
@@ -1318,8 +504,7 @@ arrow keys, select a menu entry with the return key or cancel with the
 escape key.  If FRAME has no menu bar this function does nothing.
 
 If FRAME is nil or not given, use the selected frame.  */)
-     (frame)
-     Lisp_Object frame;
+  (Lisp_Object frame)
 {
   XEvent ev;
   FRAME_PTR f = check_x_frame (frame);
@@ -1397,8 +582,7 @@ arrow keys, select a menu entry with the return key or cancel with the
 escape key.  If FRAME has no menu bar this function does nothing.
 
 If FRAME is nil or not given, use the selected frame.  */)
-     (frame)
-     Lisp_Object frame;
+  (Lisp_Object frame)
 {
   GtkWidget *menubar;
   FRAME_PTR f;
@@ -1418,11 +602,12 @@ If FRAME is nil or not given, use the selected frame.  */)
       /* Activate the first menu.  */
       GList *children = gtk_container_get_children (GTK_CONTAINER (menubar));
 
-      gtk_menu_shell_select_item (GTK_MENU_SHELL (menubar),
-                                  GTK_WIDGET (children->data));
-
-      popup_activated_flag = 1;
-      g_list_free (children);
+      if (children)
+        {
+          g_signal_emit_by_name (children->data, "activate_item");
+          popup_activated_flag = 1;
+          g_list_free (children);
+        }
     }
   UNBLOCK_INPUT;
 
@@ -1433,9 +618,7 @@ If FRAME is nil or not given, use the selected frame.  */)
    Used for popup menus and dialogs. */
 
 static void
-popup_widget_loop (do_timers, widget)
-     int do_timers;
-     GtkWidget *widget;
+popup_widget_loop (int do_timers, GtkWidget *widget)
 {
   ++popup_activated_flag;
 
@@ -1463,8 +646,7 @@ popup_widget_loop (do_timers, widget)
    execute Lisp code.  */
 
 void
-x_activate_menubar (f)
-     FRAME_PTR f;
+x_activate_menubar (FRAME_PTR f)
 {
   if (! FRAME_X_P (f))
     abort ();
@@ -1480,18 +662,22 @@ x_activate_menubar (f)
 
   set_frame_menubar (f, 0, 1);
   BLOCK_INPUT;
+  popup_activated_flag = 1;
 #ifdef USE_GTK
+  /* If we click outside any menu item, the menu bar still grabs.
+     So we send Press and the Release.  If outside, grab is released.
+     If on a menu item, it is popped up normally.
+     PutBack is like a stack, so we put back in reverse order.  */
+  f->output_data.x->saved_menu_event->type = ButtonRelease;
+  XPutBackEvent (f->output_data.x->display_info->display,
+                 f->output_data.x->saved_menu_event);
+  f->output_data.x->saved_menu_event->type = ButtonPress;
   XPutBackEvent (f->output_data.x->display_info->display,
                  f->output_data.x->saved_menu_event);
-  popup_activated_flag = 1;
 #else
   XtDispatchEvent (f->output_data.x->saved_menu_event);
 #endif
   UNBLOCK_INPUT;
-#ifdef USE_MOTIF
-  if (f->output_data.x->saved_menu_event->type == ButtonRelease)
-    pending_menu_activation = 1;
-#endif
 
   /* Ignore this if we get it a second time.  */
   f->output_data.x->saved_menu_event->type = 0;
@@ -1502,10 +688,7 @@ x_activate_menubar (f)
 
 #ifndef USE_GTK
 static void
-popup_activate_callback (widget, id, client_data)
-     Widget widget;
-     LWLIB_ID id;
-     XtPointer client_data;
+popup_activate_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
 {
   popup_activated_flag = 1;
 #ifdef USE_X_TOOLKIT
@@ -1519,18 +702,13 @@ popup_activate_callback (widget, id, client_data)
 
 #ifdef USE_GTK
 static void
-popup_deactivate_callback (widget, client_data)
-     GtkWidget *widget;
-     gpointer client_data;
+popup_deactivate_callback (GtkWidget *widget, gpointer client_data)
 {
   popup_activated_flag = 0;
 }
 #else
 static void
-popup_deactivate_callback (widget, id, client_data)
-     Widget widget;
-     LWLIB_ID id;
-     XtPointer client_data;
+popup_deactivate_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
 {
   popup_activated_flag = 0;
 }
@@ -1541,10 +719,7 @@ popup_deactivate_callback (widget, id, client_data)
    for that widget.
    F is the frame if known, or NULL if not known.  */
 static void
-show_help_event (f, widget, help)
-     FRAME_PTR f;
-     xt_or_gtk_widget widget;
-     Lisp_Object help;
+show_help_event (FRAME_PTR f, xt_or_gtk_widget widget, Lisp_Object help)
 {
   Lisp_Object frame;
 
@@ -1582,9 +757,7 @@ show_help_event (f, widget, help)
 
 #ifdef USE_GTK
 void
-menu_highlight_callback (widget, call_data)
-     GtkWidget *widget;
-     gpointer call_data;
+menu_highlight_callback (GtkWidget *widget, gpointer call_data)
 {
   xg_menu_item_cb_data *cb_data;
   Lisp_Object help;
@@ -1603,112 +776,21 @@ menu_highlight_callback (widget, call_data)
 }
 #else
 void
-menu_highlight_callback (widget, id, call_data)
-     Widget widget;
-     LWLIB_ID id;
-     void *call_data;
+menu_highlight_callback (Widget widget, LWLIB_ID id, void *call_data)
 {
   struct frame *f;
   Lisp_Object help;
 
-  widget_value *wv = (widget_value *) call_data;
-
-  help = wv ? wv->help : Qnil;
-
-  /* Determine the frame for the help event.  */
-  f = menubar_id_to_frame (id);
-
-  show_help_event (f, widget, help);
-}
-#endif
-
-/* Find the menu selection and store it in the keyboard buffer.
-   F is the frame the menu is on.
-   MENU_BAR_ITEMS_USED is the length of VECTOR.
-   VECTOR is an array of menu events for the whole menu.  */
-
-static void
-find_and_call_menu_selection (f, menu_bar_items_used, vector, client_data)
-     FRAME_PTR f;
-     EMACS_INT menu_bar_items_used;
-     Lisp_Object vector;
-     void *client_data;
-{
-  Lisp_Object prefix, entry;
-  Lisp_Object *subprefix_stack;
-  int submenu_depth = 0;
-  int i;
-
-  entry = Qnil;
-  subprefix_stack = (Lisp_Object *) alloca (menu_bar_items_used * sizeof (Lisp_Object));
-  prefix = Qnil;
-  i = 0;
-
-  while (i < menu_bar_items_used)
-    {
-      if (EQ (XVECTOR (vector)->contents[i], Qnil))
-       {
-         subprefix_stack[submenu_depth++] = prefix;
-         prefix = entry;
-         i++;
-       }
-      else if (EQ (XVECTOR (vector)->contents[i], Qlambda))
-       {
-         prefix = subprefix_stack[--submenu_depth];
-         i++;
-       }
-      else if (EQ (XVECTOR (vector)->contents[i], Qt))
-       {
-         prefix = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX];
-         i += MENU_ITEMS_PANE_LENGTH;
-       }
-      else
-       {
-         entry = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE];
-         /* The EMACS_INT cast avoids a warning.  There's no problem
-            as long as pointers have enough bits to hold small integers.  */
-         if ((int) (EMACS_INT) client_data == i)
-           {
-             int j;
-             struct input_event buf;
-             Lisp_Object frame;
-             EVENT_INIT (buf);
-
-             XSETFRAME (frame, f);
-             buf.kind = MENU_BAR_EVENT;
-             buf.frame_or_window = frame;
-             buf.arg = frame;
-             kbd_buffer_store_event (&buf);
-
-             for (j = 0; j < submenu_depth; j++)
-               if (!NILP (subprefix_stack[j]))
-                 {
-                   buf.kind = MENU_BAR_EVENT;
-                   buf.frame_or_window = frame;
-                   buf.arg = subprefix_stack[j];
-                   kbd_buffer_store_event (&buf);
-                 }
-
-             if (!NILP (prefix))
-               {
-                 buf.kind = MENU_BAR_EVENT;
-                 buf.frame_or_window = frame;
-                 buf.arg = prefix;
-                 kbd_buffer_store_event (&buf);
-               }
+  widget_value *wv = (widget_value *) call_data;
 
-             buf.kind = MENU_BAR_EVENT;
-             buf.frame_or_window = frame;
-             buf.arg = entry;
-             kbd_buffer_store_event (&buf);
+  help = wv ? wv->help : Qnil;
 
-             return;
-           }
-         i += MENU_ITEMS_ITEM_LENGTH;
-       }
-    }
-}
+  /* Determine the frame for the help event.  */
+  f = menubar_id_to_frame (id);
 
+  show_help_event (f, widget, help);
+}
+#endif
 
 #ifdef USE_GTK
 /* Gtk calls callbacks just because we tell it what item should be
@@ -1722,9 +804,7 @@ static int xg_crazy_callback_abort;
    Figure out what the user chose
    and put the appropriate events into the keyboard buffer.  */
 static void
-menubar_selection_callback (widget, client_data)
-     GtkWidget *widget;
-     gpointer client_data;
+menubar_selection_callback (GtkWidget *widget, gpointer client_data)
 {
   xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
 
@@ -1767,10 +847,7 @@ menubar_selection_callback (widget, client_data)
    Figure out what the user chose
    and put the appropriate events into the keyboard buffer.  */
 static void
-menubar_selection_callback (widget, id, client_data)
-     Widget widget;
-     LWLIB_ID id;
-     XtPointer client_data;
+menubar_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
 {
   FRAME_PTR f;
 
@@ -1781,324 +858,12 @@ menubar_selection_callback (widget, id, client_data)
                                 f->menu_bar_vector, client_data);
 }
 #endif /* not USE_GTK */
-
-/* Allocate a widget_value, blocking input.  */
-
-widget_value *
-xmalloc_widget_value ()
-{
-  widget_value *value;
-
-  BLOCK_INPUT;
-  value = malloc_widget_value ();
-  UNBLOCK_INPUT;
-
-  return value;
-}
-
-/* This recursively calls free_widget_value on the tree of widgets.
-   It must free all data that was malloc'ed for these widget_values.
-   In Emacs, many slots are pointers into the data of Lisp_Strings, and
-   must be left alone.  */
-
-void
-free_menubar_widget_value_tree (wv)
-     widget_value *wv;
-{
-  if (! wv) return;
-
-  wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
-
-  if (wv->contents && (wv->contents != (widget_value*)1))
-    {
-      free_menubar_widget_value_tree (wv->contents);
-      wv->contents = (widget_value *) 0xDEADBEEF;
-    }
-  if (wv->next)
-    {
-      free_menubar_widget_value_tree (wv->next);
-      wv->next = (widget_value *) 0xDEADBEEF;
-    }
-  BLOCK_INPUT;
-  free_widget_value (wv);
-  UNBLOCK_INPUT;
-}
-\f
-/* Set up data in menu_items for a menu bar item
-   whose event type is ITEM_KEY (with string ITEM_NAME)
-   and whose contents come from the list of keymaps MAPS.  */
-
-static int
-parse_single_submenu (item_key, item_name, maps)
-     Lisp_Object item_key, item_name, maps;
-{
-  Lisp_Object length;
-  int len;
-  Lisp_Object *mapvec;
-  int i;
-  int top_level_items = 0;
-
-  length = Flength (maps);
-  len = XINT (length);
-
-  /* Convert the list MAPS into a vector MAPVEC.  */
-  mapvec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-  for (i = 0; i < len; i++)
-    {
-      mapvec[i] = Fcar (maps);
-      maps = Fcdr (maps);
-    }
-
-  /* Loop over the given keymaps, making a pane for each map.
-     But don't make a pane that is empty--ignore that map instead.  */
-  for (i = 0; i < len; i++)
-    {
-      if (!KEYMAPP (mapvec[i]))
-       {
-         /* Here we have a command at top level in the menu bar
-            as opposed to a submenu.  */
-         top_level_items = 1;
-         push_menu_pane (Qnil, Qnil);
-         push_menu_item (item_name, Qt, item_key, mapvec[i],
-                         Qnil, Qnil, Qnil, Qnil);
-       }
-      else
-       {
-         Lisp_Object prompt;
-         prompt = Fkeymap_prompt (mapvec[i]);
-         single_keymap_panes (mapvec[i],
-                              !NILP (prompt) ? prompt : item_name,
-                              item_key, 0, 10);
-       }
-    }
-
-  return top_level_items;
-}
-
-/* Create a tree of widget_value objects
-   representing the panes and items
-   in menu_items starting at index START, up to index END.  */
-
-static widget_value *
-digest_single_submenu (start, end, top_level_items)
-     int start, end, top_level_items;
-{
-  widget_value *wv, *prev_wv, *save_wv, *first_wv;
-  int i;
-  int submenu_depth = 0;
-  widget_value **submenu_stack;
-  int panes_seen = 0;
-
-  submenu_stack
-    = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
-  wv = xmalloc_widget_value ();
-  wv->name = "menu";
-  wv->value = 0;
-  wv->enabled = 1;
-  wv->button_type = BUTTON_TYPE_NONE;
-  wv->help = Qnil;
-  first_wv = wv;
-  save_wv = 0;
-  prev_wv = 0;
-
-  /* Loop over all panes and items made by the preceding call
-     to parse_single_submenu and construct a tree of widget_value objects.
-     Ignore the panes and items used by previous calls to
-     digest_single_submenu, even though those are also in menu_items.  */
-  i = start;
-  while (i < end)
-    {
-      if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
-       {
-         submenu_stack[submenu_depth++] = save_wv;
-         save_wv = prev_wv;
-         prev_wv = 0;
-         i++;
-       }
-      else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
-       {
-         prev_wv = save_wv;
-         save_wv = submenu_stack[--submenu_depth];
-         i++;
-       }
-      else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
-              && submenu_depth != 0)
-       i += MENU_ITEMS_PANE_LENGTH;
-      /* Ignore a nil in the item list.
-        It's meaningful only for dialog boxes.  */
-      else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
-       i += 1;
-      else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
-       {
-         /* Create a new pane.  */
-         Lisp_Object pane_name, prefix;
-         char *pane_string;
-
-         panes_seen++;
-
-         pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
-         prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
-
-#ifndef HAVE_MULTILINGUAL_MENU
-         if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
-           {
-             pane_name = ENCODE_MENU_STRING (pane_name);
-             ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
-           }
-#endif
-         pane_string = (NILP (pane_name)
-                        ? "" : (char *) SDATA (pane_name));
-         /* If there is just one top-level pane, put all its items directly
-            under the top-level menu.  */
-         if (menu_items_n_panes == 1)
-           pane_string = "";
-
-         /* If the pane has a meaningful name,
-            make the pane a top-level menu item
-            with its items as a submenu beneath it.  */
-         if (strcmp (pane_string, ""))
-           {
-             wv = xmalloc_widget_value ();
-             if (save_wv)
-               save_wv->next = wv;
-             else
-               first_wv->contents = wv;
-             wv->lname = pane_name;
-              /* Set value to 1 so update_submenu_strings can handle '@'  */
-             wv->value = (char *)1;
-             wv->enabled = 1;
-             wv->button_type = BUTTON_TYPE_NONE;
-             wv->help = Qnil;
-             save_wv = wv;
-           }
-         else
-           save_wv = first_wv;
-
-         prev_wv = 0;
-         i += MENU_ITEMS_PANE_LENGTH;
-       }
-      else
-       {
-         /* Create a new item within current pane.  */
-         Lisp_Object item_name, enable, descrip, def, type, selected;
-         Lisp_Object help;
-
-         /* All items should be contained in panes.  */
-         if (panes_seen == 0)
-           abort ();
-
-         item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
-         enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
-         descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
-         def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
-         type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
-         selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
-         help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
-
-#ifndef HAVE_MULTILINGUAL_MENU
-          if (STRING_MULTIBYTE (item_name))
-           {
-             item_name = ENCODE_MENU_STRING (item_name);
-             ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
-           }
-
-          if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
-           {
-             descrip = ENCODE_MENU_STRING (descrip);
-             ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
-           }
-#endif /* not HAVE_MULTILINGUAL_MENU */
-
-         wv = xmalloc_widget_value ();
-         if (prev_wv)
-           prev_wv->next = wv;
-         else
-           save_wv->contents = wv;
-
-         wv->lname = item_name;
-         if (!NILP (descrip))
-           wv->lkey = descrip;
-         wv->value = 0;
-         /* The EMACS_INT cast avoids a warning.  There's no problem
-            as long as pointers have enough bits to hold small integers.  */
-         wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0);
-         wv->enabled = !NILP (enable);
-
-         if (NILP (type))
-           wv->button_type = BUTTON_TYPE_NONE;
-         else if (EQ (type, QCradio))
-           wv->button_type = BUTTON_TYPE_RADIO;
-         else if (EQ (type, QCtoggle))
-           wv->button_type = BUTTON_TYPE_TOGGLE;
-         else
-           abort ();
-
-         wv->selected = !NILP (selected);
-         if (! STRINGP (help))
-           help = Qnil;
-
-         wv->help = help;
-
-         prev_wv = wv;
-
-         i += MENU_ITEMS_ITEM_LENGTH;
-       }
-    }
-
-  /* If we have just one "menu item"
-     that was originally a button, return it by itself.  */
-  if (top_level_items && first_wv->contents && first_wv->contents->next == 0)
-    {
-      wv = first_wv->contents;
-      free_widget_value (first_wv);
-      return wv;
-    }
-
-  return first_wv;
-}
-
-/* Walk through the widget_value tree starting at FIRST_WV and update
-   the char * pointers from the corresponding lisp values.
-   We do this after building the whole tree, since GC may happen while the
-   tree is constructed, and small strings are relocated.  So we must wait
-   until no GC can happen before storing pointers into lisp values.  */
-static void
-update_submenu_strings (first_wv)
-     widget_value *first_wv;
-{
-  widget_value *wv;
-
-  for (wv = first_wv; wv; wv = wv->next)
-    {
-      if (STRINGP (wv->lname))
-        {
-          wv->name = (char *) SDATA (wv->lname);
-
-          /* Ignore the @ that means "separate pane".
-             This is a kludge, but this isn't worth more time.  */
-          if (wv->value == (char *)1)
-            {
-              if (wv->name[0] == '@')
-               wv->name++;
-              wv->value = 0;
-            }
-        }
-
-      if (STRINGP (wv->lkey))
-        wv->key = (char *) SDATA (wv->lkey);
-
-      if (wv->contents)
-        update_submenu_strings (wv->contents);
-    }
-}
-
 \f
 /* Recompute all the widgets of frame F, when the menu bar has been
    changed.  Value is non-zero if widgets were updated.  */
 
 static int
-update_frame_menubar (f)
-     FRAME_PTR f;
+update_frame_menubar (FRAME_PTR f)
 {
 #ifdef USE_GTK
   return xg_update_frame_menubar (f);
@@ -2146,15 +911,48 @@ update_frame_menubar (f)
   return 1;
 }
 
+#ifdef USE_LUCID
+static void
+apply_systemfont_to_dialog (Widget w)
+{
+  const char *fn = xsettings_get_system_normal_font ();
+  if (fn) 
+    {
+      XrmDatabase db = XtDatabase (XtDisplay (w));
+      if (db)
+        XrmPutStringResource (&db, "*dialog.faceName", fn);
+    }
+}
+
+static void
+apply_systemfont_to_menu (Widget w)
+{
+  const char *fn = xsettings_get_system_normal_font ();
+  int defflt;
+
+  if (!fn) return;
+
+  if (XtIsShell (w)) /* popup menu */
+    {
+      Widget *childs = NULL;
+
+      XtVaGetValues (w, XtNchildren, &childs, NULL);
+      if (*childs) w = *childs;
+    }
+
+  /* Only use system font if the default is used for the menu.  */
+  XtVaGetValues (w, XtNdefaultFace, &defflt, NULL);
+  if (defflt)
+    XtVaSetValues (w, XtNfaceName, fn, NULL);
+}
+#endif
+
 /* Set the contents of the menubar widgets of frame F.
    The argument FIRST_TIME is currently ignored;
    it is set the first time this is called, from initialize_frame_menubar.  */
 
 void
-set_frame_menubar (f, first_time, deep_p)
-     FRAME_PTR f;
-     int first_time;
-     int deep_p;
+set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
 {
   xt_or_gtk_widget menubar_widget;
 #ifdef USE_X_TOOLKIT
@@ -2181,8 +979,6 @@ set_frame_menubar (f, first_time, deep_p)
 
   if (! menubar_widget)
     deep_p = 1;
-  else if (pending_menu_activation && !deep_p)
-    deep_p = 1;
   /* Make the first call for any given frame always go deep.  */
   else if (!f->output_data.x->saved_menu_event && !deep_p)
     {
@@ -2243,8 +1039,8 @@ set_frame_menubar (f, first_time, deep_p)
 
       /* Save the frame's previous menu bar contents data.  */
       if (previous_menu_items_used)
-       bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
-              previous_menu_items_used * sizeof (Lisp_Object));
+       memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
+               previous_menu_items_used * sizeof (Lisp_Object));
 
       /* Fill in menu_items with the current menu bar contents.
         This can evaluate Lisp code.  */
@@ -2332,8 +1128,7 @@ set_frame_menubar (f, first_time, deep_p)
       f->menu_bar_vector = menu_items;
       f->menu_bar_items_used = menu_items_used;
 
-      /* This calls restore_menu_items to restore menu_items, etc.,
-        as they were outside.  */
+      /* This undoes save_menu_items.  */
       unbind_to (specpdl_count, Qnil);
 
       /* Now GC cannot happen during the lifetime of the widget_value,
@@ -2459,17 +1254,26 @@ set_frame_menubar (f, first_time, deep_p)
 
       /* Make menu pop down on C-g.  */
       XtOverrideTranslations (menubar_widget, override);
+#ifdef USE_LUCID
+      apply_systemfont_to_menu (menubar_widget);
+#endif
     }
 
   {
-    int menubar_size
+    int menubar_size;
+    if (f->output_data.x->menubar_widget)
+      XtRealizeWidget (f->output_data.x->menubar_widget);
+
+    menubar_size
       = (f->output_data.x->menubar_widget
         ? (f->output_data.x->menubar_widget->core.height
            + f->output_data.x->menubar_widget->core.border_width)
         : 0);
 
-#if 0 /* Experimentally, we now get the right results
-        for -geometry -0-0 without this.  24 Aug 96, rms.  */
+#if 1 /* Experimentally, we now get the right results
+        for -geometry -0-0 without this.  24 Aug 96, rms.
+         Maybe so, but the menu bar size is missing the pixels so the
+         WM size hints are off by these pixels.  Jan D, oct 2009.  */
 #ifdef USE_LUCID
     if (FRAME_EXTERNAL_MENU_BAR (f))
       {
@@ -2479,7 +1283,7 @@ set_frame_menubar (f, first_time, deep_p)
         menubar_size += ibw;
       }
 #endif /* USE_LUCID */
-#endif /* 0 */
+#endif /* 1 */
 
     f->output_data.x->menubar_height = menubar_size;
   }
@@ -2501,8 +1305,7 @@ set_frame_menubar (f, first_time, deep_p)
    is visible.  */
 
 void
-initialize_frame_menubar (f)
-     FRAME_PTR f;
+initialize_frame_menubar (FRAME_PTR f)
 {
   /* This function is called before the first chance to redisplay
      the frame.  It has to be, so the frame will have the right size.  */
@@ -2517,8 +1320,7 @@ initialize_frame_menubar (f)
 
 #ifndef USE_GTK
 void
-free_frame_menubar (f)
-     FRAME_PTR f;
+free_frame_menubar (FRAME_PTR f)
 {
   Widget menubar_widget;
 
@@ -2561,7 +1363,7 @@ free_frame_menubar (f)
            XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
        }
 #endif
-
+      x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
       UNBLOCK_INPUT;
     }
 }
@@ -2612,17 +1414,13 @@ struct next_popup_x_y
 
    Here only X and Y are used.  */
 static void
-menu_position_func (menu, x, y, push_in, user_data)
-     GtkMenu *menu;
-     gint *x;
-     gint *y;
-     gboolean *push_in;
-     gpointer user_data;
+menu_position_func (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data)
 {
   struct next_popup_x_y* data = (struct next_popup_x_y*)user_data;
   GtkRequisition req;
-  int disp_width = FRAME_X_DISPLAY_INFO (data->f)->width;
-  int disp_height = FRAME_X_DISPLAY_INFO (data->f)->height;
+  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (data->f);
+  int disp_width = x_display_pixel_width (dpyinfo);
+  int disp_height = x_display_pixel_height (dpyinfo);
 
   *x = data->x;
   *y = data->y;
@@ -2637,9 +1435,7 @@ menu_position_func (menu, x, y, push_in, user_data)
 }
 
 static void
-popup_selection_callback (widget, client_data)
-     GtkWidget *widget;
-     gpointer client_data;
+popup_selection_callback (GtkWidget *widget, gpointer client_data)
 {
   xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
 
@@ -2648,8 +1444,7 @@ popup_selection_callback (widget, client_data)
 }
 
 static Lisp_Object
-pop_down_menu (arg)
-     Lisp_Object arg;
+pop_down_menu (Lisp_Object arg)
 {
   struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
 
@@ -2664,12 +1459,7 @@ pop_down_menu (arg)
    menu pops down.
    menu_item_selection will be set to the selection.  */
 static void
-create_and_show_popup_menu (f, first_wv, x, y, for_click)
-     FRAME_PTR f;
-     widget_value *first_wv;
-     int x;
-     int y;
-     int for_click;
+create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y, int for_click, EMACS_UINT timestamp)
 {
   int i;
   GtkWidget *menu;
@@ -2711,11 +1501,13 @@ create_and_show_popup_menu (f, first_wv, x, y, for_click)
 
   /* Display the menu.  */
   gtk_widget_show_all (menu);
-  gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);
+
+  gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i,
+                 timestamp > 0 ? timestamp : gtk_get_current_event_time());
 
   record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
 
-  if (GTK_WIDGET_MAPPED (menu))
+  if (gtk_widget_get_mapped (menu))
     {
       /* Set this to one.  popup_widget_loop increases it by one, so it becomes
          two.  show_help_echo uses this to detect popup menus.  */
@@ -2744,10 +1536,7 @@ create_and_show_popup_menu (f, first_wv, x, y, for_click)
 LWLIB_ID widget_id_tick;
 
 static void
-popup_selection_callback (widget, id, client_data)
-     Widget widget;
-     LWLIB_ID id;
-     XtPointer client_data;
+popup_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
 {
   menu_item_selection = (Lisp_Object *) client_data;
 }
@@ -2756,8 +1545,7 @@ popup_selection_callback (widget, id, client_data)
    as a Lisp object as (HIGHPART . LOWPART).  */
 
 static Lisp_Object
-pop_down_menu (arg)
-     Lisp_Object arg;
+pop_down_menu (Lisp_Object arg)
 {
   LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
                  | XINT (XCDR (arg)));
@@ -2774,12 +1562,7 @@ pop_down_menu (arg)
    menu pops down.
    menu_item_selection will be set to the selection.  */
 static void
-create_and_show_popup_menu (f, first_wv, x, y, for_click)
-     FRAME_PTR f;
-     widget_value *first_wv;
-     int x;
-     int y;
-     int for_click;
+create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y, int for_click, unsigned int timestamp)
 {
   int i;
   Arg av[2];
@@ -2798,6 +1581,10 @@ create_and_show_popup_menu (f, first_wv, x, y, for_click)
                            popup_deactivate_callback,
                            menu_highlight_callback);
 
+#ifdef USE_LUCID
+  apply_systemfont_to_menu (menu);
+#endif
+
   dummy.type = ButtonPress;
   dummy.serial = 0;
   dummy.send_event = 0;
@@ -2847,15 +1634,9 @@ create_and_show_popup_menu (f, first_wv, x, y, for_click)
 
 #endif /* not USE_GTK */
 
-static Lisp_Object
-xmenu_show (f, x, y, for_click, keymaps, title, error)
-     FRAME_PTR f;
-     int x;
-     int y;
-     int for_click;
-     int keymaps;
-     Lisp_Object title;
-     char **error;
+Lisp_Object
+xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
+           Lisp_Object title, char **error, EMACS_UINT timestamp)
 {
   int i;
   widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
@@ -3053,8 +1834,8 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
       wv_title->name = (char *) SDATA (title);
       wv_title->enabled = TRUE;
       wv_title->button_type = BUTTON_TYPE_NONE;
-      wv_title->next = wv_sep1;
       wv_title->help = Qnil;
+      wv_title->next = wv_sep1;
       first_wv->contents = wv_title;
     }
 
@@ -3062,7 +1843,7 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
   menu_item_selection = 0;
 
   /* Actually create and show the menu until popped down.  */
-  create_and_show_popup_menu (f, first_wv, x, y, for_click);
+  create_and_show_popup_menu (f, first_wv, x, y, for_click, timestamp);
 
   /* Free the widget_value objects we used to specify the contents.  */
   free_menubar_widget_value_tree (first_wv);
@@ -3130,9 +1911,7 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
 \f
 #ifdef USE_GTK
 static void
-dialog_selection_callback (widget, client_data)
-     GtkWidget *widget;
-     gpointer client_data;
+dialog_selection_callback (GtkWidget *widget, gpointer client_data)
 {
   /* The EMACS_INT cast avoids a warning.  There's no problem
      as long as pointers have enough bits to hold small integers.  */
@@ -3146,9 +1925,7 @@ dialog_selection_callback (widget, client_data)
    dialog pops down.
    menu_item_selection will be set to the selection.  */
 static void
-create_and_show_dialog (f, first_wv)
-     FRAME_PTR f;
-     widget_value *first_wv;
+create_and_show_dialog (FRAME_PTR f, widget_value *first_wv)
 {
   GtkWidget *menu;
 
@@ -3177,10 +1954,7 @@ create_and_show_dialog (f, first_wv)
 
 #else /* not USE_GTK */
 static void
-dialog_selection_callback (widget, id, client_data)
-     Widget widget;
-     LWLIB_ID id;
-     XtPointer client_data;
+dialog_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
 {
   /* The EMACS_INT cast avoids a warning.  There's no problem
      as long as pointers have enough bits to hold small integers.  */
@@ -3198,9 +1972,7 @@ dialog_selection_callback (widget, id, client_data)
    dialog pops down.
    menu_item_selection will be set to the selection.  */
 static void
-create_and_show_dialog (f, first_wv)
-     FRAME_PTR f;
-     widget_value *first_wv;
+create_and_show_dialog (FRAME_PTR f, widget_value *first_wv)
 {
   LWLIB_ID dialog_id;
 
@@ -3208,11 +1980,13 @@ create_and_show_dialog (f, first_wv)
     abort();
 
   dialog_id = widget_id_tick++;
+#ifdef USE_LUCID
+  apply_systemfont_to_dialog (f->output_data.x->widget);
+#endif
   lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
                     f->output_data.x->widget, 1, 0,
                     dialog_selection_callback, 0, 0);
   lw_modify_all_widgets (dialog_id, first_wv->contents, True);
-
   /* Display the dialog box.  */
   lw_pop_up_all_widgets (dialog_id);
   popup_activated_flag = 1;
@@ -3243,11 +2017,7 @@ static char * button_names [] = {
   "button6", "button7", "button8", "button9", "button10" };
 
 static Lisp_Object
-xdialog_show (f, keymaps, title, header, error_name)
-     FRAME_PTR f;
-     int keymaps;
-     Lisp_Object title, header;
-     char **error_name;
+xdialog_show (FRAME_PTR f, int keymaps, Lisp_Object title, Lisp_Object header, char **error_name)
 {
   int i, nb_buttons=0;
   char dialog_name[6];
@@ -3372,14 +2142,6 @@ xdialog_show (f, keymaps, title, header, error_name)
   /* No selection has been chosen yet.  */
   menu_item_selection = 0;
 
-  /* Force a redisplay before showing the dialog.  If a frame is created
-     just before showing the dialog, its contents may not have been fully
-     drawn, as this depends on timing of events from the X server.  Redisplay
-     is not done when a dialog is shown.  If redisplay could be done in the
-     X event loop (i.e. the X event loop does not run in a signal handler)
-     this would not be needed.  */
-  Fredisplay (Qt);
-
   /* Actually create and show the dialog.  */
   create_and_show_dialog (f, first_wv);
 
@@ -3453,9 +2215,7 @@ static struct frame *menu_help_frame;
    keyboard events.  */
 
 static void
-menu_help_callback (help_string, pane, item)
-     char *help_string;
-     int pane, item;
+menu_help_callback (char *help_string, int pane, int item)
 {
   extern Lisp_Object Qmenu_item;
   Lisp_Object *first_item;
@@ -3480,8 +2240,7 @@ menu_help_callback (help_string, pane, item)
 }
 
 static Lisp_Object
-pop_down_menu (arg)
-     Lisp_Object arg;
+pop_down_menu (Lisp_Object arg)
 {
   struct Lisp_Save_Value *p1 = XSAVE_VALUE (Fcar (arg));
   struct Lisp_Save_Value *p2 = XSAVE_VALUE (Fcdr (arg));
@@ -3515,14 +2274,8 @@ pop_down_menu (arg)
 }
 
 
-static Lisp_Object
-xmenu_show (f, x, y, for_click, keymaps, title, error)
-     FRAME_PTR f;
-     int x, y;
-     int for_click;
-     int keymaps;
-     Lisp_Object title;
-     char **error;
+Lisp_Object
+xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps, Lisp_Object title, char **error, unsigned int timestamp)
 {
   Window root;
   XMenu *menu;
@@ -3537,7 +2290,7 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
   unsigned int dummy_uint;
   int specpdl_count = SPECPDL_INDEX ();
 
-  if (! FRAME_X_P (f))
+  if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f))
     abort ();
 
   *error = 0;
@@ -3653,12 +2406,10 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
              item_data
                = (unsigned char *) alloca (maxwidth
                                            + SBYTES (descrip) + 1);
-             bcopy (SDATA (item_name), item_data,
-                    SBYTES (item_name));
+             memcpy (item_data, SDATA (item_name), SBYTES (item_name));
              for (j = SCHARS (item_name); j < maxwidth; j++)
                item_data[j] = ' ';
-             bcopy (SDATA (descrip), item_data + j,
-                    SBYTES (descrip));
+             memcpy (item_data + j, SDATA (descrip), SBYTES (descrip));
              item_data[j + SBYTES (descrip)] = 0;
            }
          else
@@ -3700,6 +2451,23 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
       y -= (uly + height) - dispheight;
       uly = dispheight - height;
     }
+#ifndef HAVE_X_WINDOWS
+  if (FRAME_HAS_MINIBUF_P (f) && uly+height > dispheight - 1)
+    {
+      /* Move the menu away of the echo area, to avoid overwriting the
+        menu with help echo messages or vice versa.  */
+      if (BUFFERP (echo_area_buffer[0]) && WINDOWP (echo_area_window))
+       {
+         y -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window));
+         uly -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window));
+       }
+      else
+       {
+         y--;
+         uly--;
+       }
+    }
+#endif
   if (ulx < 0) x -= ulx;
   if (uly < 0) y -= uly;
 
@@ -3799,7 +2567,7 @@ xmenu_show (f, x, y, for_click, keymaps, title, error)
 /* Detect if a dialog or menu has been posted.  */
 
 int
-popup_activated ()
+popup_activated (void)
 {
   return popup_activated_flag;
 }
@@ -3808,7 +2576,7 @@ popup_activated ()
 
 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
        doc: /* Return t if a menu or popup dialog is active.  */)
-     ()
+  (void)
 {
 #ifdef HAVE_MENUS
   return (popup_activated ()) ? Qt : Qnil;
@@ -3818,13 +2586,9 @@ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_
 }
 \f
 void
-syms_of_xmenu ()
+syms_of_xmenu (void)
 {
-  staticpro (&menu_items);
-  menu_items = Qnil;
-  menu_items_inuse = Qnil;
-
-  Qdebug_on_next_call = intern ("debug-on-next-call");
+  Qdebug_on_next_call = intern_c_string ("debug-on-next-call");
   staticpro (&Qdebug_on_next_call);
 
 #ifdef USE_X_TOOLKIT
@@ -3832,13 +2596,12 @@ syms_of_xmenu ()
   next_menubar_widget_id = 1;
 #endif
 
-  defsubr (&Sx_popup_menu);
   defsubr (&Smenu_or_popup_active_p);
 
 #if defined (USE_GTK) || defined (USE_X_TOOLKIT)
   defsubr (&Sx_menu_bar_open_internal);
-  Ffset (intern ("accelerate-menu"),
-        intern (Sx_menu_bar_open_internal.symbol_name));
+  Ffset (intern_c_string ("accelerate-menu"),
+        intern_c_string (Sx_menu_bar_open_internal.symbol_name));
 #endif
 
 #ifdef HAVE_MENUS