Convert (most) functions in src to standard C.
[bpt/emacs.git] / src / xmenu.c
index 6767c1b..deb7c09 100644 (file)
@@ -1,6 +1,6 @@
 /* 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, 2009 Free Software Foundation, Inc.
+                 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -37,6 +37,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #endif
 
 #include <stdio.h>
+#include <setjmp.h>
 
 #include "lisp.h"
 #include "keyboard.h"
@@ -80,6 +81,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #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 */
@@ -107,8 +110,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 Lisp_Object Qdebug_on_next_call;
 
-extern Lisp_Object Vmenu_updating_frame;
-
 extern Lisp_Object Qmenu_bar;
 
 extern Lisp_Object QCtoggle, QCradio;
@@ -121,24 +122,22 @@ 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));
+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
-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
 
-static int update_frame_menubar P_ ((struct frame *));
-static Lisp_Object xmenu_show P_ ((struct frame *, int, int, int, int,
-                                  Lisp_Object, char **));
+static int update_frame_menubar (struct frame *);
 \f
 /* Flag which when set indicates a dialog or menu has been posted by
    Xt on behalf of one of the widget sets.  */
@@ -148,8 +147,8 @@ static int next_menubar_widget_id;
 
 /* 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 P_ ((void));
-extern widget_value *digest_single_submenu P_ ((int, int, int));
+extern widget_value *xmalloc_widget_value (void);
+extern widget_value *digest_single_submenu (int, int, int);
 #endif
 
 /* This is set nonzero after the user activates the menu bar, and set
@@ -196,11 +195,8 @@ menubar_id_to_frame (id)
    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;
@@ -239,282 +235,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;
-         void (*mouse_position_hook) P_ ((struct frame **, int,
-                                          Lisp_Object *,
-                                          enum scroll_bar_part *,
-                                          Lisp_Object *,
-                                          Lisp_Object *,
-                                          unsigned long *)) =
-           new_f->terminal->mouse_position_hook;
-
-         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) && ! FRAME_MSDOS_P (f))
-        error ("Can not put X menu on this 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,
@@ -604,6 +324,17 @@ for instance using the window manager, then this produces a quit and
   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.  */
@@ -657,8 +388,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;
@@ -673,8 +403,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
@@ -690,7 +418,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;
@@ -703,17 +431,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 */
@@ -908,9 +634,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;
 
@@ -938,8 +662,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 ();
@@ -994,9 +717,7 @@ 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;
 }
@@ -1016,10 +737,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;
 
@@ -1057,9 +775,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;
@@ -1109,9 +825,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;
 
@@ -1173,8 +887,7 @@ menubar_selection_callback (widget, id, client_data)
    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);
@@ -1222,15 +935,50 @@ update_frame_menubar (f)
   return 1;
 }
 
+#ifdef USE_LUCID
+static void
+apply_systemfont_to_dialog (w)
+     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 (w)
+     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
@@ -1534,6 +1282,7 @@ set_frame_menubar (f, first_time, deep_p)
 
       /* Make menu pop down on C-g.  */
       XtOverrideTranslations (menubar_widget, override);
+      apply_systemfont_to_menu (menubar_widget);
     }
 
   {
@@ -1543,8 +1292,10 @@ set_frame_menubar (f, first_time, deep_p)
            + 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 theses pixel.  Jan D, oct 2009.  */
 #ifdef USE_LUCID
     if (FRAME_EXTERNAL_MENU_BAR (f))
       {
@@ -1554,7 +1305,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;
   }
@@ -1576,8 +1327,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.  */
@@ -1687,12 +1437,7 @@ 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;
@@ -1713,9 +1458,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;
 
@@ -1724,8 +1467,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);
 
@@ -1740,12 +1482,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;
@@ -1787,11 +1524,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.  */
@@ -1850,12 +1589,13 @@ 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)
+create_and_show_popup_menu (f, first_wv, x, y, for_click, timestamp)
      FRAME_PTR f;
      widget_value *first_wv;
      int x;
      int y;
      int for_click;
+     EMACS_UINT timestamp;
 {
   int i;
   Arg av[2];
@@ -1874,6 +1614,8 @@ create_and_show_popup_menu (f, first_wv, x, y, for_click)
                            popup_deactivate_callback,
                            menu_highlight_callback);
 
+  apply_systemfont_to_menu (menu);
+
   dummy.type = ButtonPress;
   dummy.serial = 0;
   dummy.send_event = 0;
@@ -1923,15 +1665,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;
@@ -2138,7 +1874,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);
@@ -2206,9 +1942,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.  */
@@ -2222,9 +1956,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;
 
@@ -2284,11 +2016,13 @@ create_and_show_dialog (f, first_wv)
     abort();
 
   dialog_id = widget_id_tick++;
+#ifdef HAVE_XFT
+  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;
@@ -2319,11 +2053,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];
@@ -2448,14 +2178,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);
 
@@ -2591,14 +2313,15 @@ pop_down_menu (arg)
 }
 
 
-static Lisp_Object
-xmenu_show (f, x, y, for_click, keymaps, title, error)
+Lisp_Object
+xmenu_show (f, x, y, for_click, keymaps, title, error, timestamp)
      FRAME_PTR f;
      int x, y;
      int for_click;
      int keymaps;
      Lisp_Object title;
      char **error;
+     EMACS_UINT timestamp;
 {
   Window root;
   XMenu *menu;
@@ -2892,7 +2615,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;
 }
@@ -2911,9 +2634,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)
 {
-  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
@@ -2921,13 +2644,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