1 /* X Communication module for terminals which understand the X protocol.
   2    Copyright (C) 1986, 1988, 1993, 1994, 1996, 1999, 2000, 2001, 2002, 2003,
   3                  2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
   4 
   5 This file is part of GNU Emacs.
   6 
   7 GNU Emacs is free software: you can redistribute it and/or modify
   8 it under the terms of the GNU General Public License as published by
   9 the Free Software Foundation, either version 3 of the License, or
  10 (at your option) any later version.
  11 
  12 GNU Emacs is distributed in the hope that it will be useful,
  13 but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 GNU General Public License for more details.
  16 
  17 You should have received a copy of the GNU General Public License
  18 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
  19 
  20 /* X pop-up deck-of-cards menu facility for GNU Emacs.
  21  *
  22  * Written by Jon Arnold and Roman Budzianowski
  23  * Mods and rewrite by Robert Krawitz
  24  *
  25  */
  26 
  27 /* Modified by Fred Pierresteguy on December 93
  28    to make the popup menus and menubar use the Xt.  */
  29 
  30 /* Rewritten for clarity and GC protection by rms in Feb 94.  */
  31 
  32 #include <config.h>
  33 
  34 #if 0  /* Why was this included?  And without syssignal.h?  */
  35 /* On 4.3 this loses if it comes after xterm.h.  */
  36 #include <signal.h>
  37 #endif
  38 
  39 #include <stdio.h>
  40 #include <setjmp.h>
  41 
  42 #include "lisp.h"
  43 #include "keyboard.h"
  44 #include "keymap.h"
  45 #include "frame.h"
  46 #include "termhooks.h"
  47 #include "window.h"
  48 #include "blockinput.h"
  49 #include "buffer.h"
  50 #include "charset.h"
  51 #include "coding.h"
  52 #include "sysselect.h"
  53 
  54 #ifdef MSDOS
  55 #include "msdos.h"
  56 #endif
  57 
  58 #ifdef HAVE_X_WINDOWS
  59 /* This may include sys/types.h, and that somehow loses
  60    if this is not done before the other system files.  */
  61 #include "xterm.h"
  62 #endif
  63 
  64 /* Load sys/types.h if not already loaded.
  65    In some systems loading it twice is suicidal.  */
  66 #ifndef makedev
  67 #include <sys/types.h>
  68 #endif
  69 
  70 #include "dispextern.h"
  71 
  72 #ifdef HAVE_X_WINDOWS
  73 /*  Defining HAVE_MULTILINGUAL_MENU would mean that the toolkit menu
  74     code accepts the Emacs internal encoding.  */
  75 #undef HAVE_MULTILINGUAL_MENU
  76 #ifdef USE_X_TOOLKIT
  77 #include "widget.h"
  78 #include <X11/Xlib.h>
  79 #include <X11/IntrinsicP.h>
  80 #include <X11/CoreP.h>
  81 #include <X11/StringDefs.h>
  82 #include <X11/Shell.h>
  83 #ifdef USE_LUCID
  84 #include "xsettings.h"
  85 #include "../lwlib/xlwmenu.h"
  86 #ifdef HAVE_XAW3D
  87 #include <X11/Xaw3d/Paned.h>
  88 #else /* !HAVE_XAW3D */
  89 #include <X11/Xaw/Paned.h>
  90 #endif /* HAVE_XAW3D */
  91 #endif /* USE_LUCID */
  92 #include "../lwlib/lwlib.h"
  93 #else /* not USE_X_TOOLKIT */
  94 #ifndef USE_GTK
  95 #include "../oldXMenu/XMenu.h"
  96 #endif
  97 #endif /* not USE_X_TOOLKIT */
  98 #endif /* HAVE_X_WINDOWS */
  99 
 100 #ifdef USE_GTK
 101 #include "gtkutil.h"
 102 #endif
 103 
 104 #include "menu.h"
 105 
 106 #ifndef TRUE
 107 #define TRUE 1
 108 #define FALSE 0
 109 #endif /* no TRUE */
 110 
 111 Lisp_Object Qdebug_on_next_call;
 112 
 113 extern Lisp_Object Qmenu_bar;
 114 
 115 extern Lisp_Object QCtoggle, QCradio;
 116 
 117 extern Lisp_Object Voverriding_local_map;
 118 extern Lisp_Object Voverriding_local_map_menu_flag;
 119 
 120 extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 121 
 122 extern Lisp_Object Qmenu_bar_update_hook;
 123 
 124 #ifdef USE_X_TOOLKIT
 125 extern void set_frame_menubar P_ ((FRAME_PTR, int, int));
 126 extern XtAppContext Xt_app_con;
 127 
 128 static Lisp_Object xdialog_show P_ ((FRAME_PTR, int, Lisp_Object, Lisp_Object,
 129                                      char **));
 130 static void popup_get_selection P_ ((XEvent *, struct x_display_info *,
 131                                      LWLIB_ID, int));
 132 #endif /* USE_X_TOOLKIT */
 133 
 134 #ifdef USE_GTK
 135 extern void set_frame_menubar P_ ((FRAME_PTR, int, int));
 136 static Lisp_Object xdialog_show P_ ((FRAME_PTR, int, Lisp_Object, Lisp_Object,
 137                                      char **));
 138 #endif
 139 
 140 static int update_frame_menubar P_ ((struct frame *));
 141 
 142 /* Flag which when set indicates a dialog or menu has been posted by
 143    Xt on behalf of one of the widget sets.  */
 144 static int popup_activated_flag;
 145 
 146 static int next_menubar_widget_id;
 147 
 148 /* For NS and NTGUI, these prototypes are defined in keyboard.h.  */
 149 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
 150 extern widget_value *xmalloc_widget_value P_ ((void));
 151 extern widget_value *digest_single_submenu P_ ((int, int, int));
 152 #endif
 153 
 154 /* This is set nonzero after the user activates the menu bar, and set
 155    to zero again after the menu bars are redisplayed by prepare_menu_bar.
 156    While it is nonzero, all calls to set_frame_menubar go deep.
 157 
 158    I don't understand why this is needed, but it does seem to be
 159    needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>.  */
 160 
 161 int pending_menu_activation;
 162 
 163 #ifdef USE_X_TOOLKIT
 164 
 165 /* Return the frame whose ->output_data.x->id equals ID, or 0 if none.  */
 166 
 167 static struct frame *
 168 menubar_id_to_frame (id)
 169      LWLIB_ID id;
 170 {
 171   Lisp_Object tail, frame;
 172   FRAME_PTR f;
 173 
 174   for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
 175     {
 176       frame = XCAR (tail);
 177       if (!FRAMEP (frame))
 178         continue;
 179       f = XFRAME (frame);
 180       if (!FRAME_WINDOW_P (f))
 181         continue;
 182       if (f->output_data.x->id == id)
 183         return f;
 184     }
 185   return 0;
 186 }
 187 
 188 #endif
 189 
 190 #ifdef HAVE_X_WINDOWS
 191 /* Return the mouse position in *X and *Y.  The coordinates are window
 192    relative for the edit window in frame F.
 193    This is for Fx_popup_menu.  The mouse_position_hook can not
 194    be used for X, as it returns window relative coordinates
 195    for the window where the mouse is in.  This could be the menu bar,
 196    the scroll bar or the edit window.  Fx_popup_menu needs to be
 197    sure it is the edit window.  */
 198 void
 199 mouse_position_for_popup (f, x, y)
 200      FRAME_PTR f;
 201      int *x;
 202      int *y;
 203 {
 204   Window root, dummy_window;
 205   int dummy;
 206 
 207   if (! FRAME_X_P (f))
 208     abort ();
 209 
 210   BLOCK_INPUT;
 211 
 212   XQueryPointer (FRAME_X_DISPLAY (f),
 213                  DefaultRootWindow (FRAME_X_DISPLAY (f)),
 214 
 215                  /* The root window which contains the pointer.  */
 216                  &root,
 217 
 218                  /* Window pointer is on, not used  */
 219                  &dummy_window,
 220 
 221                  /* The position on that root window.  */
 222                  x, y,
 223 
 224                  /* x/y in dummy_window coordinates, not used.  */
 225                  &dummy, &dummy,
 226 
 227                  /* Modifier keys and pointer buttons, about which
 228                     we don't care.  */
 229                  (unsigned int *) &dummy);
 230 
 231   UNBLOCK_INPUT;
 232 
 233   /* xmenu_show expects window coordinates, not root window
 234      coordinates.  Translate.  */
 235   *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
 236   *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
 237 }
 238 
 239 #endif /* HAVE_X_WINDOWS */
 240 
 241 #ifdef HAVE_MENUS
 242 
 243 DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
 244        doc: /* Pop up a dialog box and return user's selection.
 245 POSITION specifies which frame to use.
 246 This is normally a mouse button event or a window or frame.
 247 If POSITION is t, it means to use the frame the mouse is on.
 248 The dialog box appears in the middle of the specified frame.
 249 
 250 CONTENTS specifies the alternatives to display in the dialog box.
 251 It is a list of the form (DIALOG ITEM1 ITEM2...).
 252 Each ITEM is a cons cell (STRING . VALUE).
 253 The return value is VALUE from the chosen item.
 254 
 255 An ITEM may also be just a string--that makes a nonselectable item.
 256 An ITEM may also be nil--that means to put all preceding items
 257 on the left of the dialog box and all following items on the right.
 258 \(By default, approximately half appear on each side.)
 259 
 260 If HEADER is non-nil, the frame title for the box is "Information",
 261 otherwise it is "Question".
 262 
 263 If the user gets rid of the dialog box without making a valid choice,
 264 for instance using the window manager, then this produces a quit and
 265 `x-popup-dialog' does not return.  */)
 266      (position, contents, header)
 267      Lisp_Object position, contents, header;
 268 {
 269   FRAME_PTR f = NULL;
 270   Lisp_Object window;
 271 
 272   check_x ();
 273 
 274   /* Decode the first argument: find the window or frame to use.  */
 275   if (EQ (position, Qt)
 276       || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
 277                                || EQ (XCAR (position), Qtool_bar))))
 278     {
 279 #if 0 /* Using the frame the mouse is on may not be right.  */
 280       /* Use the mouse's current position.  */
 281       FRAME_PTR new_f = SELECTED_FRAME ();
 282       Lisp_Object bar_window;
 283       enum scroll_bar_part part;
 284       unsigned long time;
 285       Lisp_Object x, y;
 286 
 287       (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
 288 
 289       if (new_f != 0)
 290         XSETFRAME (window, new_f);
 291       else
 292         window = selected_window;
 293 #endif
 294       window = selected_window;
 295     }
 296   else if (CONSP (position))
 297     {
 298       Lisp_Object tem;
 299       tem = Fcar (position);
 300       if (CONSP (tem))
 301         window = Fcar (Fcdr (position));
 302       else
 303         {
 304           tem = Fcar (Fcdr (position));  /* EVENT_START (position) */
 305           window = Fcar (tem);       /* POSN_WINDOW (tem) */
 306         }
 307     }
 308   else if (WINDOWP (position) || FRAMEP (position))
 309     window = position;
 310   else
 311     window = Qnil;
 312 
 313   /* Decode where to put the menu.  */
 314 
 315   if (FRAMEP (window))
 316     f = XFRAME (window);
 317   else if (WINDOWP (window))
 318     {
 319       CHECK_LIVE_WINDOW (window);
 320       f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
 321     }
 322   else
 323     /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
 324        but I don't want to make one now.  */
 325     CHECK_WINDOW (window);
 326 
 327   if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f))
 328     error ("Can not put X dialog on this terminal");
 329 
 330   /* Force a redisplay before showing the dialog.  If a frame is created
 331      just before showing the dialog, its contents may not have been fully
 332      drawn, as this depends on timing of events from the X server.  Redisplay
 333      is not done when a dialog is shown.  If redisplay could be done in the
 334      X event loop (i.e. the X event loop does not run in a signal handler)
 335      this would not be needed.
 336 
 337      Do this before creating the widget value that points to Lisp
 338      string contents, because Fredisplay may GC and relocate them.  */
 339   Fredisplay (Qt);
 340 
 341 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
 342   /* Display a menu with these alternatives
 343      in the middle of frame F.  */
 344   {
 345     Lisp_Object x, y, frame, newpos;
 346     XSETFRAME (frame, f);
 347     XSETINT (x, x_pixel_width (f) / 2);
 348     XSETINT (y, x_pixel_height (f) / 2);
 349     newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
 350 
 351     return Fx_popup_menu (newpos,
 352                           Fcons (Fcar (contents), Fcons (contents, Qnil)));
 353   }
 354 #else
 355   {
 356     Lisp_Object title;
 357     char *error_name;
 358     Lisp_Object selection;
 359     int specpdl_count = SPECPDL_INDEX ();
 360 
 361     /* Decode the dialog items from what was specified.  */
 362     title = Fcar (contents);
 363     CHECK_STRING (title);
 364     record_unwind_protect (unuse_menu_items, Qnil);
 365 
 366     if (NILP (Fcar (Fcdr (contents))))
 367       /* No buttons specified, add an "Ok" button so users can pop down
 368          the dialog.  Also, the lesstif/motif version crashes if there are
 369          no buttons.  */
 370       contents = Fcons (title, Fcons (Fcons (build_string ("Ok"), Qt), Qnil));
 371 
 372     list_of_panes (Fcons (contents, Qnil));
 373 
 374     /* Display them in a dialog box.  */
 375     BLOCK_INPUT;
 376     selection = xdialog_show (f, 0, title, header, &error_name);
 377     UNBLOCK_INPUT;
 378 
 379     unbind_to (specpdl_count, Qnil);
 380     discard_menu_items ();
 381 
 382     if (error_name) error (error_name);
 383     return selection;
 384   }
 385 #endif
 386 }
 387 
 388 
 389 #ifndef MSDOS
 390 
 391 /* Set menu_items_inuse so no other popup menu or dialog is created.  */
 392 
 393 void
 394 x_menu_set_in_use (in_use)
 395      int in_use;
 396 {
 397   menu_items_inuse = in_use ? Qt : Qnil;
 398   popup_activated_flag = in_use;
 399 #ifdef USE_X_TOOLKIT
 400   if (popup_activated_flag)
 401     x_activate_timeout_atimer ();
 402 #endif
 403 }
 404 
 405 /* Wait for an X event to arrive or for a timer to expire.  */
 406 
 407 void
 408 x_menu_wait_for_event (void *data)
 409 {
 410   /* Another way to do this is to register a timer callback, that can be
 411      done in GTK and Xt.  But we have to do it like this when using only X
 412      anyway, and with callbacks we would have three variants for timer handling
 413      instead of the small ifdefs below.  */
 414 
 415   while (
 416 #ifdef USE_X_TOOLKIT
 417          ! XtAppPending (Xt_app_con)
 418 #elif defined USE_GTK
 419          ! gtk_events_pending ()
 420 #else
 421          ! XPending ((Display*) data)
 422 #endif
 423          )
 424     {
 425       EMACS_TIME next_time = timer_check (1), *ntp;
 426       long secs = EMACS_SECS (next_time);
 427       long usecs = EMACS_USECS (next_time);
 428       SELECT_TYPE read_fds;
 429       struct x_display_info *dpyinfo;
 430       int n = 0;
 431 
 432       FD_ZERO (&read_fds);
 433       for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
 434         {
 435           int fd = ConnectionNumber (dpyinfo->display);
 436           FD_SET (fd, &read_fds);
 437           if (fd > n) n = fd;
 438           XFlush (dpyinfo->display);
 439         }
 440 
 441       if (secs < 0 && usecs < 0)
 442         ntp = 0;
 443       else
 444         ntp = &next_time;
 445 
 446       select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, ntp);
 447     }
 448 }
 449 #endif /* ! MSDOS */
 450 
 451 
 452 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
 453 
 454 #ifdef USE_X_TOOLKIT
 455 
 456 /* Loop in Xt until the menu pulldown or dialog popup has been
 457    popped down (deactivated).  This is used for x-popup-menu
 458    and x-popup-dialog; it is not used for the menu bar.
 459 
 460    NOTE: All calls to popup_get_selection should be protected
 461    with BLOCK_INPUT, UNBLOCK_INPUT wrappers.  */
 462 
 463 static void
 464 popup_get_selection (initial_event, dpyinfo, id, do_timers)
 465      XEvent *initial_event;
 466      struct x_display_info *dpyinfo;
 467      LWLIB_ID id;
 468      int do_timers;
 469 {
 470   XEvent event;
 471 
 472   while (popup_activated_flag)
 473     {
 474       if (initial_event)
 475         {
 476           event = *initial_event;
 477           initial_event = 0;
 478         }
 479       else
 480         {
 481           if (do_timers) x_menu_wait_for_event (0);
 482           XtAppNextEvent (Xt_app_con, &event);
 483         }
 484 
 485       /* Make sure we don't consider buttons grabbed after menu goes.
 486          And make sure to deactivate for any ButtonRelease,
 487          even if XtDispatchEvent doesn't do that.  */
 488       if (event.type == ButtonRelease
 489           && dpyinfo->display == event.xbutton.display)
 490         {
 491           dpyinfo->grabbed &= ~(1 << event.xbutton.button);
 492 #ifdef USE_MOTIF /* Pretending that the event came from a
 493                     Btn1Down seems the only way to convince Motif to
 494                     activate its callbacks; setting the XmNmenuPost
 495                     isn't working. --marcus@sysc.pdx.edu.  */
 496           event.xbutton.button = 1;
 497           /*  Motif only pops down menus when no Ctrl, Alt or Mod
 498               key is pressed and the button is released.  So reset key state
 499               so Motif thinks this is the case.  */
 500           event.xbutton.state = 0;
 501 #endif
 502         }
 503       /* Pop down on C-g and Escape.  */
 504       else if (event.type == KeyPress
 505                && dpyinfo->display == event.xbutton.display)
 506         {
 507           KeySym keysym = XLookupKeysym (&event.xkey, 0);
 508 
 509           if ((keysym == XK_g && (event.xkey.state & ControlMask) != 0)
 510               || keysym == XK_Escape) /* Any escape, ignore modifiers.  */
 511             popup_activated_flag = 0;
 512         }
 513 
 514       x_dispatch_event (&event, event.xany.display);
 515     }
 516 }
 517 
 518 DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_internal, 0, 1, "i",
 519        doc: /* Start key navigation of the menu bar in FRAME.
 520 This initially opens the first menu bar item and you can then navigate with the
 521 arrow keys, select a menu entry with the return key or cancel with the
 522 escape key.  If FRAME has no menu bar this function does nothing.
 523 
 524 If FRAME is nil or not given, use the selected frame.  */)
 525      (frame)
 526      Lisp_Object frame;
 527 {
 528   XEvent ev;
 529   FRAME_PTR f = check_x_frame (frame);
 530   Widget menubar;
 531   BLOCK_INPUT;
 532 
 533   if (FRAME_EXTERNAL_MENU_BAR (f))
 534     set_frame_menubar (f, 0, 1);
 535 
 536   menubar = FRAME_X_OUTPUT (f)->menubar_widget;
 537   if (menubar)
 538     {
 539       Window child;
 540       int error_p = 0;
 541 
 542       x_catch_errors (FRAME_X_DISPLAY (f));
 543       memset (&ev, 0, sizeof ev);
 544       ev.xbutton.display = FRAME_X_DISPLAY (f);
 545       ev.xbutton.window = XtWindow (menubar);
 546       ev.xbutton.root = FRAME_X_DISPLAY_INFO (f)->root_window;
 547       ev.xbutton.time = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
 548       ev.xbutton.button = Button1;
 549       ev.xbutton.x = ev.xbutton.y = FRAME_MENUBAR_HEIGHT (f) / 2;
 550       ev.xbutton.same_screen = True;
 551 
 552 #ifdef USE_MOTIF
 553       {
 554         Arg al[2];
 555         WidgetList list;
 556         Cardinal nr;
 557         XtSetArg (al[0], XtNchildren, &list);
 558         XtSetArg (al[1], XtNnumChildren, &nr);
 559         XtGetValues (menubar, al, 2);
 560         ev.xbutton.window = XtWindow (list[0]);
 561       }
 562 #endif
 563 
 564       XTranslateCoordinates (FRAME_X_DISPLAY (f),
 565                              /* From-window, to-window.  */
 566                              ev.xbutton.window, ev.xbutton.root,
 567 
 568                              /* From-position, to-position.  */
 569                              ev.xbutton.x, ev.xbutton.y,
 570                              &ev.xbutton.x_root, &ev.xbutton.y_root,
 571 
 572                              /* Child of win.  */
 573                              &child);
 574       error_p = x_had_errors_p (FRAME_X_DISPLAY (f));
 575       x_uncatch_errors ();
 576 
 577       if (! error_p)
 578         {
 579           ev.type = ButtonPress;
 580           ev.xbutton.state = 0;
 581 
 582           XtDispatchEvent (&ev);
 583           ev.xbutton.type = ButtonRelease;
 584           ev.xbutton.state = Button1Mask;
 585           XtDispatchEvent (&ev);
 586         }
 587     }
 588 
 589   UNBLOCK_INPUT;
 590 
 591   return Qnil;
 592 }
 593 #endif /* USE_X_TOOLKIT */
 594 
 595 
 596 #ifdef USE_GTK
 597 DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_internal, 0, 1, "i",
 598        doc: /* Start key navigation of the menu bar in FRAME.
 599 This initially opens the first menu bar item and you can then navigate with the
 600 arrow keys, select a menu entry with the return key or cancel with the
 601 escape key.  If FRAME has no menu bar this function does nothing.
 602 
 603 If FRAME is nil or not given, use the selected frame.  */)
 604      (frame)
 605      Lisp_Object frame;
 606 {
 607   GtkWidget *menubar;
 608   FRAME_PTR f;
 609 
 610   /* gcc 2.95 doesn't accept the FRAME_PTR declaration after
 611      BLOCK_INPUT.  */
 612 
 613   BLOCK_INPUT;
 614   f = check_x_frame (frame);
 615 
 616   if (FRAME_EXTERNAL_MENU_BAR (f))
 617     set_frame_menubar (f, 0, 1);
 618 
 619   menubar = FRAME_X_OUTPUT (f)->menubar_widget;
 620   if (menubar)
 621     {
 622       /* Activate the first menu.  */
 623       GList *children = gtk_container_get_children (GTK_CONTAINER (menubar));
 624 
 625       if (children)
 626         {
 627           g_signal_emit_by_name (children->data, "activate_item");
 628           popup_activated_flag = 1;
 629           g_list_free (children);
 630         }
 631     }
 632   UNBLOCK_INPUT;
 633 
 634   return Qnil;
 635 }
 636 
 637 /* Loop util popup_activated_flag is set to zero in a callback.
 638    Used for popup menus and dialogs. */
 639 
 640 static void
 641 popup_widget_loop (do_timers, widget)
 642      int do_timers;
 643      GtkWidget *widget;
 644 {
 645   ++popup_activated_flag;
 646 
 647   /* Process events in the Gtk event loop until done.  */
 648   while (popup_activated_flag)
 649     {
 650       if (do_timers) x_menu_wait_for_event (0);
 651       gtk_main_iteration ();
 652     }
 653 }
 654 #endif
 655 
 656 /* Activate the menu bar of frame F.
 657    This is called from keyboard.c when it gets the
 658    MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
 659 
 660    To activate the menu bar, we use the X button-press event
 661    that was saved in saved_menu_event.
 662    That makes the toolkit do its thing.
 663 
 664    But first we recompute the menu bar contents (the whole tree).
 665 
 666    The reason for saving the button event until here, instead of
 667    passing it to the toolkit right away, is that we can safely
 668    execute Lisp code.  */
 669 
 670 void
 671 x_activate_menubar (f)
 672      FRAME_PTR f;
 673 {
 674   if (! FRAME_X_P (f))
 675     abort ();
 676 
 677   if (!f->output_data.x->saved_menu_event->type)
 678     return;
 679 
 680 #ifdef USE_GTK
 681   if (! xg_win_to_widget (FRAME_X_DISPLAY (f),
 682                           f->output_data.x->saved_menu_event->xany.window))
 683     return;
 684 #endif
 685 
 686   set_frame_menubar (f, 0, 1);
 687   BLOCK_INPUT;
 688 #ifdef USE_GTK
 689   XPutBackEvent (f->output_data.x->display_info->display,
 690                  f->output_data.x->saved_menu_event);
 691   popup_activated_flag = 1;
 692 #else
 693   XtDispatchEvent (f->output_data.x->saved_menu_event);
 694 #endif
 695   UNBLOCK_INPUT;
 696 #ifdef USE_MOTIF
 697   if (f->output_data.x->saved_menu_event->type == ButtonRelease)
 698     pending_menu_activation = 1;
 699 #endif
 700 
 701   /* Ignore this if we get it a second time.  */
 702   f->output_data.x->saved_menu_event->type = 0;
 703 }
 704 
 705 /* This callback is invoked when the user selects a menubar cascade
 706    pushbutton, but before the pulldown menu is posted.  */
 707 
 708 #ifndef USE_GTK
 709 static void
 710 popup_activate_callback (widget, id, client_data)
 711      Widget widget;
 712      LWLIB_ID id;
 713      XtPointer client_data;
 714 {
 715   popup_activated_flag = 1;
 716 #ifdef USE_X_TOOLKIT
 717   x_activate_timeout_atimer ();
 718 #endif
 719 }
 720 #endif
 721 
 722 /* This callback is invoked when a dialog or menu is finished being
 723    used and has been unposted.  */
 724 
 725 #ifdef USE_GTK
 726 static void
 727 popup_deactivate_callback (widget, client_data)
 728      GtkWidget *widget;
 729      gpointer client_data;
 730 {
 731   popup_activated_flag = 0;
 732 }
 733 #else
 734 static void
 735 popup_deactivate_callback (widget, id, client_data)
 736      Widget widget;
 737      LWLIB_ID id;
 738      XtPointer client_data;
 739 {
 740   popup_activated_flag = 0;
 741 }
 742 #endif
 743 
 744 
 745 /* Function that finds the frame for WIDGET and shows the HELP text
 746    for that widget.
 747    F is the frame if known, or NULL if not known.  */
 748 static void
 749 show_help_event (f, widget, help)
 750      FRAME_PTR f;
 751      xt_or_gtk_widget widget;
 752      Lisp_Object help;
 753 {
 754   Lisp_Object frame;
 755 
 756   if (f)
 757     {
 758       XSETFRAME (frame, f);
 759       kbd_buffer_store_help_event (frame, help);
 760     }
 761   else
 762     {
 763 #if 0  /* This code doesn't do anything useful.  ++kfs */
 764       /* WIDGET is the popup menu.  It's parent is the frame's
 765          widget.  See which frame that is.  */
 766       xt_or_gtk_widget frame_widget = XtParent (widget);
 767       Lisp_Object tail;
 768 
 769       for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
 770         {
 771           frame = XCAR (tail);
 772           if (FRAMEP (frame)
 773               && (f = XFRAME (frame),
 774                   FRAME_X_P (f) && f->output_data.x->widget == frame_widget))
 775             break;
 776         }
 777 #endif
 778       show_help_echo (help, Qnil, Qnil, Qnil, 1);
 779     }
 780 }
 781 
 782 /* Callback called when menu items are highlighted/unhighlighted
 783    while moving the mouse over them.  WIDGET is the menu bar or menu
 784    popup widget.  ID is its LWLIB_ID.  CALL_DATA contains a pointer to
 785    the data structure for the menu item, or null in case of
 786    unhighlighting.  */
 787 
 788 #ifdef USE_GTK
 789 void
 790 menu_highlight_callback (widget, call_data)
 791      GtkWidget *widget;
 792      gpointer call_data;
 793 {
 794   xg_menu_item_cb_data *cb_data;
 795   Lisp_Object help;
 796 
 797   cb_data = (xg_menu_item_cb_data*) g_object_get_data (G_OBJECT (widget),
 798                                                        XG_ITEM_DATA);
 799   if (! cb_data) return;
 800 
 801   help = call_data ? cb_data->help : Qnil;
 802 
 803   /* If popup_activated_flag is greater than 1 we are in a popup menu.
 804      Don't show help for them, they won't appear before the
 805      popup is popped down.  */
 806   if (popup_activated_flag <= 1)
 807     show_help_event (cb_data->cl_data->f, widget, help);
 808 }
 809 #else
 810 void
 811 menu_highlight_callback (widget, id, call_data)
 812      Widget widget;
 813      LWLIB_ID id;
 814      void *call_data;
 815 {
 816   struct frame *f;
 817   Lisp_Object help;
 818 
 819   widget_value *wv = (widget_value *) call_data;
 820 
 821   help = wv ? wv->help : Qnil;
 822 
 823   /* Determine the frame for the help event.  */
 824   f = menubar_id_to_frame (id);
 825 
 826   show_help_event (f, widget, help);
 827 }
 828 #endif
 829 
 830 #ifdef USE_GTK
 831 /* Gtk calls callbacks just because we tell it what item should be
 832    selected in a radio group.  If this variable is set to a non-zero
 833    value, we are creating menus and don't want callbacks right now.
 834 */
 835 static int xg_crazy_callback_abort;
 836 
 837 /* This callback is called from the menu bar pulldown menu
 838    when the user makes a selection.
 839    Figure out what the user chose
 840    and put the appropriate events into the keyboard buffer.  */
 841 static void
 842 menubar_selection_callback (widget, client_data)
 843      GtkWidget *widget;
 844      gpointer client_data;
 845 {
 846   xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
 847 
 848   if (xg_crazy_callback_abort)
 849     return;
 850 
 851   if (! cb_data || ! cb_data->cl_data || ! cb_data->cl_data->f)
 852     return;
 853 
 854   /* For a group of radio buttons, GTK calls the selection callback first
 855      for the item that was active before the selection and then for the one that
 856      is active after the selection.  For C-h k this means we get the help on
 857      the deselected item and then the selected item is executed.  Prevent that
 858      by ignoring the non-active item.  */
 859   if (GTK_IS_RADIO_MENU_ITEM (widget)
 860       && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
 861     return;
 862 
 863   /* When a menu is popped down, X generates a focus event (i.e. focus
 864      goes back to the frame below the menu).  Since GTK buffers events,
 865      we force it out here before the menu selection event.  Otherwise
 866      sit-for will exit at once if the focus event follows the menu selection
 867      event.  */
 868 
 869   BLOCK_INPUT;
 870   while (gtk_events_pending ())
 871     gtk_main_iteration ();
 872   UNBLOCK_INPUT;
 873 
 874   find_and_call_menu_selection (cb_data->cl_data->f,
 875                                 cb_data->cl_data->menu_bar_items_used,
 876                                 cb_data->cl_data->menu_bar_vector,
 877                                 cb_data->call_data);
 878 }
 879 
 880 #else /* not USE_GTK */
 881 
 882 /* This callback is called from the menu bar pulldown menu
 883    when the user makes a selection.
 884    Figure out what the user chose
 885    and put the appropriate events into the keyboard buffer.  */
 886 static void
 887 menubar_selection_callback (widget, id, client_data)
 888      Widget widget;
 889      LWLIB_ID id;
 890      XtPointer client_data;
 891 {
 892   FRAME_PTR f;
 893 
 894   f = menubar_id_to_frame (id);
 895   if (!f)
 896     return;
 897   find_and_call_menu_selection (f, f->menu_bar_items_used,
 898                                 f->menu_bar_vector, client_data);
 899 }
 900 #endif /* not USE_GTK */
 901 
 902 /* Recompute all the widgets of frame F, when the menu bar has been
 903    changed.  Value is non-zero if widgets were updated.  */
 904 
 905 static int
 906 update_frame_menubar (f)
 907      FRAME_PTR f;
 908 {
 909 #ifdef USE_GTK
 910   return xg_update_frame_menubar (f);
 911 #else
 912   struct x_output *x;
 913   int columns, rows;
 914 
 915   if (! FRAME_X_P (f))
 916     abort ();
 917 
 918   x = f->output_data.x;
 919 
 920   if (!x->menubar_widget || XtIsManaged (x->menubar_widget))
 921     return 0;
 922 
 923   BLOCK_INPUT;
 924   /* Save the size of the frame because the pane widget doesn't accept
 925      to resize itself. So force it.  */
 926   columns = FRAME_COLS (f);
 927   rows = FRAME_LINES (f);
 928 
 929   /* Do the voodoo which means "I'm changing lots of things, don't try
 930      to refigure sizes until I'm done."  */
 931   lw_refigure_widget (x->column_widget, False);
 932 
 933   /* The order in which children are managed is the top to bottom
 934      order in which they are displayed in the paned window.  First,
 935      remove the text-area widget.  */
 936   XtUnmanageChild (x->edit_widget);
 937 
 938   /* Remove the menubar that is there now, and put up the menubar that
 939      should be there.  */
 940   XtManageChild (x->menubar_widget);
 941   XtMapWidget (x->menubar_widget);
 942   XtVaSetValues (x->menubar_widget, XtNmappedWhenManaged, 1, NULL);
 943 
 944   /* Re-manage the text-area widget, and then thrash the sizes.  */
 945   XtManageChild (x->edit_widget);
 946   lw_refigure_widget (x->column_widget, True);
 947 
 948   /* Force the pane widget to resize itself with the right values.  */
 949   EmacsFrameSetCharSize (x->edit_widget, columns, rows);
 950   UNBLOCK_INPUT;
 951 #endif
 952   return 1;
 953 }
 954 
 955 #ifdef USE_LUCID
 956 static void
 957 apply_systemfont_to_dialog (w)
 958      Widget w;
 959 {
 960   const char *fn = xsettings_get_system_normal_font ();
 961   if (fn) 
 962     {
 963       XrmDatabase db = XtDatabase (XtDisplay (w));
 964       if (db)
 965         XrmPutStringResource (&db, "*dialog.faceName", fn);
 966     }
 967 }
 968 
 969 static void
 970 apply_systemfont_to_menu (w)
 971      Widget w;
 972 {
 973   const char *fn = xsettings_get_system_normal_font ();
 974   int defflt;
 975 
 976   if (!fn) return;
 977 
 978   if (XtIsShell (w)) /* popup menu */
 979     {
 980       Widget *childs = NULL;
 981 
 982       XtVaGetValues (w, XtNchildren, &childs, NULL);
 983       if (*childs) w = *childs;
 984     }
 985 
 986   /* Only use system font if the default is used for the menu.  */
 987   XtVaGetValues (w, XtNdefaultFace, &defflt, NULL);
 988   if (defflt)
 989     XtVaSetValues (w, XtNfaceName, fn, NULL);
 990 }
 991 #endif
 992 
 993 /* Set the contents of the menubar widgets of frame F.
 994    The argument FIRST_TIME is currently ignored;
 995    it is set the first time this is called, from initialize_frame_menubar.  */
 996 
 997 void
 998 set_frame_menubar (f, first_time, deep_p)
 999      FRAME_PTR f;
1000      int first_time;
1001      int deep_p;
1002 {
1003   xt_or_gtk_widget menubar_widget;
1004 #ifdef USE_X_TOOLKIT
1005   LWLIB_ID id;
1006 #endif
1007   Lisp_Object items;
1008   widget_value *wv, *first_wv, *prev_wv = 0;
1009   int i, last_i = 0;
1010   int *submenu_start, *submenu_end;
1011   int *submenu_top_level_items, *submenu_n_panes;
1012 
1013   if (! FRAME_X_P (f))
1014     abort ();
1015 
1016   menubar_widget = f->output_data.x->menubar_widget;
1017 
1018   XSETFRAME (Vmenu_updating_frame, f);
1019 
1020 #ifdef USE_X_TOOLKIT
1021   if (f->output_data.x->id == 0)
1022     f->output_data.x->id = next_menubar_widget_id++;
1023   id = f->output_data.x->id;
1024 #endif
1025 
1026   if (! menubar_widget)
1027     deep_p = 1;
1028   else if (pending_menu_activation && !deep_p)
1029     deep_p = 1;
1030   /* Make the first call for any given frame always go deep.  */
1031   else if (!f->output_data.x->saved_menu_event && !deep_p)
1032     {
1033       deep_p = 1;
1034       f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent));
1035       f->output_data.x->saved_menu_event->type = 0;
1036     }
1037 
1038 #ifdef USE_GTK
1039   /* If we have detached menus, we must update deep so detached menus
1040      also gets updated.  */
1041   deep_p = deep_p || xg_have_tear_offs ();
1042 #endif
1043 
1044   if (deep_p)
1045     {
1046       /* Make a widget-value tree representing the entire menu trees.  */
1047 
1048       struct buffer *prev = current_buffer;
1049       Lisp_Object buffer;
1050       int specpdl_count = SPECPDL_INDEX ();
1051       int previous_menu_items_used = f->menu_bar_items_used;
1052       Lisp_Object *previous_items
1053         = (Lisp_Object *) alloca (previous_menu_items_used
1054                                   * sizeof (Lisp_Object));
1055 
1056       /* If we are making a new widget, its contents are empty,
1057          do always reinitialize them.  */
1058       if (! menubar_widget)
1059         previous_menu_items_used = 0;
1060 
1061       buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
1062       specbind (Qinhibit_quit, Qt);
1063       /* Don't let the debugger step into this code
1064          because it is not reentrant.  */
1065       specbind (Qdebug_on_next_call, Qnil);
1066 
1067       record_unwind_save_match_data ();
1068       if (NILP (Voverriding_local_map_menu_flag))
1069         {
1070           specbind (Qoverriding_terminal_local_map, Qnil);
1071           specbind (Qoverriding_local_map, Qnil);
1072         }
1073 
1074       set_buffer_internal_1 (XBUFFER (buffer));
1075 
1076       /* Run the Lucid hook.  */
1077       safe_run_hooks (Qactivate_menubar_hook);
1078 
1079       /* If it has changed current-menubar from previous value,
1080          really recompute the menubar from the value.  */
1081       if (! NILP (Vlucid_menu_bar_dirty_flag))
1082         call0 (Qrecompute_lucid_menubar);
1083       safe_run_hooks (Qmenu_bar_update_hook);
1084       FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
1085 
1086       items = FRAME_MENU_BAR_ITEMS (f);
1087 
1088       /* Save the frame's previous menu bar contents data.  */
1089       if (previous_menu_items_used)
1090         bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
1091                previous_menu_items_used * sizeof (Lisp_Object));
1092 
1093       /* Fill in menu_items with the current menu bar contents.
1094          This can evaluate Lisp code.  */
1095       save_menu_items ();
1096 
1097       menu_items = f->menu_bar_vector;
1098       menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
1099       submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1100       submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1101       submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int));
1102       submenu_top_level_items
1103         = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1104       init_menu_items ();
1105       for (i = 0; i < XVECTOR (items)->size; i += 4)
1106         {
1107           Lisp_Object key, string, maps;
1108 
1109           last_i = i;
1110 
1111           key = XVECTOR (items)->contents[i];
1112           string = XVECTOR (items)->contents[i + 1];
1113           maps = XVECTOR (items)->contents[i + 2];
1114           if (NILP (string))
1115             break;
1116 
1117           submenu_start[i] = menu_items_used;
1118 
1119           menu_items_n_panes = 0;
1120           submenu_top_level_items[i]
1121             = parse_single_submenu (key, string, maps);
1122           submenu_n_panes[i] = menu_items_n_panes;
1123 
1124           submenu_end[i] = menu_items_used;
1125         }
1126 
1127       finish_menu_items ();
1128 
1129       /* Convert menu_items into widget_value trees
1130          to display the menu.  This cannot evaluate Lisp code.  */
1131 
1132       wv = xmalloc_widget_value ();
1133       wv->name = "menubar";
1134       wv->value = 0;
1135       wv->enabled = 1;
1136       wv->button_type = BUTTON_TYPE_NONE;
1137       wv->help = Qnil;
1138       first_wv = wv;
1139 
1140       for (i = 0; i < last_i; i += 4)
1141         {
1142           menu_items_n_panes = submenu_n_panes[i];
1143           wv = digest_single_submenu (submenu_start[i], submenu_end[i],
1144                                       submenu_top_level_items[i]);
1145           if (prev_wv)
1146             prev_wv->next = wv;
1147           else
1148             first_wv->contents = wv;
1149           /* Don't set wv->name here; GC during the loop might relocate it.  */
1150           wv->enabled = 1;
1151           wv->button_type = BUTTON_TYPE_NONE;
1152           prev_wv = wv;
1153         }
1154 
1155       set_buffer_internal_1 (prev);
1156 
1157       /* If there has been no change in the Lisp-level contents
1158          of the menu bar, skip redisplaying it.  Just exit.  */
1159 
1160       /* Compare the new menu items with the ones computed last time.  */
1161       for (i = 0; i < previous_menu_items_used; i++)
1162         if (menu_items_used == i
1163             || (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i])))
1164           break;
1165       if (i == menu_items_used && i == previous_menu_items_used && i != 0)
1166         {
1167           /* The menu items have not changed.  Don't bother updating
1168              the menus in any form, since it would be a no-op.  */
1169           free_menubar_widget_value_tree (first_wv);
1170           discard_menu_items ();
1171           unbind_to (specpdl_count, Qnil);
1172           return;
1173         }
1174 
1175       /* The menu items are different, so store them in the frame.  */
1176       f->menu_bar_vector = menu_items;
1177       f->menu_bar_items_used = menu_items_used;
1178 
1179       /* This undoes save_menu_items.  */
1180       unbind_to (specpdl_count, Qnil);
1181 
1182       /* Now GC cannot happen during the lifetime of the widget_value,
1183          so it's safe to store data from a Lisp_String.  */
1184       wv = first_wv->contents;
1185       for (i = 0; i < XVECTOR (items)->size; i += 4)
1186         {
1187           Lisp_Object string;
1188           string = XVECTOR (items)->contents[i + 1];
1189           if (NILP (string))
1190             break;
1191           wv->name = (char *) SDATA (string);
1192           update_submenu_strings (wv->contents);
1193           wv = wv->next;
1194         }
1195 
1196     }
1197   else
1198     {
1199       /* Make a widget-value tree containing
1200          just the top level menu bar strings.  */
1201 
1202       wv = xmalloc_widget_value ();
1203       wv->name = "menubar";
1204       wv->value = 0;
1205       wv->enabled = 1;
1206       wv->button_type = BUTTON_TYPE_NONE;
1207       wv->help = Qnil;
1208       first_wv = wv;
1209 
1210       items = FRAME_MENU_BAR_ITEMS (f);
1211       for (i = 0; i < XVECTOR (items)->size; i += 4)
1212         {
1213           Lisp_Object string;
1214 
1215           string = XVECTOR (items)->contents[i + 1];
1216           if (NILP (string))
1217             break;
1218 
1219           wv = xmalloc_widget_value ();
1220           wv->name = (char *) SDATA (string);
1221           wv->value = 0;
1222           wv->enabled = 1;
1223           wv->button_type = BUTTON_TYPE_NONE;
1224           wv->help = Qnil;
1225           /* This prevents lwlib from assuming this
1226              menu item is really supposed to be empty.  */
1227           /* The EMACS_INT cast avoids a warning.
1228              This value just has to be different from small integers.  */
1229           wv->call_data = (void *) (EMACS_INT) (-1);
1230 
1231           if (prev_wv)
1232             prev_wv->next = wv;
1233           else
1234             first_wv->contents = wv;
1235           prev_wv = wv;
1236         }
1237 
1238       /* Forget what we thought we knew about what is in the
1239          detailed contents of the menu bar menus.
1240          Changing the top level always destroys the contents.  */
1241       f->menu_bar_items_used = 0;
1242     }
1243 
1244   /* Create or update the menu bar widget.  */
1245 
1246   BLOCK_INPUT;
1247 
1248 #ifdef USE_GTK
1249   xg_crazy_callback_abort = 1;
1250   if (menubar_widget)
1251     {
1252       /* The fourth arg is DEEP_P, which says to consider the entire
1253          menu trees we supply, rather than just the menu bar item names.  */
1254       xg_modify_menubar_widgets (menubar_widget,
1255                                  f,
1256                                  first_wv,
1257                                  deep_p,
1258                                  G_CALLBACK (menubar_selection_callback),
1259                                  G_CALLBACK (popup_deactivate_callback),
1260                                  G_CALLBACK (menu_highlight_callback));
1261     }
1262   else
1263     {
1264       GtkWidget *wvbox = f->output_data.x->vbox_widget;
1265 
1266       menubar_widget
1267         = xg_create_widget ("menubar", "menubar", f, first_wv,
1268                             G_CALLBACK (menubar_selection_callback),
1269                             G_CALLBACK (popup_deactivate_callback),
1270                             G_CALLBACK (menu_highlight_callback));
1271 
1272       f->output_data.x->menubar_widget = menubar_widget;
1273     }
1274 
1275 
1276 #else /* not USE_GTK */
1277   if (menubar_widget)
1278     {
1279       /* Disable resizing (done for Motif!) */
1280       lw_allow_resizing (f->output_data.x->widget, False);
1281 
1282       /* The third arg is DEEP_P, which says to consider the entire
1283          menu trees we supply, rather than just the menu bar item names.  */
1284       lw_modify_all_widgets (id, first_wv, deep_p);
1285 
1286       /* Re-enable the edit widget to resize.  */
1287       lw_allow_resizing (f->output_data.x->widget, True);
1288     }
1289   else
1290     {
1291       char menuOverride[] = "Ctrl<KeyPress>g: MenuGadgetEscape()";
1292       XtTranslations  override = XtParseTranslationTable (menuOverride);
1293 
1294       menubar_widget = lw_create_widget ("menubar", "menubar", id, first_wv,
1295                                          f->output_data.x->column_widget,
1296                                          0,
1297                                          popup_activate_callback,
1298                                          menubar_selection_callback,
1299                                          popup_deactivate_callback,
1300                                          menu_highlight_callback);
1301       f->output_data.x->menubar_widget = menubar_widget;
1302 
1303       /* Make menu pop down on C-g.  */
1304       XtOverrideTranslations (menubar_widget, override);
1305       apply_systemfont_to_menu (menubar_widget);
1306     }
1307 
1308   {
1309     int menubar_size
1310       = (f->output_data.x->menubar_widget
1311          ? (f->output_data.x->menubar_widget->core.height
1312             + f->output_data.x->menubar_widget->core.border_width)
1313          : 0);
1314 
1315 #if 1 /* Experimentally, we now get the right results
1316          for -geometry -0-0 without this.  24 Aug 96, rms.
1317          Maybe so, but the menu bar size is missing the pixels so the
1318          WM size hints are off by theses pixel.  Jan D, oct 2009.  */
1319 #ifdef USE_LUCID
1320     if (FRAME_EXTERNAL_MENU_BAR (f))
1321       {
1322         Dimension ibw = 0;
1323         XtVaGetValues (f->output_data.x->column_widget,
1324                        XtNinternalBorderWidth, &ibw, NULL);
1325         menubar_size += ibw;
1326       }
1327 #endif /* USE_LUCID */
1328 #endif /* 1 */
1329 
1330     f->output_data.x->menubar_height = menubar_size;
1331   }
1332 #endif /* not USE_GTK */
1333 
1334   free_menubar_widget_value_tree (first_wv);
1335   update_frame_menubar (f);
1336 
1337 #ifdef USE_GTK
1338   xg_crazy_callback_abort = 0;
1339 #endif
1340 
1341   UNBLOCK_INPUT;
1342 }
1343 
1344 /* Called from Fx_create_frame to create the initial menubar of a frame
1345    before it is mapped, so that the window is mapped with the menubar already
1346    there instead of us tacking it on later and thrashing the window after it
1347    is visible.  */
1348 
1349 void
1350 initialize_frame_menubar (f)
1351      FRAME_PTR f;
1352 {
1353   /* This function is called before the first chance to redisplay
1354      the frame.  It has to be, so the frame will have the right size.  */
1355   FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
1356   set_frame_menubar (f, 1, 1);
1357 }
1358 
1359 
1360 /* Get rid of the menu bar of frame F, and free its storage.
1361    This is used when deleting a frame, and when turning off the menu bar.
1362    For GTK this function is in gtkutil.c.  */
1363 
1364 #ifndef USE_GTK
1365 void
1366 free_frame_menubar (f)
1367      FRAME_PTR f;
1368 {
1369   Widget menubar_widget;
1370 
1371   if (! FRAME_X_P (f))
1372     abort ();
1373 
1374   menubar_widget = f->output_data.x->menubar_widget;
1375 
1376   f->output_data.x->menubar_height = 0;
1377 
1378   if (menubar_widget)
1379     {
1380 #ifdef USE_MOTIF
1381       /* Removing the menu bar magically changes the shell widget's x
1382          and y position of (0, 0) which, when the menu bar is turned
1383          on again, leads to pull-down menuss appearing in strange
1384          positions near the upper-left corner of the display.  This
1385          happens only with some window managers like twm and ctwm,
1386          but not with other like Motif's mwm or kwm, because the
1387          latter generate ConfigureNotify events when the menu bar
1388          is switched off, which fixes the shell position.  */
1389       Position x0, y0, x1, y1;
1390 #endif
1391 
1392       BLOCK_INPUT;
1393 
1394 #ifdef USE_MOTIF
1395       if (f->output_data.x->widget)
1396         XtVaGetValues (f->output_data.x->widget, XtNx, &x0, XtNy, &y0, NULL);
1397 #endif
1398 
1399       lw_destroy_all_widgets ((LWLIB_ID) f->output_data.x->id);
1400       f->output_data.x->menubar_widget = NULL;
1401 
1402 #ifdef USE_MOTIF
1403       if (f->output_data.x->widget)
1404         {
1405           XtVaGetValues (f->output_data.x->widget, XtNx, &x1, XtNy, &y1, NULL);
1406           if (x1 == 0 && y1 == 0)
1407             XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
1408         }
1409 #endif
1410 
1411       UNBLOCK_INPUT;
1412     }
1413 }
1414 #endif /* not USE_GTK */
1415 
1416 #endif /* USE_X_TOOLKIT || USE_GTK */
1417 
1418 /* xmenu_show actually displays a menu using the panes and items in menu_items
1419    and returns the value selected from it.
1420    There are two versions of xmenu_show, one for Xt and one for Xlib.
1421    Both assume input is blocked by the caller.  */
1422 
1423 /* F is the frame the menu is for.
1424    X and Y are the frame-relative specified position,
1425    relative to the inside upper left corner of the frame F.
1426    FOR_CLICK is nonzero if this menu was invoked for a mouse click.
1427    KEYMAPS is 1 if this menu was specified with keymaps;
1428     in that case, we return a list containing the chosen item's value
1429     and perhaps also the pane's prefix.
1430    TITLE is the specified menu title.
1431    ERROR is a place to store an error message string in case of failure.
1432    (We return nil on failure, but the value doesn't actually matter.)  */
1433 
1434 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1435 
1436 /* The item selected in the popup menu.  */
1437 static Lisp_Object *volatile menu_item_selection;
1438 
1439 #ifdef USE_GTK
1440 
1441 /* Used when position a popup menu.  See menu_position_func and
1442    create_and_show_popup_menu below.  */
1443 struct next_popup_x_y
1444 {
1445   FRAME_PTR f;
1446   int x;
1447   int y;
1448 };
1449 
1450 /* The menu position function to use if we are not putting a popup
1451    menu where the pointer is.
1452    MENU is the menu to pop up.
1453    X and Y shall on exit contain x/y where the menu shall pop up.
1454    PUSH_IN is not documented in the GTK manual.
1455    USER_DATA is any data passed in when calling gtk_menu_popup.
1456    Here it points to a struct next_popup_x_y where the coordinates
1457    to store in *X and *Y are as well as the frame for the popup.
1458 
1459    Here only X and Y are used.  */
1460 static void
1461 menu_position_func (menu, x, y, push_in, user_data)
1462      GtkMenu *menu;
1463      gint *x;
1464      gint *y;
1465      gboolean *push_in;
1466      gpointer user_data;
1467 {
1468   struct next_popup_x_y* data = (struct next_popup_x_y*)user_data;
1469   GtkRequisition req;
1470   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (data->f);
1471   int disp_width = x_display_pixel_width (dpyinfo);
1472   int disp_height = x_display_pixel_height (dpyinfo);
1473 
1474   *x = data->x;
1475   *y = data->y;
1476 
1477   /* Check if there is room for the menu.  If not, adjust x/y so that
1478      the menu is fully visible.  */
1479   gtk_widget_size_request (GTK_WIDGET (menu), &req);
1480   if (data->x + req.width > disp_width)
1481     *x -= data->x + req.width - disp_width;
1482   if (data->y + req.height > disp_height)
1483     *y -= data->y + req.height - disp_height;
1484 }
1485 
1486 static void
1487 popup_selection_callback (widget, client_data)
1488      GtkWidget *widget;
1489      gpointer client_data;
1490 {
1491   xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
1492 
1493   if (xg_crazy_callback_abort) return;
1494   if (cb_data) menu_item_selection = (Lisp_Object *) cb_data->call_data;
1495 }
1496 
1497 static Lisp_Object
1498 pop_down_menu (arg)
1499      Lisp_Object arg;
1500 {
1501   struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
1502 
1503   popup_activated_flag = 0;
1504   BLOCK_INPUT;
1505   gtk_widget_destroy (GTK_WIDGET (p->pointer));
1506   UNBLOCK_INPUT;
1507   return Qnil;
1508 }
1509 
1510 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1511    menu pops down.
1512    menu_item_selection will be set to the selection.  */
1513 static void
1514 create_and_show_popup_menu (f, first_wv, x, y, for_click, timestamp)
1515      FRAME_PTR f;
1516      widget_value *first_wv;
1517      int x;
1518      int y;
1519      int for_click;
1520      EMACS_UINT timestamp;
1521 {
1522   int i;
1523   GtkWidget *menu;
1524   GtkMenuPositionFunc pos_func = 0;  /* Pop up at pointer.  */
1525   struct next_popup_x_y popup_x_y;
1526   int specpdl_count = SPECPDL_INDEX ();
1527 
1528   if (! FRAME_X_P (f))
1529     abort ();
1530 
1531   xg_crazy_callback_abort = 1;
1532   menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
1533                            G_CALLBACK (popup_selection_callback),
1534                            G_CALLBACK (popup_deactivate_callback),
1535                            G_CALLBACK (menu_highlight_callback));
1536   xg_crazy_callback_abort = 0;
1537 
1538   if (! for_click)
1539     {
1540       /* Not invoked by a click.  pop up at x/y.  */
1541       pos_func = menu_position_func;
1542 
1543       /* Adjust coordinates to be root-window-relative.  */
1544       x += f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
1545       y += f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
1546 
1547       popup_x_y.x = x;
1548       popup_x_y.y = y;
1549       popup_x_y.f = f;
1550 
1551       i = 0;  /* gtk_menu_popup needs this to be 0 for a non-button popup.  */
1552     }
1553   else
1554     {
1555       for (i = 0; i < 5; i++)
1556         if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
1557           break;
1558     }
1559 
1560   /* Display the menu.  */
1561   gtk_widget_show_all (menu);
1562 
1563   gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i,
1564                   timestamp > 0 ? timestamp : gtk_get_current_event_time());
1565 
1566   record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
1567 
1568   if (GTK_WIDGET_MAPPED (menu))
1569     {
1570       /* Set this to one.  popup_widget_loop increases it by one, so it becomes
1571          two.  show_help_echo uses this to detect popup menus.  */
1572       popup_activated_flag = 1;
1573       /* Process events that apply to the menu.  */
1574       popup_widget_loop (1, menu);
1575     }
1576 
1577   unbind_to (specpdl_count, Qnil);
1578 
1579   /* Must reset this manually because the button release event is not passed
1580      to Emacs event loop. */
1581   FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
1582 }
1583 
1584 #else /* not USE_GTK */
1585 
1586 /* We need a unique id for each widget handled by the Lucid Widget
1587    library.
1588 
1589    For the main windows, and popup menus, we use this counter,
1590    which we increment each time after use.  This starts from 1<<16.
1591 
1592    For menu bars, we use numbers starting at 0, counted in
1593    next_menubar_widget_id.  */
1594 LWLIB_ID widget_id_tick;
1595 
1596 static void
1597 popup_selection_callback (widget, id, client_data)
1598      Widget widget;
1599      LWLIB_ID id;
1600      XtPointer client_data;
1601 {
1602   menu_item_selection = (Lisp_Object *) client_data;
1603 }
1604 
1605 /* ARG is the LWLIB ID of the dialog box, represented
1606    as a Lisp object as (HIGHPART . LOWPART).  */
1607 
1608 static Lisp_Object
1609 pop_down_menu (arg)
1610      Lisp_Object arg;
1611 {
1612   LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
1613                  | XINT (XCDR (arg)));
1614 
1615   BLOCK_INPUT;
1616   lw_destroy_all_widgets (id);
1617   UNBLOCK_INPUT;
1618   popup_activated_flag = 0;
1619 
1620   return Qnil;
1621 }
1622 
1623 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
1624    menu pops down.
1625    menu_item_selection will be set to the selection.  */
1626 static void
1627 create_and_show_popup_menu (f, first_wv, x, y, for_click, timestamp)
1628      FRAME_PTR f;
1629      widget_value *first_wv;
1630      int x;
1631      int y;
1632      int for_click;
1633      EMACS_UINT timestamp;
1634 {
1635   int i;
1636   Arg av[2];
1637   int ac = 0;
1638   XButtonPressedEvent dummy;
1639   LWLIB_ID menu_id;
1640   Widget menu;
1641 
1642   if (! FRAME_X_P (f))
1643     abort ();
1644 
1645   menu_id = widget_id_tick++;
1646   menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
1647                            f->output_data.x->widget, 1, 0,
1648                            popup_selection_callback,
1649                            popup_deactivate_callback,
1650                            menu_highlight_callback);
1651 
1652   apply_systemfont_to_menu (menu);
1653 
1654   dummy.type = ButtonPress;
1655   dummy.serial = 0;
1656   dummy.send_event = 0;
1657   dummy.display = FRAME_X_DISPLAY (f);
1658   dummy.time = CurrentTime;
1659   dummy.root = FRAME_X_DISPLAY_INFO (f)->root_window;
1660   dummy.window = dummy.root;
1661   dummy.subwindow = dummy.root;
1662   dummy.x = x;
1663   dummy.y = y;
1664 
1665   /* Adjust coordinates to be root-window-relative.  */
1666   x += f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
1667   y += f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
1668 
1669   dummy.x_root = x;
1670   dummy.y_root = y;
1671 
1672   dummy.state = 0;
1673   dummy.button = 0;
1674   for (i = 0; i < 5; i++)
1675     if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
1676       dummy.button = i;
1677 
1678   /* Don't allow any geometry request from the user.  */
1679   XtSetArg (av[ac], XtNgeometry, 0); ac++;
1680   XtSetValues (menu, av, ac);
1681 
1682   /* Display the menu.  */
1683   lw_popup_menu (menu, (XEvent *) &dummy);
1684   popup_activated_flag = 1;
1685   x_activate_timeout_atimer ();
1686 
1687   {
1688     int fact = 4 * sizeof (LWLIB_ID);
1689     int specpdl_count = SPECPDL_INDEX ();
1690     record_unwind_protect (pop_down_menu,
1691                            Fcons (make_number (menu_id >> (fact)),
1692                                   make_number (menu_id & ~(-1 << (fact)))));
1693 
1694     /* Process events that apply to the menu.  */
1695     popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 1);
1696 
1697     unbind_to (specpdl_count, Qnil);
1698   }
1699 }
1700 
1701 #endif /* not USE_GTK */
1702 
1703 Lisp_Object
1704 xmenu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
1705             Lisp_Object title, char **error, EMACS_UINT timestamp)
1706 {
1707   int i;
1708   widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
1709   widget_value **submenu_stack
1710     = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
1711   Lisp_Object *subprefix_stack
1712     = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
1713   int submenu_depth = 0;
1714 
1715   int first_pane;
1716 
1717   if (! FRAME_X_P (f))
1718     abort ();
1719 
1720   *error = NULL;
1721 
1722   if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
1723     {
1724       *error = "Empty menu";
1725       return Qnil;
1726     }
1727 
1728   /* Create a tree of widget_value objects
1729      representing the panes and their items.  */
1730   wv = xmalloc_widget_value ();
1731   wv->name = "menu";
1732   wv->value = 0;
1733   wv->enabled = 1;
1734   wv->button_type = BUTTON_TYPE_NONE;
1735   wv->help =Qnil;
1736   first_wv = wv;
1737   first_pane = 1;
1738 
1739   /* Loop over all panes and items, filling in the tree.  */
1740   i = 0;
1741   while (i < menu_items_used)
1742     {
1743       if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
1744         {
1745           submenu_stack[submenu_depth++] = save_wv;
1746           save_wv = prev_wv;
1747           prev_wv = 0;
1748           first_pane = 1;
1749           i++;
1750         }
1751       else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
1752         {
1753           prev_wv = save_wv;
1754           save_wv = submenu_stack[--submenu_depth];
1755           first_pane = 0;
1756           i++;
1757         }
1758       else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
1759                && submenu_depth != 0)
1760         i += MENU_ITEMS_PANE_LENGTH;
1761       /* Ignore a nil in the item list.
1762          It's meaningful only for dialog boxes.  */
1763       else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
1764         i += 1;
1765       else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
1766         {
1767           /* Create a new pane.  */
1768           Lisp_Object pane_name, prefix;
1769           char *pane_string;
1770 
1771           pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
1772           prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
1773 
1774 #ifndef HAVE_MULTILINGUAL_MENU
1775           if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
1776             {
1777               pane_name = ENCODE_MENU_STRING (pane_name);
1778               ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
1779             }
1780 #endif
1781           pane_string = (NILP (pane_name)
1782                          ? "" : (char *) SDATA (pane_name));
1783           /* If there is just one top-level pane, put all its items directly
1784              under the top-level menu.  */
1785           if (menu_items_n_panes == 1)
1786             pane_string = "";
1787 
1788           /* If the pane has a meaningful name,
1789              make the pane a top-level menu item
1790              with its items as a submenu beneath it.  */
1791           if (!keymaps && strcmp (pane_string, ""))
1792             {
1793               wv = xmalloc_widget_value ();
1794               if (save_wv)
1795                 save_wv->next = wv;
1796               else
1797                 first_wv->contents = wv;
1798               wv->name = pane_string;
1799               if (keymaps && !NILP (prefix))
1800                 wv->name++;
1801               wv->value = 0;
1802               wv->enabled = 1;
1803               wv->button_type = BUTTON_TYPE_NONE;
1804               wv->help = Qnil;
1805               save_wv = wv;
1806               prev_wv = 0;
1807             }
1808           else if (first_pane)
1809             {
1810               save_wv = wv;
1811               prev_wv = 0;
1812             }
1813           first_pane = 0;
1814           i += MENU_ITEMS_PANE_LENGTH;
1815         }
1816       else
1817         {
1818           /* Create a new item within current pane.  */
1819           Lisp_Object item_name, enable, descrip, def, type, selected, help;
1820           item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
1821           enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
1822           descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
1823           def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
1824           type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
1825           selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
1826           help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
1827 
1828 #ifndef HAVE_MULTILINGUAL_MENU
1829           if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
1830             {
1831               item_name = ENCODE_MENU_STRING (item_name);
1832               ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
1833             }
1834 
1835           if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
1836             {
1837               descrip = ENCODE_MENU_STRING (descrip);
1838               ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
1839             }
1840 #endif /* not HAVE_MULTILINGUAL_MENU */
1841 
1842           wv = xmalloc_widget_value ();
1843           if (prev_wv)
1844             prev_wv->next = wv;
1845           else
1846             save_wv->contents = wv;
1847           wv->name = (char *) SDATA (item_name);
1848           if (!NILP (descrip))
1849             wv->key = (char *) SDATA (descrip);
1850           wv->value = 0;
1851           /* If this item has a null value,
1852              make the call_data null so that it won't display a box
1853              when the mouse is on it.  */
1854           wv->call_data
1855             = (!NILP (def) ? (void *) &XVECTOR (menu_items)->contents[i] : 0);
1856           wv->enabled = !NILP (enable);
1857 
1858           if (NILP (type))
1859             wv->button_type = BUTTON_TYPE_NONE;
1860           else if (EQ (type, QCtoggle))
1861             wv->button_type = BUTTON_TYPE_TOGGLE;
1862           else if (EQ (type, QCradio))
1863             wv->button_type = BUTTON_TYPE_RADIO;
1864           else
1865             abort ();
1866 
1867           wv->selected = !NILP (selected);
1868 
1869           if (! STRINGP (help))
1870             help = Qnil;
1871 
1872           wv->help = help;
1873 
1874           prev_wv = wv;
1875 
1876           i += MENU_ITEMS_ITEM_LENGTH;
1877         }
1878     }
1879 
1880   /* Deal with the title, if it is non-nil.  */
1881   if (!NILP (title))
1882     {
1883       widget_value *wv_title = xmalloc_widget_value ();
1884       widget_value *wv_sep1 = xmalloc_widget_value ();
1885       widget_value *wv_sep2 = xmalloc_widget_value ();
1886 
1887       wv_sep2->name = "--";
1888       wv_sep2->next = first_wv->contents;
1889       wv_sep2->help = Qnil;
1890 
1891       wv_sep1->name = "--";
1892       wv_sep1->next = wv_sep2;
1893       wv_sep1->help = Qnil;
1894 
1895 #ifndef HAVE_MULTILINGUAL_MENU
1896       if (STRING_MULTIBYTE (title))
1897         title = ENCODE_MENU_STRING (title);
1898 #endif
1899 
1900       wv_title->name = (char *) SDATA (title);
1901       wv_title->enabled = TRUE;
1902       wv_title->button_type = BUTTON_TYPE_NONE;
1903       wv_title->help = Qnil;
1904       wv_title->next = wv_sep1;
1905       first_wv->contents = wv_title;
1906     }
1907 
1908   /* No selection has been chosen yet.  */
1909   menu_item_selection = 0;
1910 
1911   /* Actually create and show the menu until popped down.  */
1912   create_and_show_popup_menu (f, first_wv, x, y, for_click, timestamp);
1913 
1914   /* Free the widget_value objects we used to specify the contents.  */
1915   free_menubar_widget_value_tree (first_wv);
1916 
1917   /* Find the selected item, and its pane, to return
1918      the proper value.  */
1919   if (menu_item_selection != 0)
1920     {
1921       Lisp_Object prefix, entry;
1922 
1923       prefix = entry = Qnil;
1924       i = 0;
1925       while (i < menu_items_used)
1926         {
1927           if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
1928             {
1929               subprefix_stack[submenu_depth++] = prefix;
1930               prefix = entry;
1931               i++;
1932             }
1933           else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
1934             {
1935               prefix = subprefix_stack[--submenu_depth];
1936               i++;
1937             }
1938           else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
1939             {
1940               prefix
1941                 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
1942               i += MENU_ITEMS_PANE_LENGTH;
1943             }
1944           /* Ignore a nil in the item list.
1945              It's meaningful only for dialog boxes.  */
1946           else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
1947             i += 1;
1948           else
1949             {
1950               entry
1951                 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
1952               if (menu_item_selection == &XVECTOR (menu_items)->contents[i])
1953                 {
1954                   if (keymaps != 0)
1955                     {
1956                       int j;
1957 
1958                       entry = Fcons (entry, Qnil);
1959                       if (!NILP (prefix))
1960                         entry = Fcons (prefix, entry);
1961                       for (j = submenu_depth - 1; j >= 0; j--)
1962                         if (!NILP (subprefix_stack[j]))
1963                           entry = Fcons (subprefix_stack[j], entry);
1964                     }
1965                   return entry;
1966                 }
1967               i += MENU_ITEMS_ITEM_LENGTH;
1968             }
1969         }
1970     }
1971   else if (!for_click)
1972     /* Make "Cancel" equivalent to C-g.  */
1973     Fsignal (Qquit, Qnil);
1974 
1975   return Qnil;
1976 }
1977 
1978 #ifdef USE_GTK
1979 static void
1980 dialog_selection_callback (widget, client_data)
1981      GtkWidget *widget;
1982      gpointer client_data;
1983 {
1984   /* The EMACS_INT cast avoids a warning.  There's no problem
1985      as long as pointers have enough bits to hold small integers.  */
1986   if ((int) (EMACS_INT) client_data != -1)
1987     menu_item_selection = (Lisp_Object *) client_data;
1988 
1989   popup_activated_flag = 0;
1990 }
1991 
1992 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
1993    dialog pops down.
1994    menu_item_selection will be set to the selection.  */
1995 static void
1996 create_and_show_dialog (f, first_wv)
1997      FRAME_PTR f;
1998      widget_value *first_wv;
1999 {
2000   GtkWidget *menu;
2001 
2002   if (! FRAME_X_P (f))
2003     abort ();
2004 
2005   menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
2006                            G_CALLBACK (dialog_selection_callback),
2007                            G_CALLBACK (popup_deactivate_callback),
2008                            0);
2009 
2010   if (menu)
2011     {
2012       int specpdl_count = SPECPDL_INDEX ();
2013       record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
2014 
2015       /* Display the menu.  */
2016       gtk_widget_show_all (menu);
2017 
2018       /* Process events that apply to the menu.  */
2019       popup_widget_loop (1, menu);
2020 
2021       unbind_to (specpdl_count, Qnil);
2022     }
2023 }
2024 
2025 #else /* not USE_GTK */
2026 static void
2027 dialog_selection_callback (widget, id, client_data)
2028      Widget widget;
2029      LWLIB_ID id;
2030      XtPointer client_data;
2031 {
2032   /* The EMACS_INT cast avoids a warning.  There's no problem
2033      as long as pointers have enough bits to hold small integers.  */
2034   if ((int) (EMACS_INT) client_data != -1)
2035     menu_item_selection = (Lisp_Object *) client_data;
2036 
2037   BLOCK_INPUT;
2038   lw_destroy_all_widgets (id);
2039   UNBLOCK_INPUT;
2040   popup_activated_flag = 0;
2041 }
2042 
2043 
2044 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
2045    dialog pops down.
2046    menu_item_selection will be set to the selection.  */
2047 static void
2048 create_and_show_dialog (f, first_wv)
2049      FRAME_PTR f;
2050      widget_value *first_wv;
2051 {
2052   LWLIB_ID dialog_id;
2053 
2054   if (!FRAME_X_P (f))
2055     abort();
2056 
2057   dialog_id = widget_id_tick++;
2058 #ifdef HAVE_XFT
2059   apply_systemfont_to_dialog (f->output_data.x->widget);
2060 #endif
2061   lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
2062                     f->output_data.x->widget, 1, 0,
2063                     dialog_selection_callback, 0, 0);
2064   lw_modify_all_widgets (dialog_id, first_wv->contents, True);
2065   /* Display the dialog box.  */
2066   lw_pop_up_all_widgets (dialog_id);
2067   popup_activated_flag = 1;
2068   x_activate_timeout_atimer ();
2069 
2070   /* Process events that apply to the dialog box.
2071      Also handle timers.  */
2072   {
2073     int count = SPECPDL_INDEX ();
2074     int fact = 4 * sizeof (LWLIB_ID);
2075 
2076     /* xdialog_show_unwind is responsible for popping the dialog box down.  */
2077     record_unwind_protect (pop_down_menu,
2078                            Fcons (make_number (dialog_id >> (fact)),
2079                                   make_number (dialog_id & ~(-1 << (fact)))));
2080 
2081     popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f),
2082                          dialog_id, 1);
2083 
2084     unbind_to (count, Qnil);
2085   }
2086 }
2087 
2088 #endif /* not USE_GTK */
2089 
2090 static char * button_names [] = {
2091   "button1", "button2", "button3", "button4", "button5",
2092   "button6", "button7", "button8", "button9", "button10" };
2093 
2094 static Lisp_Object
2095 xdialog_show (f, keymaps, title, header, error_name)
2096      FRAME_PTR f;
2097      int keymaps;
2098      Lisp_Object title, header;
2099      char **error_name;
2100 {
2101   int i, nb_buttons=0;
2102   char dialog_name[6];
2103 
2104   widget_value *wv, *first_wv = 0, *prev_wv = 0;
2105 
2106   /* Number of elements seen so far, before boundary.  */
2107   int left_count = 0;
2108   /* 1 means we've seen the boundary between left-hand elts and right-hand.  */
2109   int boundary_seen = 0;
2110 
2111   if (! FRAME_X_P (f))
2112     abort ();
2113 
2114   *error_name = NULL;
2115 
2116   if (menu_items_n_panes > 1)
2117     {
2118       *error_name = "Multiple panes in dialog box";
2119       return Qnil;
2120     }
2121 
2122   /* Create a tree of widget_value objects
2123      representing the text label and buttons.  */
2124   {
2125     Lisp_Object pane_name, prefix;
2126     char *pane_string;
2127     pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
2128     prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
2129     pane_string = (NILP (pane_name)
2130                    ? "" : (char *) SDATA (pane_name));
2131     prev_wv = xmalloc_widget_value ();
2132     prev_wv->value = pane_string;
2133     if (keymaps && !NILP (prefix))
2134       prev_wv->name++;
2135     prev_wv->enabled = 1;
2136     prev_wv->name = "message";
2137     prev_wv->help = Qnil;
2138     first_wv = prev_wv;
2139 
2140     /* Loop over all panes and items, filling in the tree.  */
2141     i = MENU_ITEMS_PANE_LENGTH;
2142     while (i < menu_items_used)
2143       {
2144 
2145         /* Create a new item within current pane.  */
2146         Lisp_Object item_name, enable, descrip;
2147         item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
2148         enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
2149         descrip
2150           = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
2151 
2152         if (NILP (item_name))
2153           {
2154             free_menubar_widget_value_tree (first_wv);
2155             *error_name = "Submenu in dialog items";
2156             return Qnil;
2157           }
2158         if (EQ (item_name, Qquote))
2159           {
2160             /* This is the boundary between left-side elts
2161                and right-side elts.  Stop incrementing right_count.  */
2162             boundary_seen = 1;
2163             i++;
2164             continue;
2165           }
2166         if (nb_buttons >= 9)
2167           {
2168             free_menubar_widget_value_tree (first_wv);
2169             *error_name = "Too many dialog items";
2170             return Qnil;
2171           }
2172 
2173         wv = xmalloc_widget_value ();
2174         prev_wv->next = wv;
2175         wv->name = (char *) button_names[nb_buttons];
2176         if (!NILP (descrip))
2177           wv->key = (char *) SDATA (descrip);
2178         wv->value = (char *) SDATA (item_name);
2179         wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
2180         wv->enabled = !NILP (enable);
2181         wv->help = Qnil;
2182         prev_wv = wv;
2183 
2184         if (! boundary_seen)
2185           left_count++;
2186 
2187         nb_buttons++;
2188         i += MENU_ITEMS_ITEM_LENGTH;
2189       }
2190 
2191     /* If the boundary was not specified,
2192        by default put half on the left and half on the right.  */
2193     if (! boundary_seen)
2194       left_count = nb_buttons - nb_buttons / 2;
2195 
2196     wv = xmalloc_widget_value ();
2197     wv->name = dialog_name;
2198     wv->help = Qnil;
2199 
2200     /*  Frame title: 'Q' = Question, 'I' = Information.
2201         Can also have 'E' = Error if, one day, we want
2202         a popup for errors. */
2203     if (NILP(header))
2204       dialog_name[0] = 'Q';
2205     else
2206       dialog_name[0] = 'I';
2207 
2208     /* Dialog boxes use a really stupid name encoding
2209        which specifies how many buttons to use
2210        and how many buttons are on the right. */
2211     dialog_name[1] = '0' + nb_buttons;
2212     dialog_name[2] = 'B';
2213     dialog_name[3] = 'R';
2214     /* Number of buttons to put on the right.  */
2215     dialog_name[4] = '0' + nb_buttons - left_count;
2216     dialog_name[5] = 0;
2217     wv->contents = first_wv;
2218     first_wv = wv;
2219   }
2220 
2221   /* No selection has been chosen yet.  */
2222   menu_item_selection = 0;
2223 
2224   /* Actually create and show the dialog.  */
2225   create_and_show_dialog (f, first_wv);
2226 
2227   /* Free the widget_value objects we used to specify the contents.  */
2228   free_menubar_widget_value_tree (first_wv);
2229 
2230   /* Find the selected item, and its pane, to return
2231      the proper value.  */
2232   if (menu_item_selection != 0)
2233     {
2234       Lisp_Object prefix;
2235 
2236       prefix = Qnil;
2237       i = 0;
2238       while (i < menu_items_used)
2239         {
2240           Lisp_Object entry;
2241 
2242           if (EQ (XVECTOR (menu_items)->contents[i], Qt))
2243             {
2244               prefix
2245                 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
2246               i += MENU_ITEMS_PANE_LENGTH;
2247             }
2248           else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
2249             {
2250               /* This is the boundary between left-side elts and
2251                  right-side elts.  */
2252               ++i;
2253             }
2254           else
2255             {
2256               entry
2257                 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
2258               if (menu_item_selection == &XVECTOR (menu_items)->contents[i])
2259                 {
2260                   if (keymaps != 0)
2261                     {
2262                       entry = Fcons (entry, Qnil);
2263                       if (!NILP (prefix))
2264                         entry = Fcons (prefix, entry);
2265                     }
2266                   return entry;
2267                 }
2268               i += MENU_ITEMS_ITEM_LENGTH;
2269             }
2270         }
2271     }
2272   else
2273     /* Make "Cancel" equivalent to C-g.  */
2274     Fsignal (Qquit, Qnil);
2275 
2276   return Qnil;
2277 }
2278 
2279 #else /* not USE_X_TOOLKIT && not USE_GTK */
2280 
2281 /* The frame of the last activated non-toolkit menu bar.
2282    Used to generate menu help events.  */
2283 
2284 static struct frame *menu_help_frame;
2285 
2286 
2287 /* Show help HELP_STRING, or clear help if HELP_STRING is null.
2288 
2289    PANE is the pane number, and ITEM is the menu item number in
2290    the menu (currently not used).
2291 
2292    This cannot be done with generating a HELP_EVENT because
2293    XMenuActivate contains a loop that doesn't let Emacs process
2294    keyboard events.  */
2295 
2296 static void
2297 menu_help_callback (help_string, pane, item)
2298      char *help_string;
2299      int pane, item;
2300 {
2301   extern Lisp_Object Qmenu_item;
2302   Lisp_Object *first_item;
2303   Lisp_Object pane_name;
2304   Lisp_Object menu_object;
2305 
2306   first_item = XVECTOR (menu_items)->contents;
2307   if (EQ (first_item[0], Qt))
2308     pane_name = first_item[MENU_ITEMS_PANE_NAME];
2309   else if (EQ (first_item[0], Qquote))
2310     /* This shouldn't happen, see xmenu_show.  */
2311     pane_name = empty_unibyte_string;
2312   else
2313     pane_name = first_item[MENU_ITEMS_ITEM_NAME];
2314 
2315   /* (menu-item MENU-NAME PANE-NUMBER)  */
2316   menu_object = Fcons (Qmenu_item,
2317                        Fcons (pane_name,
2318                               Fcons (make_number (pane), Qnil)));
2319   show_help_echo (help_string ? build_string (help_string) : Qnil,
2320                   Qnil, menu_object, make_number (item), 1);
2321 }
2322 
2323 static Lisp_Object
2324 pop_down_menu (arg)
2325      Lisp_Object arg;
2326 {
2327   struct Lisp_Save_Value *p1 = XSAVE_VALUE (Fcar (arg));
2328   struct Lisp_Save_Value *p2 = XSAVE_VALUE (Fcdr (arg));
2329 
2330   FRAME_PTR f = p1->pointer;
2331   XMenu *menu = p2->pointer;
2332 
2333   BLOCK_INPUT;
2334 #ifndef MSDOS
2335   XUngrabPointer (FRAME_X_DISPLAY (f), CurrentTime);
2336   XUngrabKeyboard (FRAME_X_DISPLAY (f), CurrentTime);
2337 #endif
2338   XMenuDestroy (FRAME_X_DISPLAY (f), menu);
2339 
2340 #ifdef HAVE_X_WINDOWS
2341   /* Assume the mouse has moved out of the X window.
2342      If it has actually moved in, we will get an EnterNotify.  */
2343   x_mouse_leave (FRAME_X_DISPLAY_INFO (f));
2344 
2345   /* State that no mouse buttons are now held.
2346      (The oldXMenu code doesn't track this info for us.)
2347      That is not necessarily true, but the fiction leads to reasonable
2348      results, and it is a pain to ask which are actually held now.  */
2349   FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
2350 
2351 #endif /* HAVE_X_WINDOWS */
2352 
2353   UNBLOCK_INPUT;
2354 
2355   return Qnil;
2356 }
2357 
2358 
2359 Lisp_Object
2360 xmenu_show (f, x, y, for_click, keymaps, title, error, timestamp)
2361      FRAME_PTR f;
2362      int x, y;
2363      int for_click;
2364      int keymaps;
2365      Lisp_Object title;
2366      char **error;
2367      EMACS_UINT timestamp;
2368 {
2369   Window root;
2370   XMenu *menu;
2371   int pane, selidx, lpane, status;
2372   Lisp_Object entry, pane_prefix;
2373   char *datap;
2374   int ulx, uly, width, height;
2375   int dispwidth, dispheight;
2376   int i, j, lines, maxlines;
2377   int maxwidth;
2378   int dummy_int;
2379   unsigned int dummy_uint;
2380   int specpdl_count = SPECPDL_INDEX ();
2381 
2382   if (! FRAME_X_P (f) && ! FRAME_MSDOS_P (f))
2383     abort ();
2384 
2385   *error = 0;
2386   if (menu_items_n_panes == 0)
2387     return Qnil;
2388 
2389   if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
2390     {
2391       *error = "Empty menu";
2392       return Qnil;
2393     }
2394 
2395   /* Figure out which root window F is on.  */
2396   XGetGeometry (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &root,
2397                 &dummy_int, &dummy_int, &dummy_uint, &dummy_uint,
2398                 &dummy_uint, &dummy_uint);
2399 
2400   /* Make the menu on that window.  */
2401   menu = XMenuCreate (FRAME_X_DISPLAY (f), root, "emacs");
2402   if (menu == NULL)
2403     {
2404       *error = "Can't create menu";
2405       return Qnil;
2406     }
2407 
2408   /* Don't GC while we prepare and show the menu,
2409      because we give the oldxmenu library pointers to the
2410      contents of strings.  */
2411   inhibit_garbage_collection ();
2412 
2413 #ifdef HAVE_X_WINDOWS
2414   /* Adjust coordinates to relative to the outer (window manager) window.  */
2415   x += FRAME_OUTER_TO_INNER_DIFF_X (f);
2416   y += FRAME_OUTER_TO_INNER_DIFF_Y (f);
2417 #endif /* HAVE_X_WINDOWS */
2418 
2419   /* Adjust coordinates to be root-window-relative.  */
2420   x += f->left_pos;
2421   y += f->top_pos;
2422 
2423   /* Create all the necessary panes and their items.  */
2424   maxlines = lines = i = 0;
2425   while (i < menu_items_used)
2426     {
2427       if (EQ (XVECTOR (menu_items)->contents[i], Qt))
2428         {
2429           /* Create a new pane.  */
2430           Lisp_Object pane_name, prefix;
2431           char *pane_string;
2432 
2433           maxlines = max (maxlines, lines);
2434           lines = 0;
2435           pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
2436           prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
2437           pane_string = (NILP (pane_name)
2438                          ? "" : (char *) SDATA (pane_name));
2439           if (keymaps && !NILP (prefix))
2440             pane_string++;
2441 
2442           lpane = XMenuAddPane (FRAME_X_DISPLAY (f), menu, pane_string, TRUE);
2443           if (lpane == XM_FAILURE)
2444             {
2445               XMenuDestroy (FRAME_X_DISPLAY (f), menu);
2446               *error = "Can't create pane";
2447               return Qnil;
2448             }
2449           i += MENU_ITEMS_PANE_LENGTH;
2450 
2451           /* Find the width of the widest item in this pane.  */
2452           maxwidth = 0;
2453           j = i;
2454           while (j < menu_items_used)
2455             {
2456               Lisp_Object item;
2457               item = XVECTOR (menu_items)->contents[j];
2458               if (EQ (item, Qt))
2459                 break;
2460               if (NILP (item))
2461                 {
2462                   j++;
2463                   continue;
2464                 }
2465               width = SBYTES (item);
2466               if (width > maxwidth)
2467                 maxwidth = width;
2468 
2469               j += MENU_ITEMS_ITEM_LENGTH;
2470             }
2471         }
2472       /* Ignore a nil in the item list.
2473          It's meaningful only for dialog boxes.  */
2474       else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
2475         i += 1;
2476       else
2477         {
2478           /* Create a new item within current pane.  */
2479           Lisp_Object item_name, enable, descrip, help;
2480           unsigned char *item_data;
2481           char *help_string;
2482 
2483           item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
2484           enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
2485           descrip
2486             = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
2487           help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
2488           help_string = STRINGP (help) ? SDATA (help) : NULL;
2489 
2490           if (!NILP (descrip))
2491             {
2492               int gap = maxwidth - SBYTES (item_name);
2493               /* if alloca is fast, use that to make the space,
2494                  to reduce gc needs.  */
2495               item_data
2496                 = (unsigned char *) alloca (maxwidth
2497                                             + SBYTES (descrip) + 1);
2498               bcopy (SDATA (item_name), item_data,
2499                      SBYTES (item_name));
2500               for (j = SCHARS (item_name); j < maxwidth; j++)
2501                 item_data[j] = ' ';
2502               bcopy (SDATA (descrip), item_data + j,
2503                      SBYTES (descrip));
2504               item_data[j + SBYTES (descrip)] = 0;
2505             }
2506           else
2507             item_data = SDATA (item_name);
2508 
2509           if (XMenuAddSelection (FRAME_X_DISPLAY (f),
2510                                  menu, lpane, 0, item_data,
2511                                  !NILP (enable), help_string)
2512               == XM_FAILURE)
2513             {
2514               XMenuDestroy (FRAME_X_DISPLAY (f), menu);
2515               *error = "Can't add selection to menu";
2516               return Qnil;
2517             }
2518           i += MENU_ITEMS_ITEM_LENGTH;
2519           lines++;
2520         }
2521     }
2522 
2523   maxlines = max (maxlines, lines);
2524 
2525   /* All set and ready to fly.  */
2526   XMenuRecompute (FRAME_X_DISPLAY (f), menu);
2527   dispwidth = DisplayWidth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f));
2528   dispheight = DisplayHeight (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f));
2529   x = min (x, dispwidth);
2530   y = min (y, dispheight);
2531   x = max (x, 1);
2532   y = max (y, 1);
2533   XMenuLocate (FRAME_X_DISPLAY (f), menu, 0, 0, x, y,
2534                &ulx, &uly, &width, &height);
2535   if (ulx+width > dispwidth)
2536     {
2537       x -= (ulx + width) - dispwidth;
2538       ulx = dispwidth - width;
2539     }
2540   if (uly+height > dispheight)
2541     {
2542       y -= (uly + height) - dispheight;
2543       uly = dispheight - height;
2544     }
2545 #ifndef HAVE_X_WINDOWS
2546   if (FRAME_HAS_MINIBUF_P (f) && uly+height > dispheight - 1)
2547     {
2548       /* Move the menu away of the echo area, to avoid overwriting the
2549          menu with help echo messages or vice versa.  */
2550       if (BUFFERP (echo_area_buffer[0]) && WINDOWP (echo_area_window))
2551         {
2552           y -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window));
2553           uly -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window));
2554         }
2555       else
2556         {
2557           y--;
2558           uly--;
2559         }
2560     }
2561 #endif
2562   if (ulx < 0) x -= ulx;
2563   if (uly < 0) y -= uly;
2564 
2565   if (! for_click)
2566     {
2567       /* If position was not given by a mouse click, adjust so upper left
2568          corner of the menu as a whole ends up at given coordinates.  This
2569          is what x-popup-menu says in its documentation.  */
2570       x += width/2;
2571       y += 1.5*height/(maxlines+2);
2572     }
2573 
2574   XMenuSetAEQ (menu, TRUE);
2575   XMenuSetFreeze (menu, TRUE);
2576   pane = selidx = 0;
2577 
2578 #ifndef MSDOS
2579   XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f));
2580 #endif
2581 
2582   record_unwind_protect (pop_down_menu,
2583                          Fcons (make_save_value (f, 0),
2584                                 make_save_value (menu, 0)));
2585 
2586   /* Help display under X won't work because XMenuActivate contains
2587      a loop that doesn't give Emacs a chance to process it.  */
2588   menu_help_frame = f;
2589   status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
2590                           x, y, ButtonReleaseMask, &datap,
2591                           menu_help_callback);
2592 
2593   switch (status)
2594     {
2595     case XM_SUCCESS:
2596 #ifdef XDEBUG
2597       fprintf (stderr, "pane= %d line = %d\n", panes, selidx);
2598 #endif
2599 
2600       /* Find the item number SELIDX in pane number PANE.  */
2601       i = 0;
2602       while (i < menu_items_used)
2603         {
2604           if (EQ (XVECTOR (menu_items)->contents[i], Qt))
2605             {
2606               if (pane == 0)
2607                 pane_prefix
2608                   = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
2609               pane--;
2610               i += MENU_ITEMS_PANE_LENGTH;
2611             }
2612           else
2613             {
2614               if (pane == -1)
2615                 {
2616                   if (selidx == 0)
2617                     {
2618                       entry
2619                         = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
2620                       if (keymaps != 0)
2621                         {
2622                           entry = Fcons (entry, Qnil);
2623                           if (!NILP (pane_prefix))
2624                             entry = Fcons (pane_prefix, entry);
2625                         }
2626                       break;
2627                     }
2628                   selidx--;
2629                 }
2630               i += MENU_ITEMS_ITEM_LENGTH;
2631             }
2632         }
2633       break;
2634 
2635     case XM_FAILURE:
2636       *error = "Can't activate menu";
2637     case XM_IA_SELECT:
2638       entry = Qnil;
2639       break;
2640     case XM_NO_SELECT:
2641       /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
2642          the menu was invoked with a mouse event as POSITION).  */
2643       if (! for_click)
2644         Fsignal (Qquit, Qnil);
2645       entry = Qnil;
2646       break;
2647     }
2648 
2649   unbind_to (specpdl_count, Qnil);
2650 
2651   return entry;
2652 }
2653 
2654 #endif /* not USE_X_TOOLKIT */
2655 
2656 #endif /* HAVE_MENUS */
2657 
2658 /* Detect if a dialog or menu has been posted.  */
2659 
2660 int
2661 popup_activated ()
2662 {
2663   return popup_activated_flag;
2664 }
2665 
2666 /* The following is used by delayed window autoselection.  */
2667 
2668 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
2669        doc: /* Return t if a menu or popup dialog is active.  */)
2670      ()
2671 {
2672 #ifdef HAVE_MENUS
2673   return (popup_activated ()) ? Qt : Qnil;
2674 #else
2675   return Qnil;
2676 #endif /* HAVE_MENUS */
2677 }
2678 
2679 void
2680 syms_of_xmenu ()
2681 {
2682   Qdebug_on_next_call = intern_c_string ("debug-on-next-call");
2683   staticpro (&Qdebug_on_next_call);
2684 
2685 #ifdef USE_X_TOOLKIT
2686   widget_id_tick = (1<<16);
2687   next_menubar_widget_id = 1;
2688 #endif
2689 
2690   defsubr (&Smenu_or_popup_active_p);
2691 
2692 #if defined (USE_GTK) || defined (USE_X_TOOLKIT)
2693   defsubr (&Sx_menu_bar_open_internal);
2694   Ffset (intern_c_string ("accelerate-menu"),
2695          intern_c_string (Sx_menu_bar_open_internal.symbol_name));
2696 #endif
2697 
2698 #ifdef HAVE_MENUS
2699   defsubr (&Sx_popup_dialog);
2700 #endif
2701 }
2702 
2703 /* arch-tag: 92ea573c-398e-496e-ac73-2436f7d63242
2704    (do not change this comment) */