Fixes: debbugs:17865
[bpt/emacs.git] / src / xmenu.c
index b7dd547..9b1ac54 100644 (file)
@@ -1,7 +1,7 @@
 /* X Communication module for terminals which understand the X protocol.
 
 /* X Communication module for terminals which understand the X protocol.
 
-Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2012
-  Free Software Foundation, Inc.
+Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2014 Free Software
+Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 
 This file is part of GNU Emacs.
 
@@ -32,13 +32,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
 
 #include <config.h>
 
-#if 0  /* Why was this included?  And without syssignal.h?  */
-/* On 4.3 this loses if it comes after xterm.h.  */
-#include <signal.h>
-#endif
-
 #include <stdio.h>
 #include <stdio.h>
-#include <setjmp.h>
 
 #include "lisp.h"
 #include "keyboard.h"
 
 #include "lisp.h"
 #include "keyboard.h"
@@ -117,7 +111,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 static Lisp_Object Qdebug_on_next_call;
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
 static Lisp_Object Qdebug_on_next_call;
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
-static Lisp_Object xdialog_show (FRAME_PTR, int, Lisp_Object, Lisp_Object,
+static Lisp_Object xdialog_show (struct frame *, bool, Lisp_Object, Lisp_Object,
                                  const char **);
 #endif
 \f
                                  const char **);
 #endif
 \f
@@ -136,13 +130,10 @@ static struct frame *
 menubar_id_to_frame (LWLIB_ID id)
 {
   Lisp_Object tail, frame;
 menubar_id_to_frame (LWLIB_ID id)
 {
   Lisp_Object tail, frame;
-  FRAME_PTR f;
+  struct frame *f;
 
 
-  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
+  FOR_EACH_FRAME (tail, frame)
     {
     {
-      frame = XCAR (tail);
-      if (!FRAMEP (frame))
-        continue;
       f = XFRAME (frame);
       if (!FRAME_WINDOW_P (f))
        continue;
       f = XFRAME (frame);
       if (!FRAME_WINDOW_P (f))
        continue;
@@ -163,15 +154,14 @@ menubar_id_to_frame (LWLIB_ID id)
    the scroll bar or the edit window.  Fx_popup_menu needs to be
    sure it is the edit window.  */
 void
    the scroll bar or the edit window.  Fx_popup_menu needs to be
    sure it is the edit window.  */
 void
-mouse_position_for_popup (FRAME_PTR f, int *x, int *y)
+mouse_position_for_popup (struct frame *f, int *x, int *y)
 {
   Window root, dummy_window;
   int dummy;
 
 {
   Window root, dummy_window;
   int dummy;
 
-  if (! FRAME_X_P (f))
-    abort ();
+  eassert (FRAME_X_P (f));
 
 
-  BLOCK_INPUT;
+  block_input ();
 
   XQueryPointer (FRAME_X_DISPLAY (f),
                  DefaultRootWindow (FRAME_X_DISPLAY (f)),
 
   XQueryPointer (FRAME_X_DISPLAY (f),
                  DefaultRootWindow (FRAME_X_DISPLAY (f)),
@@ -192,7 +182,7 @@ mouse_position_for_popup (FRAME_PTR f, int *x, int *y)
                     we don't care.  */
                  (unsigned int *) &dummy);
 
                     we don't care.  */
                  (unsigned int *) &dummy);
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   /* xmenu_show expects window coordinates, not root window
      coordinates.  Translate.  */
 
   /* xmenu_show expects window coordinates, not root window
      coordinates.  Translate.  */
@@ -202,153 +192,6 @@ mouse_position_for_popup (FRAME_PTR f, int *x, int *y)
 
 #endif /* HAVE_X_WINDOWS */
 
 
 #endif /* HAVE_X_WINDOWS */
 
-#ifdef HAVE_MENUS
-
-DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
-       doc: /* Pop up a dialog box and return user's selection.
-POSITION specifies which frame to use.
-This is normally a mouse button event or a window or frame.
-If POSITION is t, it means to use the frame the mouse is on.
-The dialog box appears in the middle of the specified frame.
-
-CONTENTS specifies the alternatives to display in the dialog box.
-It is a list of the form (DIALOG ITEM1 ITEM2...).
-Each ITEM is a cons cell (STRING . VALUE).
-The return value is VALUE from the chosen item.
-
-An ITEM may also be just a string--that makes a nonselectable item.
-An ITEM may also be nil--that means to put all preceding items
-on the left of the dialog box and all following items on the right.
-\(By default, approximately half appear on each side.)
-
-If HEADER is non-nil, the frame title for the box is "Information",
-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.  */)
-  (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
-{
-  FRAME_PTR f = NULL;
-  Lisp_Object window;
-
-  check_x ();
-
-  /* Decode the first argument: find the window or frame to use.  */
-  if (EQ (position, Qt)
-      || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
-                              || EQ (XCAR (position), Qtool_bar))))
-    {
-#if 0 /* Using the frame the mouse is on may not be right.  */
-      /* Use the mouse's current position.  */
-      FRAME_PTR new_f = SELECTED_FRAME ();
-      Lisp_Object bar_window;
-      enum scroll_bar_part part;
-      Time time;
-      Lisp_Object x, y;
-
-      (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
-
-      if (new_f != 0)
-       XSETFRAME (window, new_f);
-      else
-       window = selected_window;
-#endif
-      window = selected_window;
-    }
-  else if (CONSP (position))
-    {
-      Lisp_Object tem;
-      tem = Fcar (position);
-      if (CONSP (tem))
-       window = Fcar (Fcdr (position));
-      else
-       {
-         tem = Fcar (Fcdr (position));  /* EVENT_START (position) */
-         window = Fcar (tem);       /* POSN_WINDOW (tem) */
-       }
-    }
-  else if (WINDOWP (position) || FRAMEP (position))
-    window = position;
-  else
-    window = Qnil;
-
-  /* Decode where to put the menu.  */
-
-  if (FRAMEP (window))
-    f = XFRAME (window);
-  else if (WINDOWP (window))
-    {
-      CHECK_LIVE_WINDOW (window);
-      f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
-    }
-  else
-    /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
-       but I don't want to make one now.  */
-    CHECK_WINDOW (window);
-
-  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
-     in the middle of frame F.  */
-  {
-    Lisp_Object x, y, frame, newpos;
-    XSETFRAME (frame, f);
-    XSETINT (x, x_pixel_width (f) / 2);
-    XSETINT (y, x_pixel_height (f) / 2);
-    newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
-
-    return Fx_popup_menu (newpos,
-                         Fcons (Fcar (contents), Fcons (contents, Qnil)));
-  }
-#else
-  {
-    Lisp_Object title;
-    const char *error_name;
-    Lisp_Object selection;
-    ptrdiff_t specpdl_count = SPECPDL_INDEX ();
-
-    /* Decode the dialog items from what was specified.  */
-    title = Fcar (contents);
-    CHECK_STRING (title);
-    record_unwind_protect (unuse_menu_items, Qnil);
-
-    if (NILP (Fcar (Fcdr (contents))))
-      /* No buttons specified, add an "Ok" button so users can pop down
-         the dialog.  Also, the lesstif/motif version crashes if there are
-         no buttons.  */
-      contents = Fcons (title, Fcons (Fcons (build_string ("Ok"), Qt), Qnil));
-
-    list_of_panes (Fcons (contents, Qnil));
-
-    /* Display them in a dialog box.  */
-    BLOCK_INPUT;
-    selection = xdialog_show (f, 0, title, header, &error_name);
-    UNBLOCK_INPUT;
-
-    unbind_to (specpdl_count, Qnil);
-    discard_menu_items ();
-
-    if (error_name) error ("%s", error_name);
-    return selection;
-  }
-#endif
-}
-
-
 #ifndef MSDOS
 
 #if defined USE_GTK || defined USE_MOTIF
 #ifndef MSDOS
 
 #if defined USE_GTK || defined USE_MOTIF
@@ -387,12 +230,12 @@ x_menu_wait_for_event (void *data)
 #elif defined USE_GTK
          ! gtk_events_pending ()
 #else
 #elif defined USE_GTK
          ! gtk_events_pending ()
 #else
-         ! XPending ((Display*) data)
+         ! XPending (data)
 #endif
          )
     {
 #endif
          )
     {
-      EMACS_TIME next_time = timer_check (), *ntp;
-      SELECT_TYPE read_fds;
+      struct timespec next_time = timer_check (), *ntp;
+      fd_set read_fds;
       struct x_display_info *dpyinfo;
       int n = 0;
 
       struct x_display_info *dpyinfo;
       int n = 0;
 
@@ -405,12 +248,12 @@ x_menu_wait_for_event (void *data)
           XFlush (dpyinfo->display);
         }
 
           XFlush (dpyinfo->display);
         }
 
-      if (! EMACS_TIME_VALID_P (next_time))
+      if (! timespec_valid_p (next_time))
         ntp = 0;
       else
         ntp = &next_time;
 
         ntp = 0;
       else
         ntp = &next_time;
 
-#ifdef HAVE_GTK3
+#if defined USE_GTK && defined HAVE_GTK3
       /* Gtk3 have arrows on menus when they don't fit.  When the
         pointer is over an arrow, a timeout scrolls it a bit.  Use
         xg_select so that timeout gets triggered.  */
       /* Gtk3 have arrows on menus when they don't fit.  When the
         pointer is over an arrow, a timeout scrolls it a bit.  Use
         xg_select so that timeout gets triggered.  */
@@ -495,9 +338,9 @@ If FRAME is nil or not given, use the selected frame.  */)
   (Lisp_Object frame)
 {
   XEvent ev;
   (Lisp_Object frame)
 {
   XEvent ev;
-  FRAME_PTR f = check_x_frame (frame);
+  struct frame *f = decode_window_system_frame (frame);
   Widget menubar;
   Widget menubar;
-  BLOCK_INPUT;
+  block_input ();
 
   if (FRAME_EXTERNAL_MENU_BAR (f))
     set_frame_menubar (f, 0, 1);
 
   if (FRAME_EXTERNAL_MENU_BAR (f))
     set_frame_menubar (f, 0, 1);
@@ -506,13 +349,13 @@ If FRAME is nil or not given, use the selected frame.  */)
   if (menubar)
     {
       Window child;
   if (menubar)
     {
       Window child;
-      int error_p = 0;
+      bool error_p = 0;
 
       x_catch_errors (FRAME_X_DISPLAY (f));
       memset (&ev, 0, sizeof ev);
       ev.xbutton.display = FRAME_X_DISPLAY (f);
       ev.xbutton.window = XtWindow (menubar);
 
       x_catch_errors (FRAME_X_DISPLAY (f));
       memset (&ev, 0, sizeof ev);
       ev.xbutton.display = FRAME_X_DISPLAY (f);
       ev.xbutton.window = XtWindow (menubar);
-      ev.xbutton.root = FRAME_X_DISPLAY_INFO (f)->root_window;
+      ev.xbutton.root = FRAME_DISPLAY_INFO (f)->root_window;
       ev.xbutton.time = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
       ev.xbutton.button = Button1;
       ev.xbutton.x = ev.xbutton.y = FRAME_MENUBAR_HEIGHT (f) / 2;
       ev.xbutton.time = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
       ev.xbutton.button = Button1;
       ev.xbutton.x = ev.xbutton.y = FRAME_MENUBAR_HEIGHT (f) / 2;
@@ -555,7 +398,7 @@ If FRAME is nil or not given, use the selected frame.  */)
         }
     }
 
         }
     }
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   return Qnil;
 }
 
   return Qnil;
 }
@@ -573,13 +416,10 @@ If FRAME is nil or not given, use the selected frame.  */)
   (Lisp_Object frame)
 {
   GtkWidget *menubar;
   (Lisp_Object frame)
 {
   GtkWidget *menubar;
-  FRAME_PTR f;
-
-  /* gcc 2.95 doesn't accept the FRAME_PTR declaration after
-     BLOCK_INPUT.  */
+  struct frame *f;
 
 
-  BLOCK_INPUT;
-  f = check_x_frame (frame);
+  block_input ();
+  f = decode_window_system_frame (frame);
 
   if (FRAME_EXTERNAL_MENU_BAR (f))
     set_frame_menubar (f, 0, 1);
 
   if (FRAME_EXTERNAL_MENU_BAR (f))
     set_frame_menubar (f, 0, 1);
@@ -597,7 +437,7 @@ If FRAME is nil or not given, use the selected frame.  */)
           g_list_free (children);
         }
     }
           g_list_free (children);
         }
     }
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   return Qnil;
 }
 
   return Qnil;
 }
@@ -634,10 +474,9 @@ popup_widget_loop (int do_timers, GtkWidget *widget)
    execute Lisp code.  */
 
 void
    execute Lisp code.  */
 
 void
-x_activate_menubar (FRAME_PTR f)
+x_activate_menubar (struct frame *f)
 {
 {
-  if (! FRAME_X_P (f))
-    abort ();
+  eassert (FRAME_X_P (f));
 
   if (!f->output_data.x->saved_menu_event->type)
     return;
 
   if (!f->output_data.x->saved_menu_event->type)
     return;
@@ -649,7 +488,7 @@ x_activate_menubar (FRAME_PTR f)
 #endif
 
   set_frame_menubar (f, 0, 1);
 #endif
 
   set_frame_menubar (f, 0, 1);
-  BLOCK_INPUT;
+  block_input ();
   popup_activated_flag = 1;
 #ifdef USE_GTK
   XPutBackEvent (f->output_data.x->display_info->display,
   popup_activated_flag = 1;
 #ifdef USE_GTK
   XPutBackEvent (f->output_data.x->display_info->display,
@@ -657,7 +496,7 @@ x_activate_menubar (FRAME_PTR f)
 #else
   XtDispatchEvent (f->output_data.x->saved_menu_event);
 #endif
 #else
   XtDispatchEvent (f->output_data.x->saved_menu_event);
 #endif
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   /* Ignore this if we get it a second time.  */
   f->output_data.x->saved_menu_event->type = 0;
 
   /* Ignore this if we get it a second time.  */
   f->output_data.x->saved_menu_event->type = 0;
@@ -671,35 +510,31 @@ static void
 popup_activate_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
 {
   popup_activated_flag = 1;
 popup_activate_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
 {
   popup_activated_flag = 1;
-#ifdef USE_X_TOOLKIT
   x_activate_timeout_atimer ();
   x_activate_timeout_atimer ();
-#endif
 }
 #endif
 
 /* This callback is invoked when a dialog or menu is finished being
    used and has been unposted.  */
 
 }
 #endif
 
 /* This callback is invoked when a dialog or menu is finished being
    used and has been unposted.  */
 
-#ifdef USE_GTK
 static void
 static void
-popup_deactivate_callback (GtkWidget *widget, gpointer client_data)
-{
-  popup_activated_flag = 0;
-}
+popup_deactivate_callback (
+#ifdef USE_GTK
+                          GtkWidget *widget, gpointer client_data
 #else
 #else
-static void
-popup_deactivate_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
+                          Widget widget, LWLIB_ID id, XtPointer client_data
+#endif
+                          )
 {
   popup_activated_flag = 0;
 }
 {
   popup_activated_flag = 0;
 }
-#endif
 
 
 /* Function that finds the frame for WIDGET and shows the HELP text
    for that widget.
    F is the frame if known, or NULL if not known.  */
 static void
 
 
 /* Function that finds the frame for WIDGET and shows the HELP text
    for that widget.
    F is the frame if known, or NULL if not known.  */
 static void
-show_help_event (FRAME_PTR f, xt_or_gtk_widget widget, Lisp_Object help)
+show_help_event (struct frame *f, xt_or_gtk_widget widget, Lisp_Object help)
 {
   Lisp_Object frame;
 
 {
   Lisp_Object frame;
 
@@ -742,8 +577,7 @@ menu_highlight_callback (GtkWidget *widget, gpointer call_data)
   xg_menu_item_cb_data *cb_data;
   Lisp_Object help;
 
   xg_menu_item_cb_data *cb_data;
   Lisp_Object help;
 
-  cb_data = (xg_menu_item_cb_data*) g_object_get_data (G_OBJECT (widget),
-                                                       XG_ITEM_DATA);
+  cb_data = g_object_get_data (G_OBJECT (widget), XG_ITEM_DATA);
   if (! cb_data) return;
 
   help = call_data ? cb_data->help : Qnil;
   if (! cb_data) return;
 
   help = call_data ? cb_data->help : Qnil;
@@ -761,15 +595,11 @@ menu_highlight_callback (GtkWidget *widget, gpointer call_data)
 static void
 menu_highlight_callback (Widget widget, LWLIB_ID id, void *call_data)
 {
 static void
 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;
+  widget_value *wv = call_data;
+  Lisp_Object help = wv ? wv->help : Qnil;
 
   /* Determine the frame for the help event.  */
 
   /* Determine the frame for the help event.  */
-  f = menubar_id_to_frame (id);
+  struct frame *f = menubar_id_to_frame (id);
 
   show_help_event (f, widget, help);
 }
 
   show_help_event (f, widget, help);
 }
@@ -789,7 +619,7 @@ static int xg_crazy_callback_abort;
 static void
 menubar_selection_callback (GtkWidget *widget, gpointer client_data)
 {
 static void
 menubar_selection_callback (GtkWidget *widget, gpointer client_data)
 {
-  xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
+  xg_menu_item_cb_data *cb_data = client_data;
 
   if (xg_crazy_callback_abort)
     return;
 
   if (xg_crazy_callback_abort)
     return;
@@ -812,10 +642,10 @@ menubar_selection_callback (GtkWidget *widget, gpointer client_data)
      sit-for will exit at once if the focus event follows the menu selection
      event.  */
 
      sit-for will exit at once if the focus event follows the menu selection
      event.  */
 
-  BLOCK_INPUT;
+  block_input ();
   while (gtk_events_pending ())
     gtk_main_iteration ();
   while (gtk_events_pending ())
     gtk_main_iteration ();
-  UNBLOCK_INPUT;
+  unblock_input ();
 
   find_and_call_menu_selection (cb_data->cl_data->f,
                                 cb_data->cl_data->menu_bar_items_used,
 
   find_and_call_menu_selection (cb_data->cl_data->f,
                                 cb_data->cl_data->menu_bar_items_used,
@@ -832,7 +662,7 @@ menubar_selection_callback (GtkWidget *widget, gpointer client_data)
 static void
 menubar_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
 {
 static void
 menubar_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
 {
-  FRAME_PTR f;
+  struct frame *f;
 
   f = menubar_id_to_frame (id);
   if (!f)
 
   f = menubar_id_to_frame (id);
   if (!f)
@@ -843,26 +673,25 @@ menubar_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
 #endif /* not USE_GTK */
 \f
 /* Recompute all the widgets of frame F, when the menu bar has been
 #endif /* not USE_GTK */
 \f
 /* Recompute all the widgets of frame F, when the menu bar has been
-   changed.  Value is non-zero if widgets were updated.  */
+   changed.  */
 
 
-static int
-update_frame_menubar (FRAME_PTR f)
+static void
+update_frame_menubar (struct frame *f)
 {
 #ifdef USE_GTK
 {
 #ifdef USE_GTK
-  return xg_update_frame_menubar (f);
+  xg_update_frame_menubar (f);
 #else
   struct x_output *x;
   int columns, rows;
 
 #else
   struct x_output *x;
   int columns, rows;
 
-  if (! FRAME_X_P (f))
-    abort ();
+  eassert (FRAME_X_P (f));
 
   x = f->output_data.x;
 
   if (!x->menubar_widget || XtIsManaged (x->menubar_widget))
 
   x = f->output_data.x;
 
   if (!x->menubar_widget || XtIsManaged (x->menubar_widget))
-    return 0;
+    return;
 
 
-  BLOCK_INPUT;
+  block_input ();
   /* Save the size of the frame because the pane widget doesn't accept
      to resize itself. So force it.  */
   columns = FRAME_COLS (f);
   /* Save the size of the frame because the pane widget doesn't accept
      to resize itself. So force it.  */
   columns = FRAME_COLS (f);
@@ -889,9 +718,8 @@ update_frame_menubar (FRAME_PTR f)
 
   /* Force the pane widget to resize itself with the right values.  */
   EmacsFrameSetCharSize (x->edit_widget, columns, rows);
 
   /* Force the pane widget to resize itself with the right values.  */
   EmacsFrameSetCharSize (x->edit_widget, columns, rows);
-  UNBLOCK_INPUT;
+  unblock_input ();
 #endif
 #endif
-  return 1;
 }
 
 #ifdef USE_LUCID
 }
 
 #ifdef USE_LUCID
@@ -930,7 +758,7 @@ apply_systemfont_to_menu (struct frame *f, Widget w)
    it is set the first time this is called, from initialize_frame_menubar.  */
 
 void
    it is set the first time this is called, from initialize_frame_menubar.  */
 
 void
-set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
+set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
 {
   xt_or_gtk_widget menubar_widget;
 #ifdef USE_X_TOOLKIT
 {
   xt_or_gtk_widget menubar_widget;
 #ifdef USE_X_TOOLKIT
@@ -940,10 +768,10 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
   widget_value *wv, *first_wv, *prev_wv = 0;
   int i;
   int *submenu_start, *submenu_end;
   widget_value *wv, *first_wv, *prev_wv = 0;
   int i;
   int *submenu_start, *submenu_end;
-  int *submenu_top_level_items, *submenu_n_panes;
+  bool *submenu_top_level_items;
+  int *submenu_n_panes;
 
 
-  if (! FRAME_X_P (f))
-    abort ();
+  eassert (FRAME_X_P (f));
 
   menubar_widget = f->output_data.x->menubar_widget;
 
 
   menubar_widget = f->output_data.x->menubar_widget;
 
@@ -968,7 +796,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
 #ifdef USE_GTK
   /* If we have detached menus, we must update deep so detached menus
      also gets updated.  */
 #ifdef USE_GTK
   /* If we have detached menus, we must update deep so detached menus
      also gets updated.  */
-  deep_p = deep_p || xg_have_tear_offs ();
+  deep_p = deep_p || xg_have_tear_offs (f);
 #endif
 
   if (deep_p)
 #endif
 
   if (deep_p)
@@ -980,8 +808,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
       ptrdiff_t specpdl_count = SPECPDL_INDEX ();
       int previous_menu_items_used = f->menu_bar_items_used;
       Lisp_Object *previous_items
       ptrdiff_t specpdl_count = SPECPDL_INDEX ();
       int previous_menu_items_used = f->menu_bar_items_used;
       Lisp_Object *previous_items
-       = (Lisp_Object *) alloca (previous_menu_items_used
-                                 * sizeof (Lisp_Object));
+       = alloca (previous_menu_items_used * sizeof *previous_items);
       int subitems;
 
       /* If we are making a new widget, its contents are empty,
       int subitems;
 
       /* If we are making a new widget, its contents are empty,
@@ -989,7 +816,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
       if (! menubar_widget)
        previous_menu_items_used = 0;
 
       if (! menubar_widget)
        previous_menu_items_used = 0;
 
-      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
+      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents;
       specbind (Qinhibit_quit, Qt);
       /* Don't let the debugger step into this code
         because it is not reentrant.  */
       specbind (Qinhibit_quit, Qt);
       /* Don't let the debugger step into this code
         because it is not reentrant.  */
@@ -1012,14 +839,14 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
       if (! NILP (Vlucid_menu_bar_dirty_flag))
        call0 (Qrecompute_lucid_menubar);
       safe_run_hooks (Qmenu_bar_update_hook);
       if (! NILP (Vlucid_menu_bar_dirty_flag))
        call0 (Qrecompute_lucid_menubar);
       safe_run_hooks (Qmenu_bar_update_hook);
-      FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
+      fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
 
       items = FRAME_MENU_BAR_ITEMS (f);
 
       /* Save the frame's previous menu bar contents data.  */
       if (previous_menu_items_used)
        memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
 
       items = FRAME_MENU_BAR_ITEMS (f);
 
       /* Save the frame's previous menu bar contents data.  */
       if (previous_menu_items_used)
        memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
-               previous_menu_items_used * sizeof (Lisp_Object));
+               previous_menu_items_used * word_size);
 
       /* Fill in menu_items with the current menu bar contents.
         This can evaluate Lisp code.  */
 
       /* Fill in menu_items with the current menu bar contents.
         This can evaluate Lisp code.  */
@@ -1028,10 +855,11 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
       menu_items = f->menu_bar_vector;
       menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
       subitems = ASIZE (items) / 4;
       menu_items = f->menu_bar_vector;
       menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
       subitems = ASIZE (items) / 4;
-      submenu_start = (int *) alloca ((subitems + 1) * sizeof (int));
-      submenu_end = (int *) alloca (subitems * sizeof (int));
-      submenu_n_panes = (int *) alloca (subitems * sizeof (int));
-      submenu_top_level_items = (int *) alloca (subitems * sizeof (int));
+      submenu_start = alloca ((subitems + 1) * sizeof *submenu_start);
+      submenu_end = alloca (subitems * sizeof *submenu_end);
+      submenu_n_panes = alloca (subitems * sizeof *submenu_n_panes);
+      submenu_top_level_items = alloca (subitems
+                                       * sizeof *submenu_top_level_items);
       init_menu_items ();
       for (i = 0; i < subitems; i++)
        {
       init_menu_items ();
       for (i = 0; i < subitems; i++)
        {
@@ -1067,7 +895,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
       wv->help = Qnil;
       first_wv = wv;
 
       wv->help = Qnil;
       first_wv = wv;
 
-      for (i = 0; 0 <= submenu_start[i]; i++)
+      for (i = 0; submenu_start[i] >= 0; i++)
        {
          menu_items_n_panes = submenu_n_panes[i];
          wv = digest_single_submenu (submenu_start[i], submenu_end[i],
        {
          menu_items_n_panes = submenu_n_panes[i];
          wv = digest_single_submenu (submenu_start[i], submenu_end[i],
@@ -1103,7 +931,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
        }
 
       /* The menu items are different, so store them in the frame.  */
        }
 
       /* The menu items are different, so store them in the frame.  */
-      f->menu_bar_vector = menu_items;
+      fset_menu_bar_vector (f, menu_items);
       f->menu_bar_items_used = menu_items_used;
 
       /* This undoes save_menu_items.  */
       f->menu_bar_items_used = menu_items_used;
 
       /* This undoes save_menu_items.  */
@@ -1173,7 +1001,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
 
   /* Create or update the menu bar widget.  */
 
 
   /* Create or update the menu bar widget.  */
 
-  BLOCK_INPUT;
+  block_input ();
 
 #ifdef USE_GTK
   xg_crazy_callback_abort = 1;
 
 #ifdef USE_GTK
   xg_crazy_callback_abort = 1;
@@ -1273,7 +1101,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
   xg_crazy_callback_abort = 0;
 #endif
 
   xg_crazy_callback_abort = 0;
 #endif
 
-  UNBLOCK_INPUT;
+  unblock_input ();
 }
 
 /* Called from Fx_create_frame to create the initial menubar of a frame
 }
 
 /* Called from Fx_create_frame to create the initial menubar of a frame
@@ -1282,11 +1110,11 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
    is visible.  */
 
 void
    is visible.  */
 
 void
-initialize_frame_menubar (FRAME_PTR f)
+initialize_frame_menubar (struct frame *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.  */
 {
   /* This function is called before the first chance to redisplay
      the frame.  It has to be, so the frame will have the right size.  */
-  FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
+  fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
   set_frame_menubar (f, 1, 1);
 }
 
   set_frame_menubar (f, 1, 1);
 }
 
@@ -1297,12 +1125,11 @@ initialize_frame_menubar (FRAME_PTR f)
 
 #ifndef USE_GTK
 void
 
 #ifndef USE_GTK
 void
-free_frame_menubar (FRAME_PTR f)
+free_frame_menubar (struct frame *f)
 {
   Widget menubar_widget;
 
 {
   Widget menubar_widget;
 
-  if (! FRAME_X_P (f))
-    abort ();
+  eassert (FRAME_X_P (f));
 
   menubar_widget = f->output_data.x->menubar_widget;
 
 
   menubar_widget = f->output_data.x->menubar_widget;
 
@@ -1322,7 +1149,7 @@ free_frame_menubar (FRAME_PTR f)
       Position x0, y0, x1, y1;
 #endif
 
       Position x0, y0, x1, y1;
 #endif
 
-      BLOCK_INPUT;
+      block_input ();
 
 #ifdef USE_MOTIF
       if (f->output_data.x->widget)
 
 #ifdef USE_MOTIF
       if (f->output_data.x->widget)
@@ -1339,9 +1166,9 @@ free_frame_menubar (FRAME_PTR f)
          if (x1 == 0 && y1 == 0)
            XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
 #endif
          if (x1 == 0 && y1 == 0)
            XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
 #endif
-          x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+         x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
        }
        }
-      UNBLOCK_INPUT;
+      unblock_input ();
     }
 }
 #endif /* not USE_GTK */
     }
 }
 #endif /* not USE_GTK */
@@ -1356,8 +1183,8 @@ free_frame_menubar (FRAME_PTR f)
 /* F is the frame the menu is for.
    X and Y are the frame-relative specified position,
    relative to the inside upper left corner of the frame F.
 /* F is the frame the menu is for.
    X and Y are the frame-relative specified position,
    relative to the inside upper left corner of the frame F.
-   FOR_CLICK is nonzero if this menu was invoked for a mouse click.
-   KEYMAPS is 1 if this menu was specified with keymaps;
+   FOR_CLICK is true if this menu was invoked for a mouse click.
+   KEYMAPS is true if this menu was specified with keymaps;
     in that case, we return a list containing the chosen item's value
     and perhaps also the pane's prefix.
    TITLE is the specified menu title.
     in that case, we return a list containing the chosen item's value
     and perhaps also the pane's prefix.
    TITLE is the specified menu title.
@@ -1375,7 +1202,7 @@ static Lisp_Object *volatile menu_item_selection;
    create_and_show_popup_menu below.  */
 struct next_popup_x_y
 {
    create_and_show_popup_menu below.  */
 struct next_popup_x_y
 {
-  FRAME_PTR f;
+  struct frame *f;
   int x;
   int y;
 };
   int x;
   int y;
 };
@@ -1393,9 +1220,9 @@ struct next_popup_x_y
 static void
 menu_position_func (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data)
 {
 static void
 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;
+  struct next_popup_x_y *data = user_data;
   GtkRequisition req;
   GtkRequisition req;
-  struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (data->f);
+  struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (data->f);
   int disp_width = x_display_pixel_width (dpyinfo);
   int disp_height = x_display_pixel_height (dpyinfo);
 
   int disp_width = x_display_pixel_width (dpyinfo);
   int disp_height = x_display_pixel_height (dpyinfo);
 
@@ -1414,37 +1241,34 @@ menu_position_func (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer
 static void
 popup_selection_callback (GtkWidget *widget, gpointer client_data)
 {
 static void
 popup_selection_callback (GtkWidget *widget, gpointer client_data)
 {
-  xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
+  xg_menu_item_cb_data *cb_data = client_data;
 
   if (xg_crazy_callback_abort) return;
 
   if (xg_crazy_callback_abort) return;
-  if (cb_data) menu_item_selection = (Lisp_Object *) cb_data->call_data;
+  if (cb_data) menu_item_selection = cb_data->call_data;
 }
 
 }
 
-static Lisp_Object
-pop_down_menu (Lisp_Object arg)
+static void
+pop_down_menu (void *arg)
 {
 {
-  struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
-
   popup_activated_flag = 0;
   popup_activated_flag = 0;
-  BLOCK_INPUT;
-  gtk_widget_destroy (GTK_WIDGET (p->pointer));
-  UNBLOCK_INPUT;
-  return Qnil;
+  block_input ();
+  gtk_widget_destroy (GTK_WIDGET (arg));
+  unblock_input ();
 }
 
 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
    menu pops down.
    menu_item_selection will be set to the selection.  */
 static void
 }
 
 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
    menu pops down.
    menu_item_selection will be set to the selection.  */
 static void
-create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y,
-                           int for_click, Time timestamp)
+create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
+                           int x, int y, bool for_click)
 {
   int i;
   GtkWidget *menu;
   GtkMenuPositionFunc pos_func = 0;  /* Pop up at pointer.  */
   struct next_popup_x_y popup_x_y;
   ptrdiff_t specpdl_count = SPECPDL_INDEX ();
 {
   int i;
   GtkWidget *menu;
   GtkMenuPositionFunc pos_func = 0;  /* Pop up at pointer.  */
   struct next_popup_x_y popup_x_y;
   ptrdiff_t specpdl_count = SPECPDL_INDEX ();
-  int use_pos_func = ! for_click;
+  bool use_pos_func = ! for_click;
 
 #ifdef HAVE_GTK3
   /* Always use position function for Gtk3.  Otherwise menus may become
 
 #ifdef HAVE_GTK3
   /* Always use position function for Gtk3.  Otherwise menus may become
@@ -1452,8 +1276,7 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y,
   use_pos_func = 1;
 #endif
 
   use_pos_func = 1;
 #endif
 
-  if (! FRAME_X_P (f))
-    abort ();
+  eassert (FRAME_X_P (f));
 
   xg_crazy_callback_abort = 1;
   menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
 
   xg_crazy_callback_abort = 1;
   menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
@@ -1481,17 +1304,19 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y,
   if (for_click)
     {
       for (i = 0; i < 5; i++)
   if (for_click)
     {
       for (i = 0; i < 5; i++)
-        if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
+        if (FRAME_DISPLAY_INFO (f)->grabbed & (1 << i))
           break;
           break;
+      /* If keys aren't grabbed (i.e., a mouse up event), use 0.  */
+      if (i == 5) i = 0;
     }
 
   /* Display the menu.  */
   gtk_widget_show_all (menu);
 
   gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i,
     }
 
   /* Display the menu.  */
   gtk_widget_show_all (menu);
 
   gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i,
-                 timestamp ? timestamp : gtk_get_current_event_time ());
+                 FRAME_DISPLAY_INFO (f)->last_user_time);
 
 
-  record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
+  record_unwind_protect_ptr (pop_down_menu, menu);
 
   if (gtk_widget_get_mapped (menu))
     {
 
   if (gtk_widget_get_mapped (menu))
     {
@@ -1506,7 +1331,7 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv, int x, int y,
 
   /* Must reset this manually because the button release event is not passed
      to Emacs event loop. */
 
   /* Must reset this manually because the button release event is not passed
      to Emacs event loop. */
-  FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+  FRAME_DISPLAY_INFO (f)->grabbed = 0;
 }
 
 #else /* not USE_GTK */
 }
 
 #else /* not USE_GTK */
@@ -1524,32 +1349,30 @@ LWLIB_ID widget_id_tick;
 static void
 popup_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
 {
 static void
 popup_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
 {
-  menu_item_selection = (Lisp_Object *) client_data;
+  menu_item_selection = client_data;
 }
 
 /* ARG is the LWLIB ID of the dialog box, represented
    as a Lisp object as (HIGHPART . LOWPART).  */
 
 }
 
 /* ARG is the LWLIB ID of the dialog box, represented
    as a Lisp object as (HIGHPART . LOWPART).  */
 
-static Lisp_Object
+static void
 pop_down_menu (Lisp_Object arg)
 {
   LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
                  | XINT (XCDR (arg)));
 
 pop_down_menu (Lisp_Object arg)
 {
   LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
                  | XINT (XCDR (arg)));
 
-  BLOCK_INPUT;
+  block_input ();
   lw_destroy_all_widgets (id);
   lw_destroy_all_widgets (id);
-  UNBLOCK_INPUT;
+  unblock_input ();
   popup_activated_flag = 0;
   popup_activated_flag = 0;
-
-  return Qnil;
 }
 
 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
    menu pops down.
    menu_item_selection will be set to the selection.  */
 static void
 }
 
 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
    menu pops down.
    menu_item_selection will be set to the selection.  */
 static void
-create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv,
-                           int x, int y, int for_click, Time timestamp)
+create_and_show_popup_menu (struct frame *f, widget_value *first_wv,
+                           int x, int y, bool for_click)
 {
   int i;
   Arg av[2];
 {
   int i;
   Arg av[2];
@@ -1559,8 +1382,7 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv,
   LWLIB_ID menu_id;
   Widget menu;
 
   LWLIB_ID menu_id;
   Widget menu;
 
-  if (! FRAME_X_P (f))
-    abort ();
+  eassert (FRAME_X_P (f));
 
 #ifdef USE_LUCID
   apply_systemfont_to_menu (f, f->output_data.x->widget);
 
 #ifdef USE_LUCID
   apply_systemfont_to_menu (f, f->output_data.x->widget);
@@ -1578,7 +1400,7 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv,
   event->send_event = 0;
   event->display = FRAME_X_DISPLAY (f);
   event->time = CurrentTime;
   event->send_event = 0;
   event->display = FRAME_X_DISPLAY (f);
   event->time = CurrentTime;
-  event->root = FRAME_X_DISPLAY_INFO (f)->root_window;
+  event->root = FRAME_DISPLAY_INFO (f)->root_window;
   event->window = event->subwindow = event->root;
   event->x = x;
   event->y = y;
   event->window = event->subwindow = event->root;
   event->x = x;
   event->y = y;
@@ -1593,7 +1415,7 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv,
   event->state = 0;
   event->button = 0;
   for (i = 0; i < 5; i++)
   event->state = 0;
   event->button = 0;
   for (i = 0; i < 5; i++)
-    if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
+    if (FRAME_DISPLAY_INFO (f)->grabbed & (1 << i))
       event->button = i;
 
   /* Don't allow any geometry request from the user.  */
       event->button = i;
 
   /* Don't allow any geometry request from the user.  */
@@ -1613,7 +1435,7 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv,
                                   make_number (menu_id & ~(-1 << (fact)))));
 
     /* Process events that apply to the menu.  */
                                   make_number (menu_id & ~(-1 << (fact)))));
 
     /* Process events that apply to the menu.  */
-    popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 1);
+    popup_get_selection (0, FRAME_DISPLAY_INFO (f), menu_id, 1);
 
     unbind_to (specpdl_count, Qnil);
   }
 
     unbind_to (specpdl_count, Qnil);
   }
@@ -1621,35 +1443,29 @@ create_and_show_popup_menu (FRAME_PTR f, widget_value *first_wv,
 
 #endif /* not USE_GTK */
 
 
 #endif /* not USE_GTK */
 
-static Lisp_Object
-cleanup_widget_value_tree (Lisp_Object arg)
+static void
+cleanup_widget_value_tree (void *arg)
 {
 {
-  struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
-  widget_value *wv = p->pointer;
-
-  free_menubar_widget_value_tree (wv);
-
-  return Qnil;
+  free_menubar_widget_value_tree (arg);
 }
 
 Lisp_Object
 }
 
 Lisp_Object
-xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
-           Lisp_Object title, const char **error_name, Time timestamp)
+xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
+           Lisp_Object title, const char **error_name)
 {
   int i;
   widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
   widget_value **submenu_stack
 {
   int i;
   widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
   widget_value **submenu_stack
-    = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
+    = alloca (menu_items_used * sizeof *submenu_stack);
   Lisp_Object *subprefix_stack
   Lisp_Object *subprefix_stack
-    = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
+    = alloca (menu_items_used * sizeof *subprefix_stack);
   int submenu_depth = 0;
 
   int first_pane;
 
   ptrdiff_t specpdl_count = SPECPDL_INDEX ();
 
   int submenu_depth = 0;
 
   int first_pane;
 
   ptrdiff_t specpdl_count = SPECPDL_INDEX ();
 
-  if (! FRAME_X_P (f))
-    abort ();
+  eassert (FRAME_X_P (f));
 
   *error_name = NULL;
 
 
   *error_name = NULL;
 
@@ -1659,6 +1475,8 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
       return Qnil;
     }
 
       return Qnil;
     }
 
+  block_input ();
+
   /* Create a tree of widget_value objects
      representing the panes and their items.  */
   wv = xmalloc_widget_value ();
   /* Create a tree of widget_value objects
      representing the panes and their items.  */
   wv = xmalloc_widget_value ();
@@ -1785,8 +1603,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
          /* If this item has a null value,
             make the call_data null so that it won't display a box
             when the mouse is on it.  */
          /* If this item has a null value,
             make the call_data null so that it won't display a box
             when the mouse is on it.  */
-         wv->call_data
-           = (!NILP (def) ? (void *) &AREF (menu_items, i) : 0);
+         wv->call_data = !NILP (def) ? aref_addr (menu_items, i) : 0;
          wv->enabled = !NILP (enable);
 
          if (NILP (type))
          wv->enabled = !NILP (enable);
 
          if (NILP (type))
@@ -1796,7 +1613,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
          else if (EQ (type, QCradio))
            wv->button_type = BUTTON_TYPE_RADIO;
          else
          else if (EQ (type, QCradio))
            wv->button_type = BUTTON_TYPE_RADIO;
          else
-           abort ();
+           emacs_abort ();
 
          wv->selected = !NILP (selected);
 
 
          wv->selected = !NILP (selected);
 
@@ -1832,7 +1649,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
 #endif
 
       wv_title->name = SSDATA (title);
 #endif
 
       wv_title->name = SSDATA (title);
-      wv_title->enabled = TRUE;
+      wv_title->enabled = true;
       wv_title->button_type = BUTTON_TYPE_NONE;
       wv_title->help = Qnil;
       wv_title->next = wv_sep1;
       wv_title->button_type = BUTTON_TYPE_NONE;
       wv_title->help = Qnil;
       wv_title->next = wv_sep1;
@@ -1844,11 +1661,10 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
 
   /* Make sure to free the widget_value objects we used to specify the
      contents even with longjmp.  */
 
   /* Make sure to free the widget_value objects we used to specify the
      contents even with longjmp.  */
-  record_unwind_protect (cleanup_widget_value_tree,
-                        make_save_value (first_wv, 0));
+  record_unwind_protect_ptr (cleanup_widget_value_tree, first_wv);
 
   /* Actually create and show the menu until popped down.  */
 
   /* Actually create and show the menu until popped down.  */
-  create_and_show_popup_menu (f, first_wv, x, y, for_click, timestamp);
+  create_and_show_popup_menu (f, first_wv, x, y, for_click);
 
   unbind_to (specpdl_count, Qnil);
 
 
   unbind_to (specpdl_count, Qnil);
 
@@ -1887,19 +1703,20 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
            {
              entry
                = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
            {
              entry
                = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
-             if (menu_item_selection == &AREF (menu_items, i))
+             if (menu_item_selection == aref_addr (menu_items, i))
                {
                {
-                 if (keymaps != 0)
+                 if (keymaps)
                    {
                      int j;
 
                    {
                      int j;
 
-                     entry = Fcons (entry, Qnil);
+                     entry = list1 (entry);
                      if (!NILP (prefix))
                        entry = Fcons (prefix, entry);
                      for (j = submenu_depth - 1; j >= 0; j--)
                        if (!NILP (subprefix_stack[j]))
                          entry = Fcons (subprefix_stack[j], entry);
                    }
                      if (!NILP (prefix))
                        entry = Fcons (prefix, entry);
                      for (j = submenu_depth - 1; j >= 0; j--)
                        if (!NILP (subprefix_stack[j]))
                          entry = Fcons (subprefix_stack[j], entry);
                    }
+                 unblock_input ();
                  return entry;
                }
              i += MENU_ITEMS_ITEM_LENGTH;
                  return entry;
                }
              i += MENU_ITEMS_ITEM_LENGTH;
@@ -1907,9 +1724,13 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
        }
     }
   else if (!for_click)
        }
     }
   else if (!for_click)
-    /* Make "Cancel" equivalent to C-g.  */
-    Fsignal (Qquit, Qnil);
+    {
+      unblock_input ();
+      /* Make "Cancel" equivalent to C-g.  */
+      Fsignal (Qquit, Qnil);
+    }
 
 
+  unblock_input ();
   return Qnil;
 }
 \f
   return Qnil;
 }
 \f
@@ -1920,7 +1741,7 @@ dialog_selection_callback (GtkWidget *widget, gpointer client_data)
   /* Treat the pointer as an integer.  There's no problem
      as long as pointers have enough bits to hold small integers.  */
   if ((intptr_t) client_data != -1)
   /* Treat the pointer as an integer.  There's no problem
      as long as pointers have enough bits to hold small integers.  */
   if ((intptr_t) client_data != -1)
-    menu_item_selection = (Lisp_Object *) client_data;
+    menu_item_selection = client_data;
 
   popup_activated_flag = 0;
 }
 
   popup_activated_flag = 0;
 }
@@ -1929,12 +1750,11 @@ dialog_selection_callback (GtkWidget *widget, gpointer client_data)
    dialog pops down.
    menu_item_selection will be set to the selection.  */
 static void
    dialog pops down.
    menu_item_selection will be set to the selection.  */
 static void
-create_and_show_dialog (FRAME_PTR f, widget_value *first_wv)
+create_and_show_dialog (struct frame *f, widget_value *first_wv)
 {
   GtkWidget *menu;
 
 {
   GtkWidget *menu;
 
-  if (! FRAME_X_P (f))
-    abort ();
+  eassert (FRAME_X_P (f));
 
   menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
                            G_CALLBACK (dialog_selection_callback),
 
   menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
                            G_CALLBACK (dialog_selection_callback),
@@ -1944,7 +1764,7 @@ create_and_show_dialog (FRAME_PTR f, widget_value *first_wv)
   if (menu)
     {
       ptrdiff_t specpdl_count = SPECPDL_INDEX ();
   if (menu)
     {
       ptrdiff_t specpdl_count = SPECPDL_INDEX ();
-      record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
+      record_unwind_protect_ptr (pop_down_menu, menu);
 
       /* Display the menu.  */
       gtk_widget_show_all (menu);
 
       /* Display the menu.  */
       gtk_widget_show_all (menu);
@@ -1963,11 +1783,11 @@ dialog_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
   /* Treat the pointer as an integer.  There's no problem
      as long as pointers have enough bits to hold small integers.  */
   if ((intptr_t) client_data != -1)
   /* Treat the pointer as an integer.  There's no problem
      as long as pointers have enough bits to hold small integers.  */
   if ((intptr_t) client_data != -1)
-    menu_item_selection = (Lisp_Object *) client_data;
+    menu_item_selection = client_data;
 
 
-  BLOCK_INPUT;
+  block_input ();
   lw_destroy_all_widgets (id);
   lw_destroy_all_widgets (id);
-  UNBLOCK_INPUT;
+  unblock_input ();
   popup_activated_flag = 0;
 }
 
   popup_activated_flag = 0;
 }
 
@@ -1976,12 +1796,11 @@ dialog_selection_callback (Widget widget, LWLIB_ID id, XtPointer client_data)
    dialog pops down.
    menu_item_selection will be set to the selection.  */
 static void
    dialog pops down.
    menu_item_selection will be set to the selection.  */
 static void
-create_and_show_dialog (FRAME_PTR f, widget_value *first_wv)
+create_and_show_dialog (struct frame *f, widget_value *first_wv)
 {
   LWLIB_ID dialog_id;
 
 {
   LWLIB_ID dialog_id;
 
-  if (!FRAME_X_P (f))
-    abort ();
+  eassert (FRAME_X_P (f));
 
   dialog_id = widget_id_tick++;
 #ifdef USE_LUCID
 
   dialog_id = widget_id_tick++;
 #ifdef USE_LUCID
@@ -2007,8 +1826,7 @@ create_and_show_dialog (FRAME_PTR f, widget_value *first_wv)
                            Fcons (make_number (dialog_id >> (fact)),
                                   make_number (dialog_id & ~(-1 << (fact)))));
 
                            Fcons (make_number (dialog_id >> (fact)),
                                   make_number (dialog_id & ~(-1 << (fact)))));
 
-    popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f),
-                         dialog_id, 1);
+    popup_get_selection (0, FRAME_DISPLAY_INFO (f), dialog_id, 1);
 
     unbind_to (count, Qnil);
   }
 
     unbind_to (count, Qnil);
   }
@@ -2021,8 +1839,8 @@ static const char * button_names [] = {
   "button6", "button7", "button8", "button9", "button10" };
 
 static Lisp_Object
   "button6", "button7", "button8", "button9", "button10" };
 
 static Lisp_Object
-xdialog_show (FRAME_PTR f,
-              int keymaps,
+xdialog_show (struct frame *f,
+              bool keymaps,
               Lisp_Object title,
               Lisp_Object header,
               const char **error_name)
               Lisp_Object title,
               Lisp_Object header,
               const char **error_name)
@@ -2039,8 +1857,7 @@ xdialog_show (FRAME_PTR f,
 
   ptrdiff_t specpdl_count = SPECPDL_INDEX ();
 
 
   ptrdiff_t specpdl_count = SPECPDL_INDEX ();
 
-  if (! FRAME_X_P (f))
-    abort ();
+  eassert (FRAME_X_P (f));
 
   *error_name = NULL;
 
 
   *error_name = NULL;
 
@@ -2107,7 +1924,7 @@ xdialog_show (FRAME_PTR f,
        if (!NILP (descrip))
          wv->key = SSDATA (descrip);
        wv->value = SSDATA (item_name);
        if (!NILP (descrip))
          wv->key = SSDATA (descrip);
        wv->value = SSDATA (item_name);
-       wv->call_data = (void *) &AREF (menu_items, i);
+       wv->call_data = aref_addr (menu_items, i);
        wv->enabled = !NILP (enable);
        wv->help = Qnil;
        prev_wv = wv;
        wv->enabled = !NILP (enable);
        wv->help = Qnil;
        prev_wv = wv;
@@ -2154,8 +1971,7 @@ xdialog_show (FRAME_PTR f,
 
   /* Make sure to free the widget_value objects we used to specify the
      contents even with longjmp.  */
 
   /* Make sure to free the widget_value objects we used to specify the
      contents even with longjmp.  */
-  record_unwind_protect (cleanup_widget_value_tree,
-                        make_save_value (first_wv, 0));
+  record_unwind_protect_ptr (cleanup_widget_value_tree, first_wv);
 
   /* Actually create and show the dialog.  */
   create_and_show_dialog (f, first_wv);
 
   /* Actually create and show the dialog.  */
   create_and_show_dialog (f, first_wv);
@@ -2190,11 +2006,11 @@ xdialog_show (FRAME_PTR f,
            {
              entry
                = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
            {
              entry
                = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
-             if (menu_item_selection == &AREF (menu_items, i))
+             if (menu_item_selection == aref_addr (menu_items, i))
                {
                  if (keymaps != 0)
                    {
                {
                  if (keymaps != 0)
                    {
-                     entry = Fcons (entry, Qnil);
+                     entry = list1 (entry);
                      if (!NILP (prefix))
                        entry = Fcons (prefix, entry);
                    }
                      if (!NILP (prefix))
                        entry = Fcons (prefix, entry);
                    }
@@ -2211,6 +2027,41 @@ xdialog_show (FRAME_PTR f,
   return Qnil;
 }
 
   return Qnil;
 }
 
+Lisp_Object
+xw_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
+{
+  Lisp_Object title;
+  const char *error_name;
+  Lisp_Object selection;
+  ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+
+  check_window_system (f);
+
+  /* Decode the dialog items from what was specified.  */
+  title = Fcar (contents);
+  CHECK_STRING (title);
+  record_unwind_protect_void (unuse_menu_items);
+
+  if (NILP (Fcar (Fcdr (contents))))
+    /* No buttons specified, add an "Ok" button so users can pop down
+       the dialog.  Also, the lesstif/motif version crashes if there are
+       no buttons.  */
+    contents = list2 (title, Fcons (build_string ("Ok"), Qt));
+
+  list_of_panes (list1 (contents));
+
+  /* Display them in a dialog box.  */
+  block_input ();
+  selection = xdialog_show (f, 0, title, header, &error_name);
+  unblock_input ();
+
+  unbind_to (specpdl_count, Qnil);
+  discard_menu_items ();
+
+  if (error_name) error ("%s", error_name);
+  return selection;
+}
+
 #else /* not USE_X_TOOLKIT && not USE_GTK */
 
 /* The frame of the last activated non-toolkit menu bar.
 #else /* not USE_X_TOOLKIT && not USE_GTK */
 
 /* The frame of the last activated non-toolkit menu bar.
@@ -2245,23 +2096,18 @@ menu_help_callback (char const *help_string, int pane, int item)
     pane_name = first_item[MENU_ITEMS_ITEM_NAME];
 
   /* (menu-item MENU-NAME PANE-NUMBER)  */
     pane_name = first_item[MENU_ITEMS_ITEM_NAME];
 
   /* (menu-item MENU-NAME PANE-NUMBER)  */
-  menu_object = Fcons (Qmenu_item,
-                      Fcons (pane_name,
-                             Fcons (make_number (pane), Qnil)));
+  menu_object = list3 (Qmenu_item, pane_name, make_number (pane));
   show_help_echo (help_string ? build_string (help_string) : Qnil,
                  Qnil, menu_object, make_number (item));
 }
 
   show_help_echo (help_string ? build_string (help_string) : Qnil,
                  Qnil, menu_object, make_number (item));
 }
 
-static Lisp_Object
+static void
 pop_down_menu (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));
+  struct frame *f = XSAVE_POINTER (arg, 0);
+  XMenu *menu = XSAVE_POINTER (arg, 1);
 
 
-  FRAME_PTR f = p1->pointer;
-  XMenu *menu = p2->pointer;
-
-  BLOCK_INPUT;
+  block_input ();
 #ifndef MSDOS
   XUngrabPointer (FRAME_X_DISPLAY (f), CurrentTime);
   XUngrabKeyboard (FRAME_X_DISPLAY (f), CurrentTime);
 #ifndef MSDOS
   XUngrabPointer (FRAME_X_DISPLAY (f), CurrentTime);
   XUngrabKeyboard (FRAME_X_DISPLAY (f), CurrentTime);
@@ -2271,25 +2117,23 @@ pop_down_menu (Lisp_Object arg)
 #ifdef HAVE_X_WINDOWS
   /* Assume the mouse has moved out of the X window.
      If it has actually moved in, we will get an EnterNotify.  */
 #ifdef HAVE_X_WINDOWS
   /* Assume the mouse has moved out of the X window.
      If it has actually moved in, we will get an EnterNotify.  */
-  x_mouse_leave (FRAME_X_DISPLAY_INFO (f));
+  x_mouse_leave (FRAME_DISPLAY_INFO (f));
 
   /* State that no mouse buttons are now held.
      (The oldXMenu code doesn't track this info for us.)
      That is not necessarily true, but the fiction leads to reasonable
      results, and it is a pain to ask which are actually held now.  */
 
   /* State that no mouse buttons are now held.
      (The oldXMenu code doesn't track this info for us.)
      That is not necessarily true, but the fiction leads to reasonable
      results, and it is a pain to ask which are actually held now.  */
-  FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+  FRAME_DISPLAY_INFO (f)->grabbed = 0;
 
 #endif /* HAVE_X_WINDOWS */
 
 
 #endif /* HAVE_X_WINDOWS */
 
-  UNBLOCK_INPUT;
-
-  return Qnil;
+  unblock_input ();
 }
 
 
 Lisp_Object
 }
 
 
 Lisp_Object
-xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
-           Lisp_Object title, const char **error_name, Time timestamp)
+xmenu_show (struct frame *f, int x, int y, bool for_click, bool keymaps,
+           Lisp_Object title, const char **error_name)
 {
   Window root;
   XMenu *menu;
 {
   Window root;
   XMenu *menu;
@@ -2304,8 +2148,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
   unsigned int dummy_uint;
   ptrdiff_t specpdl_count = SPECPDL_INDEX ();
 
   unsigned int dummy_uint;
   ptrdiff_t specpdl_count = SPECPDL_INDEX ();
 
-  if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f))
-    abort ();
+  eassert (FRAME_X_P (f) || FRAME_MSDOS_P (f));
 
   *error_name = 0;
   if (menu_items_n_panes == 0)
 
   *error_name = 0;
   if (menu_items_n_panes == 0)
@@ -2317,6 +2160,8 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
       return Qnil;
     }
 
       return Qnil;
     }
 
+  block_input ();
+
   /* Figure out which root window F is on.  */
   XGetGeometry (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &root,
                &dummy_int, &dummy_int, &dummy_uint, &dummy_uint,
   /* Figure out which root window F is on.  */
   XGetGeometry (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &root,
                &dummy_int, &dummy_int, &dummy_uint, &dummy_uint,
@@ -2327,6 +2172,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
   if (menu == NULL)
     {
       *error_name = "Can't create menu";
   if (menu == NULL)
     {
       *error_name = "Can't create menu";
+      unblock_input ();
       return Qnil;
     }
 
       return Qnil;
     }
 
@@ -2370,6 +2216,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
            {
              XMenuDestroy (FRAME_X_DISPLAY (f), menu);
              *error_name = "Can't create pane";
            {
              XMenuDestroy (FRAME_X_DISPLAY (f), menu);
              *error_name = "Can't create pane";
+             unblock_input ();
              return Qnil;
            }
          i += MENU_ITEMS_PANE_LENGTH;
              return Qnil;
            }
          i += MENU_ITEMS_PANE_LENGTH;
@@ -2416,7 +2263,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
            {
              /* if alloca is fast, use that to make the space,
                 to reduce gc needs.  */
            {
              /* if alloca is fast, use that to make the space,
                 to reduce gc needs.  */
-             item_data = (char *) alloca (maxwidth + SBYTES (descrip) + 1);
+             item_data = alloca (maxwidth + SBYTES (descrip) + 1);
              memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
              for (j = SCHARS (item_name); j < maxwidth; j++)
                item_data[j] = ' ';
              memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
              for (j = SCHARS (item_name); j < maxwidth; j++)
                item_data[j] = ' ';
@@ -2434,6 +2281,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
            {
              XMenuDestroy (FRAME_X_DISPLAY (f), menu);
              *error_name = "Can't add selection to menu";
            {
              XMenuDestroy (FRAME_X_DISPLAY (f), menu);
              *error_name = "Can't add selection to menu";
+             unblock_input ();
              return Qnil;
            }
          i += MENU_ITEMS_ITEM_LENGTH;
              return Qnil;
            }
          i += MENU_ITEMS_ITEM_LENGTH;
@@ -2500,9 +2348,7 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
   XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f));
 #endif
 
   XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f));
 #endif
 
-  record_unwind_protect (pop_down_menu,
-                         Fcons (make_save_value (f, 0),
-                                make_save_value (menu, 0)));
+  record_unwind_protect (pop_down_menu, make_save_ptr_ptr (f, menu));
 
   /* Help display under X won't work because XMenuActivate contains
      a loop that doesn't give Emacs a chance to process it.  */
 
   /* Help display under X won't work because XMenuActivate contains
      a loop that doesn't give Emacs a chance to process it.  */
@@ -2539,9 +2385,9 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
                    {
                      entry
                        = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
                    {
                      entry
                        = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
-                     if (keymaps != 0)
+                     if (keymaps)
                        {
                        {
-                         entry = Fcons (entry, Qnil);
+                         entry = list1 (entry);
                          if (!NILP (pane_prefix))
                            entry = Fcons (pane_prefix, entry);
                        }
                          if (!NILP (pane_prefix))
                            entry = Fcons (pane_prefix, entry);
                        }
@@ -2562,10 +2408,14 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
       /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
         the menu was invoked with a mouse event as POSITION).  */
       if (! for_click)
       /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
         the menu was invoked with a mouse event as POSITION).  */
       if (! for_click)
-        Fsignal (Qquit, Qnil);
+       {
+         unblock_input ();
+         Fsignal (Qquit, Qnil);
+       }
       break;
     }
 
       break;
     }
 
+  unblock_input ();
   unbind_to (specpdl_count, Qnil);
 
   return entry;
   unbind_to (specpdl_count, Qnil);
 
   return entry;
@@ -2573,13 +2423,11 @@ xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
 
 #endif /* not USE_X_TOOLKIT */
 
 
 #endif /* not USE_X_TOOLKIT */
 
-#endif /* HAVE_MENUS */
-
 #ifndef MSDOS
 /* Detect if a dialog or menu has been posted.  MSDOS has its own
    implementation on msdos.c.  */
 
 #ifndef MSDOS
 /* Detect if a dialog or menu has been posted.  MSDOS has its own
    implementation on msdos.c.  */
 
-int
+int ATTRIBUTE_CONST
 popup_activated (void)
 {
   return popup_activated_flag;
 popup_activated (void)
 {
   return popup_activated_flag;
@@ -2592,11 +2440,7 @@ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_
        doc: /* Return t if a menu or popup dialog is active.  */)
   (void)
 {
        doc: /* Return t if a menu or popup dialog is active.  */)
   (void)
 {
-#ifdef HAVE_MENUS
   return (popup_activated ()) ? Qt : Qnil;
   return (popup_activated ()) ? Qt : Qnil;
-#else
-  return Qnil;
-#endif /* HAVE_MENUS */
 }
 \f
 void
 }
 \f
 void
@@ -2616,8 +2460,4 @@ syms_of_xmenu (void)
   Ffset (intern_c_string ("accelerate-menu"),
         intern_c_string (Sx_menu_bar_open_internal.symbol_name));
 #endif
   Ffset (intern_c_string ("accelerate-menu"),
         intern_c_string (Sx_menu_bar_open_internal.symbol_name));
 #endif
-
-#ifdef HAVE_MENUS
-  defsubr (&Sx_popup_dialog);
-#endif
 }
 }