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 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
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, or (at your option)
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.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* X pop-up deck-of-cards menu facility for GNU Emacs.
24 * Written by Jon Arnold and Roman Budzianowski
25 * Mods and rewrite by Robert Krawitz
29 /* Modified by Fred Pierresteguy on December 93
30 to make the popup menus and menubar use the Xt. */
32 /* Rewritten for clarity and GC protection by rms in Feb 94. */
36 #if 0 /* Why was this included? And without syssignal.h? */
37 /* On 4.3 this loses if it comes after xterm.h. */
47 #include "termhooks.h"
49 #include "blockinput.h"
53 #include "sysselect.h"
60 /* This may include sys/types.h, and that somehow loses
61 if this is not done before the other system files. */
65 /* Load sys/types.h if not already loaded.
66 In some systems loading it twice is suicidal. */
68 #include <sys/types.h>
71 #include "dispextern.h"
74 /* Defining HAVE_MULTILINGUAL_MENU would mean that the toolkit menu
75 code accepts the Emacs internal encoding. */
76 #undef HAVE_MULTILINGUAL_MENU
80 #include <X11/IntrinsicP.h>
81 #include <X11/CoreP.h>
82 #include <X11/StringDefs.h>
83 #include <X11/Shell.h>
86 #include <X11/Xaw3d/Paned.h>
87 #else /* !HAVE_XAW3D */
88 #include <X11/Xaw/Paned.h>
89 #endif /* HAVE_XAW3D */
90 #endif /* USE_LUCID */
91 #include "../lwlib/lwlib.h"
92 #else /* not USE_X_TOOLKIT */
94 #include "../oldXMenu/XMenu.h"
96 #endif /* not USE_X_TOOLKIT */
97 #endif /* HAVE_X_WINDOWS */
104 Lisp_Object Qdebug_on_next_call
;
106 extern Lisp_Object Vmenu_updating_frame
;
108 extern Lisp_Object Qmenu_bar
;
110 extern Lisp_Object QCtoggle
, QCradio
;
112 extern Lisp_Object Voverriding_local_map
;
113 extern Lisp_Object Voverriding_local_map_menu_flag
;
115 extern Lisp_Object Qoverriding_local_map
, Qoverriding_terminal_local_map
;
117 extern Lisp_Object Qmenu_bar_update_hook
;
120 extern void set_frame_menubar
P_ ((FRAME_PTR
, int, int));
121 extern XtAppContext Xt_app_con
;
123 static Lisp_Object xdialog_show
P_ ((FRAME_PTR
, int, Lisp_Object
, Lisp_Object
,
125 static void popup_get_selection
P_ ((XEvent
*, struct x_display_info
*,
128 /* Define HAVE_BOXES if menus can handle radio and toggle buttons. */
131 #endif /* USE_X_TOOLKIT */
136 extern void set_frame_menubar
P_ ((FRAME_PTR
, int, int));
137 static Lisp_Object xdialog_show
P_ ((FRAME_PTR
, int, Lisp_Object
, Lisp_Object
,
141 /* This is how to deal with multibyte text if HAVE_MULTILINGUAL_MENU
142 isn't defined. The use of HAVE_MULTILINGUAL_MENU could probably be
143 confined to an extended version of this with sections of code below
144 using it unconditionally. */
146 /* gtk just uses utf-8. */
147 # define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str)
148 #elif defined HAVE_X_I18N
149 # define ENCODE_MENU_STRING(str) ENCODE_SYSTEM (str)
151 # define ENCODE_MENU_STRING(str) string_make_unibyte (str)
154 static void push_menu_item
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
,
155 Lisp_Object
, Lisp_Object
, Lisp_Object
,
156 Lisp_Object
, Lisp_Object
));
157 static int update_frame_menubar
P_ ((struct frame
*));
158 static Lisp_Object xmenu_show
P_ ((struct frame
*, int, int, int, int,
159 Lisp_Object
, char **));
160 static void keymap_panes
P_ ((Lisp_Object
*, int, int));
161 static void single_keymap_panes
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
,
163 static void list_of_panes
P_ ((Lisp_Object
));
164 static void list_of_items
P_ ((Lisp_Object
));
167 /* This holds a Lisp vector that holds the results of decoding
168 the keymaps or alist-of-alists that specify a menu.
170 It describes the panes and items within the panes.
172 Each pane is described by 3 elements in the vector:
173 t, the pane name, the pane's prefix key.
174 Then follow the pane's items, with 5 elements per item:
175 the item string, the enable flag, the item's value,
176 the definition, and the equivalent keyboard key's description string.
178 In some cases, multiple levels of menus may be described.
179 A single vector slot containing nil indicates the start of a submenu.
180 A single vector slot containing lambda indicates the end of a submenu.
181 The submenu follows a menu item which is the way to reach the submenu.
183 A single vector slot containing quote indicates that the
184 following items should appear on the right of a dialog box.
186 Using a Lisp vector to hold this information while we decode it
187 takes care of protecting all the data from GC. */
189 #define MENU_ITEMS_PANE_NAME 1
190 #define MENU_ITEMS_PANE_PREFIX 2
191 #define MENU_ITEMS_PANE_LENGTH 3
195 MENU_ITEMS_ITEM_NAME
= 0,
196 MENU_ITEMS_ITEM_ENABLE
,
197 MENU_ITEMS_ITEM_VALUE
,
198 MENU_ITEMS_ITEM_EQUIV_KEY
,
199 MENU_ITEMS_ITEM_DEFINITION
,
200 MENU_ITEMS_ITEM_TYPE
,
201 MENU_ITEMS_ITEM_SELECTED
,
202 MENU_ITEMS_ITEM_HELP
,
203 MENU_ITEMS_ITEM_LENGTH
206 static Lisp_Object menu_items
;
208 /* If non-nil, means that the global vars defined here are already in use.
209 Used to detect cases where we try to re-enter this non-reentrant code. */
210 static Lisp_Object menu_items_inuse
;
212 /* Number of slots currently allocated in menu_items. */
213 static int menu_items_allocated
;
215 /* This is the index in menu_items of the first empty slot. */
216 static int menu_items_used
;
218 /* The number of panes currently recorded in menu_items,
219 excluding those within submenus. */
220 static int menu_items_n_panes
;
222 /* Current depth within submenus. */
223 static int menu_items_submenu_depth
;
225 /* Flag which when set indicates a dialog or menu has been posted by
226 Xt on behalf of one of the widget sets. */
227 static int popup_activated_flag
;
229 static int next_menubar_widget_id
;
231 /* This is set nonzero after the user activates the menu bar, and set
232 to zero again after the menu bars are redisplayed by prepare_menu_bar.
233 While it is nonzero, all calls to set_frame_menubar go deep.
235 I don't understand why this is needed, but it does seem to be
236 needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
238 int pending_menu_activation
;
242 /* Return the frame whose ->output_data.x->id equals ID, or 0 if none. */
244 static struct frame
*
245 menubar_id_to_frame (id
)
248 Lisp_Object tail
, frame
;
251 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
257 if (!FRAME_WINDOW_P (f
))
259 if (f
->output_data
.x
->id
== id
)
267 /* Initialize the menu_items structure if we haven't already done so.
268 Also mark it as currently empty. */
273 if (!NILP (menu_items_inuse
))
274 error ("Trying to use a menu from within a menu-entry");
276 if (NILP (menu_items
))
278 menu_items_allocated
= 60;
279 menu_items
= Fmake_vector (make_number (menu_items_allocated
), Qnil
);
282 menu_items_inuse
= Qt
;
284 menu_items_n_panes
= 0;
285 menu_items_submenu_depth
= 0;
288 /* Call at the end of generating the data in menu_items. */
296 unuse_menu_items (dummy
)
299 return menu_items_inuse
= Qnil
;
302 /* Call when finished using the data for the current menu
306 discard_menu_items ()
308 /* Free the structure if it is especially large.
309 Otherwise, hold on to it, to save time. */
310 if (menu_items_allocated
> 200)
313 menu_items_allocated
= 0;
315 xassert (NILP (menu_items_inuse
));
318 /* This undoes save_menu_items, and it is called by the specpdl unwind
322 restore_menu_items (saved
)
325 menu_items
= XCAR (saved
);
326 menu_items_inuse
= (! NILP (menu_items
) ? Qt
: Qnil
);
327 menu_items_allocated
= (VECTORP (menu_items
) ? ASIZE (menu_items
) : 0);
328 saved
= XCDR (saved
);
329 menu_items_used
= XINT (XCAR (saved
));
330 saved
= XCDR (saved
);
331 menu_items_n_panes
= XINT (XCAR (saved
));
332 saved
= XCDR (saved
);
333 menu_items_submenu_depth
= XINT (XCAR (saved
));
337 /* Push the whole state of menu_items processing onto the specpdl.
338 It will be restored when the specpdl is unwound. */
343 Lisp_Object saved
= list4 (!NILP (menu_items_inuse
) ? menu_items
: Qnil
,
344 make_number (menu_items_used
),
345 make_number (menu_items_n_panes
),
346 make_number (menu_items_submenu_depth
));
347 record_unwind_protect (restore_menu_items
, saved
);
348 menu_items_inuse
= Qnil
;
352 /* Make the menu_items vector twice as large. */
357 menu_items_allocated
*= 2;
358 menu_items
= larger_vector (menu_items
, menu_items_allocated
, Qnil
);
361 /* Begin a submenu. */
364 push_submenu_start ()
366 if (menu_items_used
+ 1 > menu_items_allocated
)
369 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qnil
;
370 menu_items_submenu_depth
++;
378 if (menu_items_used
+ 1 > menu_items_allocated
)
381 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qlambda
;
382 menu_items_submenu_depth
--;
385 /* Indicate boundary between left and right. */
388 push_left_right_boundary ()
390 if (menu_items_used
+ 1 > menu_items_allocated
)
393 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qquote
;
396 /* Start a new menu pane in menu_items.
397 NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
400 push_menu_pane (name
, prefix_vec
)
401 Lisp_Object name
, prefix_vec
;
403 if (menu_items_used
+ MENU_ITEMS_PANE_LENGTH
> menu_items_allocated
)
406 if (menu_items_submenu_depth
== 0)
407 menu_items_n_panes
++;
408 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qt
;
409 XVECTOR (menu_items
)->contents
[menu_items_used
++] = name
;
410 XVECTOR (menu_items
)->contents
[menu_items_used
++] = prefix_vec
;
413 /* Push one menu item into the current pane. NAME is the string to
414 display. ENABLE if non-nil means this item can be selected. KEY
415 is the key generated by choosing this item, or nil if this item
416 doesn't really have a definition. DEF is the definition of this
417 item. EQUIV is the textual description of the keyboard equivalent
418 for this item (or nil if none). TYPE is the type of this menu
419 item, one of nil, `toggle' or `radio'. */
422 push_menu_item (name
, enable
, key
, def
, equiv
, type
, selected
, help
)
423 Lisp_Object name
, enable
, key
, def
, equiv
, type
, selected
, help
;
425 if (menu_items_used
+ MENU_ITEMS_ITEM_LENGTH
> menu_items_allocated
)
428 XVECTOR (menu_items
)->contents
[menu_items_used
++] = name
;
429 XVECTOR (menu_items
)->contents
[menu_items_used
++] = enable
;
430 XVECTOR (menu_items
)->contents
[menu_items_used
++] = key
;
431 XVECTOR (menu_items
)->contents
[menu_items_used
++] = equiv
;
432 XVECTOR (menu_items
)->contents
[menu_items_used
++] = def
;
433 XVECTOR (menu_items
)->contents
[menu_items_used
++] = type
;
434 XVECTOR (menu_items
)->contents
[menu_items_used
++] = selected
;
435 XVECTOR (menu_items
)->contents
[menu_items_used
++] = help
;
438 /* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
439 and generate menu panes for them in menu_items.
440 If NOTREAL is nonzero,
441 don't bother really computing whether an item is enabled. */
444 keymap_panes (keymaps
, nmaps
, notreal
)
445 Lisp_Object
*keymaps
;
453 /* Loop over the given keymaps, making a pane for each map.
454 But don't make a pane that is empty--ignore that map instead.
455 P is the number of panes we have made so far. */
456 for (mapno
= 0; mapno
< nmaps
; mapno
++)
457 single_keymap_panes (keymaps
[mapno
],
458 Fkeymap_prompt (keymaps
[mapno
]), Qnil
, notreal
, 10);
460 finish_menu_items ();
463 /* Args passed between single_keymap_panes and single_menu_item. */
466 Lisp_Object pending_maps
;
467 int maxdepth
, notreal
;
471 static void single_menu_item
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
,
474 /* This is a recursive subroutine of keymap_panes.
475 It handles one keymap, KEYMAP.
476 The other arguments are passed along
477 or point to local variables of the previous function.
478 If NOTREAL is nonzero, only check for equivalent key bindings, don't
479 evaluate expressions in menu items and don't make any menu.
481 If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
484 single_keymap_panes (keymap
, pane_name
, prefix
, notreal
, maxdepth
)
486 Lisp_Object pane_name
;
494 skp
.pending_maps
= Qnil
;
495 skp
.maxdepth
= maxdepth
;
496 skp
.notreal
= notreal
;
502 push_menu_pane (pane_name
, prefix
);
505 /* Remember index for first item in this pane so we can go back and
506 add a prefix when (if) we see the first button. After that, notbuttons
507 is set to 0, to mark that we have seen a button and all non button
508 items need a prefix. */
509 skp
.notbuttons
= menu_items_used
;
512 GCPRO1 (skp
.pending_maps
);
513 map_keymap_canonical (keymap
, single_menu_item
, Qnil
, &skp
);
516 /* Process now any submenus which want to be panes at this level. */
517 while (CONSP (skp
.pending_maps
))
519 Lisp_Object elt
, eltcdr
, string
;
520 elt
= XCAR (skp
.pending_maps
);
522 string
= XCAR (eltcdr
);
523 /* We no longer discard the @ from the beginning of the string here.
524 Instead, we do this in xmenu_show. */
525 single_keymap_panes (Fcar (elt
), string
,
526 XCDR (eltcdr
), notreal
, maxdepth
- 1);
527 skp
.pending_maps
= XCDR (skp
.pending_maps
);
531 /* This is a subroutine of single_keymap_panes that handles one
533 KEY is a key in a keymap and ITEM is its binding.
534 SKP->PENDING_MAPS_PTR is a list of keymaps waiting to be made into
536 If SKP->NOTREAL is nonzero, only check for equivalent key bindings, don't
537 evaluate expressions in menu items and don't make any menu.
538 If we encounter submenus deeper than SKP->MAXDEPTH levels, ignore them.
539 SKP->NOTBUTTONS is only used when simulating toggle boxes and radio
540 buttons. It keeps track of if we have seen a button in this menu or
544 single_menu_item (key
, item
, dummy
, skp_v
)
545 Lisp_Object key
, item
, dummy
;
548 Lisp_Object map
, item_string
, enabled
;
549 struct gcpro gcpro1
, gcpro2
;
551 struct skp
*skp
= skp_v
;
553 /* Parse the menu item and leave the result in item_properties. */
555 res
= parse_menu_item (item
, skp
->notreal
, 0);
558 return; /* Not a menu item. */
560 map
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_MAP
];
564 /* We don't want to make a menu, just traverse the keymaps to
565 precompute equivalent key bindings. */
567 single_keymap_panes (map
, Qnil
, key
, 1, skp
->maxdepth
- 1);
571 enabled
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_ENABLE
];
572 item_string
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_NAME
];
574 if (!NILP (map
) && SREF (item_string
, 0) == '@')
577 /* An enabled separate pane. Remember this to handle it later. */
578 skp
->pending_maps
= Fcons (Fcons (map
, Fcons (item_string
, key
)),
584 /* Simulate radio buttons and toggle boxes by putting a prefix in
587 Lisp_Object prefix
= Qnil
;
588 Lisp_Object type
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_TYPE
];
592 = XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_SELECTED
];
595 /* The first button. Line up previous items in this menu. */
597 int index
= skp
->notbuttons
; /* Index for first item this menu. */
600 while (index
< menu_items_used
)
603 = XVECTOR (menu_items
)->contents
[index
+ MENU_ITEMS_ITEM_NAME
];
607 submenu
++; /* Skip sub menu. */
609 else if (EQ (tem
, Qlambda
))
612 submenu
--; /* End sub menu. */
614 else if (EQ (tem
, Qt
))
615 index
+= 3; /* Skip new pane marker. */
616 else if (EQ (tem
, Qquote
))
617 index
++; /* Skip a left, right divider. */
620 if (!submenu
&& SREF (tem
, 0) != '\0'
621 && SREF (tem
, 0) != '-')
622 XVECTOR (menu_items
)->contents
[index
+ MENU_ITEMS_ITEM_NAME
]
623 = concat2 (build_string (" "), tem
);
624 index
+= MENU_ITEMS_ITEM_LENGTH
;
630 /* Calculate prefix, if any, for this item. */
631 if (EQ (type
, QCtoggle
))
632 prefix
= build_string (NILP (selected
) ? "[ ] " : "[X] ");
633 else if (EQ (type
, QCradio
))
634 prefix
= build_string (NILP (selected
) ? "( ) " : "(*) ");
636 /* Not a button. If we have earlier buttons, then we need a prefix. */
637 else if (!skp
->notbuttons
&& SREF (item_string
, 0) != '\0'
638 && SREF (item_string
, 0) != '-')
639 prefix
= build_string (" ");
642 item_string
= concat2 (prefix
, item_string
);
644 #endif /* not HAVE_BOXES */
646 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
648 /* Indicate visually that this is a submenu. */
649 item_string
= concat2 (item_string
, build_string (" >"));
652 push_menu_item (item_string
, enabled
, key
,
653 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_DEF
],
654 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_KEYEQ
],
655 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_TYPE
],
656 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_SELECTED
],
657 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_HELP
]);
659 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
660 /* Display a submenu using the toolkit. */
661 if (! (NILP (map
) || NILP (enabled
)))
663 push_submenu_start ();
664 single_keymap_panes (map
, Qnil
, key
, 0, skp
->maxdepth
- 1);
670 /* Push all the panes and items of a menu described by the
671 alist-of-alists MENU.
672 This handles old-fashioned calls to x-popup-menu. */
682 for (tail
= menu
; CONSP (tail
); tail
= XCDR (tail
))
684 Lisp_Object elt
, pane_name
, pane_data
;
686 pane_name
= Fcar (elt
);
687 CHECK_STRING (pane_name
);
688 push_menu_pane (ENCODE_MENU_STRING (pane_name
), Qnil
);
689 pane_data
= Fcdr (elt
);
690 CHECK_CONS (pane_data
);
691 list_of_items (pane_data
);
694 finish_menu_items ();
697 /* Push the items in a single pane defined by the alist PANE. */
703 Lisp_Object tail
, item
, item1
;
705 for (tail
= pane
; CONSP (tail
); tail
= XCDR (tail
))
709 push_menu_item (ENCODE_MENU_STRING (item
), Qnil
, Qnil
, Qt
,
710 Qnil
, Qnil
, Qnil
, Qnil
);
711 else if (CONSP (item
))
714 CHECK_STRING (item1
);
715 push_menu_item (ENCODE_MENU_STRING (item1
), Qt
, XCDR (item
),
716 Qt
, Qnil
, Qnil
, Qnil
, Qnil
);
719 push_left_right_boundary ();
724 #ifdef HAVE_X_WINDOWS
725 /* Return the mouse position in *X and *Y. The coordinates are window
726 relative for the edit window in frame F.
727 This is for Fx_popup_menu. The mouse_position_hook can not
728 be used for X, as it returns window relative coordinates
729 for the window where the mouse is in. This could be the menu bar,
730 the scroll bar or the edit window. Fx_popup_menu needs to be
731 sure it is the edit window. */
733 mouse_position_for_popup (f
, x
, y
)
738 Window root
, dummy_window
;
746 XQueryPointer (FRAME_X_DISPLAY (f
),
747 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
749 /* The root window which contains the pointer. */
752 /* Window pointer is on, not used */
755 /* The position on that root window. */
758 /* x/y in dummy_window coordinates, not used. */
761 /* Modifier keys and pointer buttons, about which
763 (unsigned int *) &dummy
);
767 /* xmenu_show expects window coordinates, not root window
768 coordinates. Translate. */
769 *x
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
770 *y
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
773 #endif /* HAVE_X_WINDOWS */
775 DEFUN ("x-popup-menu", Fx_popup_menu
, Sx_popup_menu
, 2, 2, 0,
776 doc
: /* Pop up a deck-of-cards menu and return user's selection.
777 POSITION is a position specification. This is either a mouse button event
778 or a list ((XOFFSET YOFFSET) WINDOW)
779 where XOFFSET and YOFFSET are positions in pixels from the top left
780 corner of WINDOW. (WINDOW may be a window or a frame object.)
781 This controls the position of the top left of the menu as a whole.
782 If POSITION is t, it means to use the current mouse position.
784 MENU is a specifier for a menu. For the simplest case, MENU is a keymap.
785 The menu items come from key bindings that have a menu string as well as
786 a definition; actually, the "definition" in such a key binding looks like
787 \(STRING . REAL-DEFINITION). To give the menu a title, put a string into
788 the keymap as a top-level element.
790 If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.
791 Otherwise, REAL-DEFINITION should be a valid key binding definition.
793 You can also use a list of keymaps as MENU.
794 Then each keymap makes a separate pane.
796 When MENU is a keymap or a list of keymaps, the return value is the
797 list of events corresponding to the user's choice. Note that
798 `x-popup-menu' does not actually execute the command bound to that
801 Alternatively, you can specify a menu of multiple panes
802 with a list of the form (TITLE PANE1 PANE2...),
803 where each pane is a list of form (TITLE ITEM1 ITEM2...).
804 Each ITEM is normally a cons cell (STRING . VALUE);
805 but a string can appear as an item--that makes a nonselectable line
807 With this form of menu, the return value is VALUE from the chosen item.
809 If POSITION is nil, don't display the menu at all, just precalculate the
810 cached information about equivalent key sequences.
812 If the user gets rid of the menu without making a valid choice, for
813 instance by clicking the mouse away from a valid choice or by typing
814 keyboard input, then this normally results in a quit and
815 `x-popup-menu' does not return. But if POSITION is a mouse button
816 event (indicating that the user invoked the menu with the mouse) then
817 no quit occurs and `x-popup-menu' returns nil. */)
819 Lisp_Object position
, menu
;
821 Lisp_Object keymap
, tem
;
822 int xpos
= 0, ypos
= 0;
824 char *error_name
= NULL
;
825 Lisp_Object selection
= Qnil
;
827 Lisp_Object x
, y
, window
;
830 int specpdl_count
= SPECPDL_INDEX ();
834 if (! NILP (position
))
836 int get_current_pos_p
= 0;
839 /* Decode the first argument: find the window and the coordinates. */
840 if (EQ (position
, Qt
)
841 || (CONSP (position
) && (EQ (XCAR (position
), Qmenu_bar
)
842 || EQ (XCAR (position
), Qtool_bar
))))
844 get_current_pos_p
= 1;
848 tem
= Fcar (position
);
851 window
= Fcar (Fcdr (position
));
853 y
= Fcar (XCDR (tem
));
858 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
859 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
860 tem
= Fcar (Fcdr (Fcdr (tem
))); /* POSN_WINDOW_POSN (tem) */
865 /* If a click happens in an external tool bar or a detached
866 tool bar, x and y is NIL. In that case, use the current
867 mouse position. This happens for the help button in the
868 tool bar. Ideally popup-menu should pass NIL to
869 this function, but it doesn't. */
870 if (NILP (x
) && NILP (y
))
871 get_current_pos_p
= 1;
874 if (get_current_pos_p
)
876 /* Use the mouse's current position. */
877 FRAME_PTR new_f
= SELECTED_FRAME ();
878 #ifdef HAVE_X_WINDOWS
879 /* Can't use mouse_position_hook for X since it returns
880 coordinates relative to the window the mouse is in,
881 we need coordinates relative to the edit widget always. */
886 mouse_position_for_popup (new_f
, &cur_x
, &cur_y
);
887 /* cur_x/y may be negative, so use make_number. */
888 x
= make_number (cur_x
);
889 y
= make_number (cur_y
);
892 #else /* not HAVE_X_WINDOWS */
893 Lisp_Object bar_window
;
894 enum scroll_bar_part part
;
897 if (mouse_position_hook
)
898 (*mouse_position_hook
) (&new_f
, 1, &bar_window
,
899 &part
, &x
, &y
, &time
);
900 #endif /* not HAVE_X_WINDOWS */
903 XSETFRAME (window
, new_f
);
906 window
= selected_window
;
915 /* Decode where to put the menu. */
923 else if (WINDOWP (window
))
925 CHECK_LIVE_WINDOW (window
);
926 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
928 xpos
= WINDOW_LEFT_EDGE_X (XWINDOW (window
));
929 ypos
= WINDOW_TOP_EDGE_Y (XWINDOW (window
));
932 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
933 but I don't want to make one now. */
934 CHECK_WINDOW (window
);
940 error ("Can not put X menu on non-X terminal");
942 XSETFRAME (Vmenu_updating_frame
, f
);
945 Vmenu_updating_frame
= Qnil
;
946 #endif /* HAVE_MENUS */
948 record_unwind_protect (unuse_menu_items
, Qnil
);
952 /* Decode the menu items from what was specified. */
954 keymap
= get_keymap (menu
, 0, 0);
957 /* We were given a keymap. Extract menu info from the keymap. */
960 /* Extract the detailed info to make one pane. */
961 keymap_panes (&menu
, 1, NILP (position
));
963 /* Search for a string appearing directly as an element of the keymap.
964 That string is the title of the menu. */
965 prompt
= Fkeymap_prompt (keymap
);
966 if (NILP (title
) && !NILP (prompt
))
969 /* Make that be the pane title of the first pane. */
970 if (!NILP (prompt
) && menu_items_n_panes
>= 0)
971 XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
] = prompt
;
975 else if (CONSP (menu
) && KEYMAPP (XCAR (menu
)))
977 /* We were given a list of keymaps. */
978 int nmaps
= XFASTINT (Flength (menu
));
980 = (Lisp_Object
*) alloca (nmaps
* sizeof (Lisp_Object
));
985 /* The first keymap that has a prompt string
986 supplies the menu title. */
987 for (tem
= menu
, i
= 0; CONSP (tem
); tem
= XCDR (tem
))
991 maps
[i
++] = keymap
= get_keymap (XCAR (tem
), 1, 0);
993 prompt
= Fkeymap_prompt (keymap
);
994 if (NILP (title
) && !NILP (prompt
))
998 /* Extract the detailed info to make one pane. */
999 keymap_panes (maps
, nmaps
, NILP (position
));
1001 /* Make the title be the pane title of the first pane. */
1002 if (!NILP (title
) && menu_items_n_panes
>= 0)
1003 XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
] = title
;
1009 /* We were given an old-fashioned menu. */
1010 title
= Fcar (menu
);
1011 CHECK_STRING (title
);
1013 list_of_panes (Fcdr (menu
));
1018 unbind_to (specpdl_count
, Qnil
);
1020 if (NILP (position
))
1022 discard_menu_items ();
1028 /* Display them in a menu. */
1031 selection
= xmenu_show (f
, xpos
, ypos
, for_click
,
1032 keymaps
, title
, &error_name
);
1035 discard_menu_items ();
1038 #endif /* HAVE_MENUS */
1040 if (error_name
) error (error_name
);
1046 DEFUN ("x-popup-dialog", Fx_popup_dialog
, Sx_popup_dialog
, 2, 3, 0,
1047 doc
: /* Pop up a dialog box and return user's selection.
1048 POSITION specifies which frame to use.
1049 This is normally a mouse button event or a window or frame.
1050 If POSITION is t, it means to use the frame the mouse is on.
1051 The dialog box appears in the middle of the specified frame.
1053 CONTENTS specifies the alternatives to display in the dialog box.
1054 It is a list of the form (DIALOG ITEM1 ITEM2...).
1055 Each ITEM is a cons cell (STRING . VALUE).
1056 The return value is VALUE from the chosen item.
1058 An ITEM may also be just a string--that makes a nonselectable item.
1059 An ITEM may also be nil--that means to put all preceding items
1060 on the left of the dialog box and all following items on the right.
1061 \(By default, approximately half appear on each side.)
1063 If HEADER is non-nil, the frame title for the box is "Information",
1064 otherwise it is "Question".
1066 If the user gets rid of the dialog box without making a valid choice,
1067 for instance using the window manager, then this produces a quit and
1068 `x-popup-dialog' does not return. */)
1069 (position
, contents
, header
)
1070 Lisp_Object position
, contents
, header
;
1077 /* Decode the first argument: find the window or frame to use. */
1078 if (EQ (position
, Qt
)
1079 || (CONSP (position
) && (EQ (XCAR (position
), Qmenu_bar
)
1080 || EQ (XCAR (position
), Qtool_bar
))))
1082 #if 0 /* Using the frame the mouse is on may not be right. */
1083 /* Use the mouse's current position. */
1084 FRAME_PTR new_f
= SELECTED_FRAME ();
1085 Lisp_Object bar_window
;
1086 enum scroll_bar_part part
;
1090 (*mouse_position_hook
) (&new_f
, 1, &bar_window
, &part
, &x
, &y
, &time
);
1093 XSETFRAME (window
, new_f
);
1095 window
= selected_window
;
1097 window
= selected_window
;
1099 else if (CONSP (position
))
1102 tem
= Fcar (position
);
1104 window
= Fcar (Fcdr (position
));
1107 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
1108 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
1111 else if (WINDOWP (position
) || FRAMEP (position
))
1116 /* Decode where to put the menu. */
1118 if (FRAMEP (window
))
1119 f
= XFRAME (window
);
1120 else if (WINDOWP (window
))
1122 CHECK_LIVE_WINDOW (window
);
1123 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
1126 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
1127 but I don't want to make one now. */
1128 CHECK_WINDOW (window
);
1130 if (! FRAME_X_P (f
))
1131 error ("Can not put X dialog on non-X terminal");
1133 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
1134 /* Display a menu with these alternatives
1135 in the middle of frame F. */
1137 Lisp_Object x
, y
, frame
, newpos
;
1138 XSETFRAME (frame
, f
);
1139 XSETINT (x
, x_pixel_width (f
) / 2);
1140 XSETINT (y
, x_pixel_height (f
) / 2);
1141 newpos
= Fcons (Fcons (x
, Fcons (y
, Qnil
)), Fcons (frame
, Qnil
));
1143 return Fx_popup_menu (newpos
,
1144 Fcons (Fcar (contents
), Fcons (contents
, Qnil
)));
1150 Lisp_Object selection
;
1151 int specpdl_count
= SPECPDL_INDEX ();
1153 /* Decode the dialog items from what was specified. */
1154 title
= Fcar (contents
);
1155 CHECK_STRING (title
);
1156 record_unwind_protect (unuse_menu_items
, Qnil
);
1158 if (NILP (Fcar (Fcdr (contents
))))
1159 /* No buttons specified, add an "Ok" button so users can pop down
1160 the dialog. Also, the lesstif/motif version crashes if there are
1162 contents
= Fcons (title
, Fcons (Fcons (build_string ("Ok"), Qt
), Qnil
));
1164 list_of_panes (Fcons (contents
, Qnil
));
1166 /* Display them in a dialog box. */
1168 selection
= xdialog_show (f
, 0, title
, header
, &error_name
);
1171 unbind_to (specpdl_count
, Qnil
);
1172 discard_menu_items ();
1174 if (error_name
) error (error_name
);
1183 /* Set menu_items_inuse so no other popup menu or dialog is created. */
1186 x_menu_set_in_use (in_use
)
1189 menu_items_inuse
= in_use
? Qt
: Qnil
;
1190 popup_activated_flag
= in_use
;
1191 #ifdef USE_X_TOOLKIT
1192 if (popup_activated_flag
)
1193 x_activate_timeout_atimer ();
1197 /* Wait for an X event to arrive or for a timer to expire. */
1200 x_menu_wait_for_event (void *data
)
1202 extern EMACS_TIME timer_check
P_ ((int));
1204 /* Another way to do this is to register a timer callback, that can be
1205 done in GTK and Xt. But we have to do it like this when using only X
1206 anyway, and with callbacks we would have three variants for timer handling
1207 instead of the small ifdefs below. */
1210 #ifdef USE_X_TOOLKIT
1211 ! XtAppPending (Xt_app_con
)
1212 #elif defined USE_GTK
1213 ! gtk_events_pending ()
1215 ! XPending ((Display
*) data
)
1219 EMACS_TIME next_time
= timer_check (1);
1220 long secs
= EMACS_SECS (next_time
);
1221 long usecs
= EMACS_USECS (next_time
);
1222 SELECT_TYPE read_fds
;
1223 struct x_display_info
*dpyinfo
;
1226 FD_ZERO (&read_fds
);
1227 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
1229 int fd
= ConnectionNumber (dpyinfo
->display
);
1230 FD_SET (fd
, &read_fds
);
1234 if (secs
< 0 || (secs
== 0 && usecs
== 0))
1236 /* Sometimes timer_check returns -1 (no timers) even if there are
1237 timers. So do a timeout anyway. */
1238 EMACS_SET_SECS (next_time
, 1);
1239 EMACS_SET_USECS (next_time
, 0);
1242 select (n
+ 1, &read_fds
, (SELECT_TYPE
*)0, (SELECT_TYPE
*)0, &next_time
);
1245 #endif /* ! MSDOS */
1248 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1250 #ifdef USE_X_TOOLKIT
1252 /* Loop in Xt until the menu pulldown or dialog popup has been
1253 popped down (deactivated). This is used for x-popup-menu
1254 and x-popup-dialog; it is not used for the menu bar.
1256 NOTE: All calls to popup_get_selection should be protected
1257 with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */
1260 popup_get_selection (initial_event
, dpyinfo
, id
, do_timers
)
1261 XEvent
*initial_event
;
1262 struct x_display_info
*dpyinfo
;
1268 while (popup_activated_flag
)
1272 event
= *initial_event
;
1277 if (do_timers
) x_menu_wait_for_event (0);
1278 XtAppNextEvent (Xt_app_con
, &event
);
1281 /* Make sure we don't consider buttons grabbed after menu goes.
1282 And make sure to deactivate for any ButtonRelease,
1283 even if XtDispatchEvent doesn't do that. */
1284 if (event
.type
== ButtonRelease
1285 && dpyinfo
->display
== event
.xbutton
.display
)
1287 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
1288 #ifdef USE_MOTIF /* Pretending that the event came from a
1289 Btn1Down seems the only way to convince Motif to
1290 activate its callbacks; setting the XmNmenuPost
1291 isn't working. --marcus@sysc.pdx.edu. */
1292 event
.xbutton
.button
= 1;
1293 /* Motif only pops down menus when no Ctrl, Alt or Mod
1294 key is pressed and the button is released. So reset key state
1295 so Motif thinks this is the case. */
1296 event
.xbutton
.state
= 0;
1299 /* Pop down on C-g and Escape. */
1300 else if (event
.type
== KeyPress
1301 && dpyinfo
->display
== event
.xbutton
.display
)
1303 KeySym keysym
= XLookupKeysym (&event
.xkey
, 0);
1305 if ((keysym
== XK_g
&& (event
.xkey
.state
& ControlMask
) != 0)
1306 || keysym
== XK_Escape
) /* Any escape, ignore modifiers. */
1307 popup_activated_flag
= 0;
1310 x_dispatch_event (&event
, event
.xany
.display
);
1314 DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal
, Sx_menu_bar_open_internal
, 0, 1, "i",
1315 doc
: /* Start key navigation of the menu bar in FRAME.
1316 This initially opens the first menu bar item and you can then navigate with the
1317 arrow keys, select a menu entry with the return key or cancel with the
1318 escape key. If FRAME has no menu bar this function does nothing.
1320 If FRAME is nil or not given, use the selected frame. */)
1325 FRAME_PTR f
= check_x_frame (frame
);
1329 if (FRAME_EXTERNAL_MENU_BAR (f
))
1330 set_frame_menubar (f
, 0, 1);
1332 menubar
= FRAME_X_OUTPUT (f
)->menubar_widget
;
1338 x_catch_errors (FRAME_X_DISPLAY (f
));
1339 memset (&ev
, 0, sizeof ev
);
1340 ev
.xbutton
.display
= FRAME_X_DISPLAY (f
);
1341 ev
.xbutton
.window
= XtWindow (menubar
);
1342 ev
.xbutton
.root
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
1343 ev
.xbutton
.time
= XtLastTimestampProcessed (FRAME_X_DISPLAY (f
));
1344 ev
.xbutton
.button
= Button1
;
1345 ev
.xbutton
.x
= ev
.xbutton
.y
= FRAME_MENUBAR_HEIGHT (f
) / 2;
1346 ev
.xbutton
.same_screen
= True
;
1353 XtSetArg (al
[0], XtNchildren
, &list
);
1354 XtSetArg (al
[1], XtNnumChildren
, &nr
);
1355 XtGetValues (menubar
, al
, 2);
1356 ev
.xbutton
.window
= XtWindow (list
[0]);
1360 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
1361 /* From-window, to-window. */
1362 ev
.xbutton
.window
, ev
.xbutton
.root
,
1364 /* From-position, to-position. */
1365 ev
.xbutton
.x
, ev
.xbutton
.y
,
1366 &ev
.xbutton
.x_root
, &ev
.xbutton
.y_root
,
1370 error_p
= x_had_errors_p (FRAME_X_DISPLAY (f
));
1371 x_uncatch_errors ();
1375 ev
.type
= ButtonPress
;
1376 ev
.xbutton
.state
= 0;
1378 XtDispatchEvent (&ev
);
1379 ev
.xbutton
.type
= ButtonRelease
;
1380 ev
.xbutton
.state
= Button1Mask
;
1381 XtDispatchEvent (&ev
);
1389 #endif /* USE_X_TOOLKIT */
1393 DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal
, Sx_menu_bar_open_internal
, 0, 1, "i",
1394 doc
: /* Start key navigation of the menu bar in FRAME.
1395 This initially opens the first menu bar item and you can then navigate with the
1396 arrow keys, select a menu entry with the return key or cancel with the
1397 escape key. If FRAME has no menu bar this function does nothing.
1399 If FRAME is nil or not given, use the selected frame. */)
1406 /* gcc 2.95 doesn't accept the FRAME_PTR declaration after
1410 f
= check_x_frame (frame
);
1412 if (FRAME_EXTERNAL_MENU_BAR (f
))
1413 set_frame_menubar (f
, 0, 1);
1415 menubar
= FRAME_X_OUTPUT (f
)->menubar_widget
;
1418 /* Activate the first menu. */
1419 GList
*children
= gtk_container_get_children (GTK_CONTAINER (menubar
));
1421 gtk_menu_shell_select_item (GTK_MENU_SHELL (menubar
),
1422 GTK_WIDGET (children
->data
));
1424 popup_activated_flag
= 1;
1425 g_list_free (children
);
1432 /* Loop util popup_activated_flag is set to zero in a callback.
1433 Used for popup menus and dialogs. */
1436 popup_widget_loop (do_timers
, widget
)
1440 ++popup_activated_flag
;
1442 /* Process events in the Gtk event loop until done. */
1443 while (popup_activated_flag
)
1445 if (do_timers
) x_menu_wait_for_event (0);
1446 gtk_main_iteration ();
1451 /* Activate the menu bar of frame F.
1452 This is called from keyboard.c when it gets the
1453 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
1455 To activate the menu bar, we use the X button-press event
1456 that was saved in saved_menu_event.
1457 That makes the toolkit do its thing.
1459 But first we recompute the menu bar contents (the whole tree).
1461 The reason for saving the button event until here, instead of
1462 passing it to the toolkit right away, is that we can safely
1463 execute Lisp code. */
1466 x_activate_menubar (f
)
1469 if (! FRAME_X_P (f
))
1472 if (!f
->output_data
.x
->saved_menu_event
->type
)
1476 if (! xg_win_to_widget (FRAME_X_DISPLAY (f
),
1477 f
->output_data
.x
->saved_menu_event
->xany
.window
))
1481 set_frame_menubar (f
, 0, 1);
1484 XPutBackEvent (f
->output_data
.x
->display_info
->display
,
1485 f
->output_data
.x
->saved_menu_event
);
1486 popup_activated_flag
= 1;
1488 XtDispatchEvent (f
->output_data
.x
->saved_menu_event
);
1492 if (f
->output_data
.x
->saved_menu_event
->type
== ButtonRelease
)
1493 pending_menu_activation
= 1;
1496 /* Ignore this if we get it a second time. */
1497 f
->output_data
.x
->saved_menu_event
->type
= 0;
1500 /* This callback is invoked when the user selects a menubar cascade
1501 pushbutton, but before the pulldown menu is posted. */
1505 popup_activate_callback (widget
, id
, client_data
)
1508 XtPointer client_data
;
1510 popup_activated_flag
= 1;
1511 #ifdef USE_X_TOOLKIT
1512 x_activate_timeout_atimer ();
1517 /* This callback is invoked when a dialog or menu is finished being
1518 used and has been unposted. */
1522 popup_deactivate_callback (widget
, client_data
)
1524 gpointer client_data
;
1526 popup_activated_flag
= 0;
1530 popup_deactivate_callback (widget
, id
, client_data
)
1533 XtPointer client_data
;
1535 popup_activated_flag
= 0;
1540 /* Function that finds the frame for WIDGET and shows the HELP text
1542 F is the frame if known, or NULL if not known. */
1544 show_help_event (f
, widget
, help
)
1546 xt_or_gtk_widget widget
;
1553 XSETFRAME (frame
, f
);
1554 kbd_buffer_store_help_event (frame
, help
);
1558 #if 0 /* This code doesn't do anything useful. ++kfs */
1559 /* WIDGET is the popup menu. It's parent is the frame's
1560 widget. See which frame that is. */
1561 xt_or_gtk_widget frame_widget
= XtParent (widget
);
1564 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
1566 frame
= XCAR (tail
);
1568 && (f
= XFRAME (frame
),
1569 FRAME_X_P (f
) && f
->output_data
.x
->widget
== frame_widget
))
1573 show_help_echo (help
, Qnil
, Qnil
, Qnil
, 1);
1577 /* Callback called when menu items are highlighted/unhighlighted
1578 while moving the mouse over them. WIDGET is the menu bar or menu
1579 popup widget. ID is its LWLIB_ID. CALL_DATA contains a pointer to
1580 the data structure for the menu item, or null in case of
1585 menu_highlight_callback (widget
, call_data
)
1589 xg_menu_item_cb_data
*cb_data
;
1592 cb_data
= (xg_menu_item_cb_data
*) g_object_get_data (G_OBJECT (widget
),
1594 if (! cb_data
) return;
1596 help
= call_data
? cb_data
->help
: Qnil
;
1598 /* If popup_activated_flag is greater than 1 we are in a popup menu.
1599 Don't show help for them, they won't appear before the
1600 popup is popped down. */
1601 if (popup_activated_flag
<= 1)
1602 show_help_event (cb_data
->cl_data
->f
, widget
, help
);
1606 menu_highlight_callback (widget
, id
, call_data
)
1614 widget_value
*wv
= (widget_value
*) call_data
;
1616 help
= wv
? wv
->help
: Qnil
;
1618 /* Determine the frame for the help event. */
1619 f
= menubar_id_to_frame (id
);
1621 show_help_event (f
, widget
, help
);
1625 /* Find the menu selection and store it in the keyboard buffer.
1626 F is the frame the menu is on.
1627 MENU_BAR_ITEMS_USED is the length of VECTOR.
1628 VECTOR is an array of menu events for the whole menu. */
1631 find_and_call_menu_selection (f
, menu_bar_items_used
, vector
, client_data
)
1633 EMACS_INT menu_bar_items_used
;
1637 Lisp_Object prefix
, entry
;
1638 Lisp_Object
*subprefix_stack
;
1639 int submenu_depth
= 0;
1643 subprefix_stack
= (Lisp_Object
*) alloca (menu_bar_items_used
* sizeof (Lisp_Object
));
1647 while (i
< menu_bar_items_used
)
1649 if (EQ (XVECTOR (vector
)->contents
[i
], Qnil
))
1651 subprefix_stack
[submenu_depth
++] = prefix
;
1655 else if (EQ (XVECTOR (vector
)->contents
[i
], Qlambda
))
1657 prefix
= subprefix_stack
[--submenu_depth
];
1660 else if (EQ (XVECTOR (vector
)->contents
[i
], Qt
))
1662 prefix
= XVECTOR (vector
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
1663 i
+= MENU_ITEMS_PANE_LENGTH
;
1667 entry
= XVECTOR (vector
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
1668 /* The EMACS_INT cast avoids a warning. There's no problem
1669 as long as pointers have enough bits to hold small integers. */
1670 if ((int) (EMACS_INT
) client_data
== i
)
1673 struct input_event buf
;
1677 XSETFRAME (frame
, f
);
1678 buf
.kind
= MENU_BAR_EVENT
;
1679 buf
.frame_or_window
= frame
;
1681 kbd_buffer_store_event (&buf
);
1683 for (j
= 0; j
< submenu_depth
; j
++)
1684 if (!NILP (subprefix_stack
[j
]))
1686 buf
.kind
= MENU_BAR_EVENT
;
1687 buf
.frame_or_window
= frame
;
1688 buf
.arg
= subprefix_stack
[j
];
1689 kbd_buffer_store_event (&buf
);
1694 buf
.kind
= MENU_BAR_EVENT
;
1695 buf
.frame_or_window
= frame
;
1697 kbd_buffer_store_event (&buf
);
1700 buf
.kind
= MENU_BAR_EVENT
;
1701 buf
.frame_or_window
= frame
;
1703 kbd_buffer_store_event (&buf
);
1707 i
+= MENU_ITEMS_ITEM_LENGTH
;
1714 /* Gtk calls callbacks just because we tell it what item should be
1715 selected in a radio group. If this variable is set to a non-zero
1716 value, we are creating menus and don't want callbacks right now.
1718 static int xg_crazy_callback_abort
;
1720 /* This callback is called from the menu bar pulldown menu
1721 when the user makes a selection.
1722 Figure out what the user chose
1723 and put the appropriate events into the keyboard buffer. */
1725 menubar_selection_callback (widget
, client_data
)
1727 gpointer client_data
;
1729 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) client_data
;
1731 if (xg_crazy_callback_abort
)
1734 if (! cb_data
|| ! cb_data
->cl_data
|| ! cb_data
->cl_data
->f
)
1737 /* For a group of radio buttons, GTK calls the selection callback first
1738 for the item that was active before the selection and then for the one that
1739 is active after the selection. For C-h k this means we get the help on
1740 the deselected item and then the selected item is executed. Prevent that
1741 by ignoring the non-active item. */
1742 if (GTK_IS_RADIO_MENU_ITEM (widget
)
1743 && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget
)))
1746 /* When a menu is popped down, X generates a focus event (i.e. focus
1747 goes back to the frame below the menu). Since GTK buffers events,
1748 we force it out here before the menu selection event. Otherwise
1749 sit-for will exit at once if the focus event follows the menu selection
1753 while (gtk_events_pending ())
1754 gtk_main_iteration ();
1757 find_and_call_menu_selection (cb_data
->cl_data
->f
,
1758 cb_data
->cl_data
->menu_bar_items_used
,
1759 cb_data
->cl_data
->menu_bar_vector
,
1760 cb_data
->call_data
);
1763 #else /* not USE_GTK */
1765 /* This callback is called from the menu bar pulldown menu
1766 when the user makes a selection.
1767 Figure out what the user chose
1768 and put the appropriate events into the keyboard buffer. */
1770 menubar_selection_callback (widget
, id
, client_data
)
1773 XtPointer client_data
;
1777 f
= menubar_id_to_frame (id
);
1780 find_and_call_menu_selection (f
, f
->menu_bar_items_used
,
1781 f
->menu_bar_vector
, client_data
);
1783 #endif /* not USE_GTK */
1785 /* Allocate a widget_value, blocking input. */
1788 xmalloc_widget_value ()
1790 widget_value
*value
;
1793 value
= malloc_widget_value ();
1799 /* This recursively calls free_widget_value on the tree of widgets.
1800 It must free all data that was malloc'ed for these widget_values.
1801 In Emacs, many slots are pointers into the data of Lisp_Strings, and
1802 must be left alone. */
1805 free_menubar_widget_value_tree (wv
)
1810 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
1812 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
1814 free_menubar_widget_value_tree (wv
->contents
);
1815 wv
->contents
= (widget_value
*) 0xDEADBEEF;
1819 free_menubar_widget_value_tree (wv
->next
);
1820 wv
->next
= (widget_value
*) 0xDEADBEEF;
1823 free_widget_value (wv
);
1827 /* Set up data in menu_items for a menu bar item
1828 whose event type is ITEM_KEY (with string ITEM_NAME)
1829 and whose contents come from the list of keymaps MAPS. */
1832 parse_single_submenu (item_key
, item_name
, maps
)
1833 Lisp_Object item_key
, item_name
, maps
;
1837 Lisp_Object
*mapvec
;
1839 int top_level_items
= 0;
1841 length
= Flength (maps
);
1842 len
= XINT (length
);
1844 /* Convert the list MAPS into a vector MAPVEC. */
1845 mapvec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
1846 for (i
= 0; i
< len
; i
++)
1848 mapvec
[i
] = Fcar (maps
);
1852 /* Loop over the given keymaps, making a pane for each map.
1853 But don't make a pane that is empty--ignore that map instead. */
1854 for (i
= 0; i
< len
; i
++)
1856 if (!KEYMAPP (mapvec
[i
]))
1858 /* Here we have a command at top level in the menu bar
1859 as opposed to a submenu. */
1860 top_level_items
= 1;
1861 push_menu_pane (Qnil
, Qnil
);
1862 push_menu_item (item_name
, Qt
, item_key
, mapvec
[i
],
1863 Qnil
, Qnil
, Qnil
, Qnil
);
1868 prompt
= Fkeymap_prompt (mapvec
[i
]);
1869 single_keymap_panes (mapvec
[i
],
1870 !NILP (prompt
) ? prompt
: item_name
,
1875 return top_level_items
;
1878 /* Create a tree of widget_value objects
1879 representing the panes and items
1880 in menu_items starting at index START, up to index END. */
1882 static widget_value
*
1883 digest_single_submenu (start
, end
, top_level_items
)
1884 int start
, end
, top_level_items
;
1886 widget_value
*wv
, *prev_wv
, *save_wv
, *first_wv
;
1888 int submenu_depth
= 0;
1889 widget_value
**submenu_stack
;
1893 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
1894 wv
= xmalloc_widget_value ();
1898 wv
->button_type
= BUTTON_TYPE_NONE
;
1904 /* Loop over all panes and items made by the preceding call
1905 to parse_single_submenu and construct a tree of widget_value objects.
1906 Ignore the panes and items used by previous calls to
1907 digest_single_submenu, even though those are also in menu_items. */
1911 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1913 submenu_stack
[submenu_depth
++] = save_wv
;
1918 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1921 save_wv
= submenu_stack
[--submenu_depth
];
1924 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
1925 && submenu_depth
!= 0)
1926 i
+= MENU_ITEMS_PANE_LENGTH
;
1927 /* Ignore a nil in the item list.
1928 It's meaningful only for dialog boxes. */
1929 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1931 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1933 /* Create a new pane. */
1934 Lisp_Object pane_name
, prefix
;
1939 pane_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_NAME
];
1940 prefix
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
1942 #ifndef HAVE_MULTILINGUAL_MENU
1943 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
1945 pane_name
= ENCODE_MENU_STRING (pane_name
);
1946 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
1949 pane_string
= (NILP (pane_name
)
1950 ? "" : (char *) SDATA (pane_name
));
1951 /* If there is just one top-level pane, put all its items directly
1952 under the top-level menu. */
1953 if (menu_items_n_panes
== 1)
1956 /* If the pane has a meaningful name,
1957 make the pane a top-level menu item
1958 with its items as a submenu beneath it. */
1959 if (strcmp (pane_string
, ""))
1961 wv
= xmalloc_widget_value ();
1965 first_wv
->contents
= wv
;
1966 wv
->lname
= pane_name
;
1967 /* Set value to 1 so update_submenu_strings can handle '@' */
1968 wv
->value
= (char *)1;
1970 wv
->button_type
= BUTTON_TYPE_NONE
;
1978 i
+= MENU_ITEMS_PANE_LENGTH
;
1982 /* Create a new item within current pane. */
1983 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
;
1986 /* All items should be contained in panes. */
1987 if (panes_seen
== 0)
1990 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
1991 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
1992 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
1993 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
1994 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
1995 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
1996 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
1998 #ifndef HAVE_MULTILINGUAL_MENU
1999 if (STRING_MULTIBYTE (item_name
))
2001 item_name
= ENCODE_MENU_STRING (item_name
);
2002 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
2005 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
2007 descrip
= ENCODE_MENU_STRING (descrip
);
2008 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
2010 #endif /* not HAVE_MULTILINGUAL_MENU */
2012 wv
= xmalloc_widget_value ();
2016 save_wv
->contents
= wv
;
2018 wv
->lname
= item_name
;
2019 if (!NILP (descrip
))
2022 /* The EMACS_INT cast avoids a warning. There's no problem
2023 as long as pointers have enough bits to hold small integers. */
2024 wv
->call_data
= (!NILP (def
) ? (void *) (EMACS_INT
) i
: 0);
2025 wv
->enabled
= !NILP (enable
);
2028 wv
->button_type
= BUTTON_TYPE_NONE
;
2029 else if (EQ (type
, QCradio
))
2030 wv
->button_type
= BUTTON_TYPE_RADIO
;
2031 else if (EQ (type
, QCtoggle
))
2032 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
2036 wv
->selected
= !NILP (selected
);
2037 if (! STRINGP (help
))
2044 i
+= MENU_ITEMS_ITEM_LENGTH
;
2048 /* If we have just one "menu item"
2049 that was originally a button, return it by itself. */
2050 if (top_level_items
&& first_wv
->contents
&& first_wv
->contents
->next
== 0)
2052 wv
= first_wv
->contents
;
2053 free_widget_value (first_wv
);
2060 /* Walk through the widget_value tree starting at FIRST_WV and update
2061 the char * pointers from the corresponding lisp values.
2062 We do this after building the whole tree, since GC may happen while the
2063 tree is constructed, and small strings are relocated. So we must wait
2064 until no GC can happen before storing pointers into lisp values. */
2066 update_submenu_strings (first_wv
)
2067 widget_value
*first_wv
;
2071 for (wv
= first_wv
; wv
; wv
= wv
->next
)
2073 if (STRINGP (wv
->lname
))
2075 wv
->name
= (char *) SDATA (wv
->lname
);
2077 /* Ignore the @ that means "separate pane".
2078 This is a kludge, but this isn't worth more time. */
2079 if (wv
->value
== (char *)1)
2081 if (wv
->name
[0] == '@')
2087 if (STRINGP (wv
->lkey
))
2088 wv
->key
= (char *) SDATA (wv
->lkey
);
2091 update_submenu_strings (wv
->contents
);
2096 /* Recompute all the widgets of frame F, when the menu bar has been
2097 changed. Value is non-zero if widgets were updated. */
2100 update_frame_menubar (f
)
2104 return xg_update_frame_menubar (f
);
2109 if (! FRAME_X_P (f
))
2112 x
= f
->output_data
.x
;
2114 if (!x
->menubar_widget
|| XtIsManaged (x
->menubar_widget
))
2118 /* Save the size of the frame because the pane widget doesn't accept
2119 to resize itself. So force it. */
2120 columns
= FRAME_COLS (f
);
2121 rows
= FRAME_LINES (f
);
2123 /* Do the voodoo which means "I'm changing lots of things, don't try
2124 to refigure sizes until I'm done." */
2125 lw_refigure_widget (x
->column_widget
, False
);
2127 /* The order in which children are managed is the top to bottom
2128 order in which they are displayed in the paned window. First,
2129 remove the text-area widget. */
2130 XtUnmanageChild (x
->edit_widget
);
2132 /* Remove the menubar that is there now, and put up the menubar that
2134 XtManageChild (x
->menubar_widget
);
2135 XtMapWidget (x
->menubar_widget
);
2136 XtVaSetValues (x
->menubar_widget
, XtNmappedWhenManaged
, 1, NULL
);
2138 /* Re-manage the text-area widget, and then thrash the sizes. */
2139 XtManageChild (x
->edit_widget
);
2140 lw_refigure_widget (x
->column_widget
, True
);
2142 /* Force the pane widget to resize itself with the right values. */
2143 EmacsFrameSetCharSize (x
->edit_widget
, columns
, rows
);
2149 /* Set the contents of the menubar widgets of frame F.
2150 The argument FIRST_TIME is currently ignored;
2151 it is set the first time this is called, from initialize_frame_menubar. */
2154 set_frame_menubar (f
, first_time
, deep_p
)
2159 xt_or_gtk_widget menubar_widget
;
2160 #ifdef USE_X_TOOLKIT
2164 widget_value
*wv
, *first_wv
, *prev_wv
= 0;
2166 int *submenu_start
, *submenu_end
;
2167 int *submenu_top_level_items
, *submenu_n_panes
;
2169 if (! FRAME_X_P (f
))
2172 menubar_widget
= f
->output_data
.x
->menubar_widget
;
2174 XSETFRAME (Vmenu_updating_frame
, f
);
2176 #ifdef USE_X_TOOLKIT
2177 if (f
->output_data
.x
->id
== 0)
2178 f
->output_data
.x
->id
= next_menubar_widget_id
++;
2179 id
= f
->output_data
.x
->id
;
2182 if (! menubar_widget
)
2184 else if (pending_menu_activation
&& !deep_p
)
2186 /* Make the first call for any given frame always go deep. */
2187 else if (!f
->output_data
.x
->saved_menu_event
&& !deep_p
)
2190 f
->output_data
.x
->saved_menu_event
= (XEvent
*)xmalloc (sizeof (XEvent
));
2191 f
->output_data
.x
->saved_menu_event
->type
= 0;
2195 /* If we have detached menus, we must update deep so detached menus
2196 also gets updated. */
2197 deep_p
= deep_p
|| xg_have_tear_offs ();
2202 /* Make a widget-value tree representing the entire menu trees. */
2204 struct buffer
*prev
= current_buffer
;
2206 int specpdl_count
= SPECPDL_INDEX ();
2207 int previous_menu_items_used
= f
->menu_bar_items_used
;
2208 Lisp_Object
*previous_items
2209 = (Lisp_Object
*) alloca (previous_menu_items_used
2210 * sizeof (Lisp_Object
));
2212 /* If we are making a new widget, its contents are empty,
2213 do always reinitialize them. */
2214 if (! menubar_widget
)
2215 previous_menu_items_used
= 0;
2217 buffer
= XWINDOW (FRAME_SELECTED_WINDOW (f
))->buffer
;
2218 specbind (Qinhibit_quit
, Qt
);
2219 /* Don't let the debugger step into this code
2220 because it is not reentrant. */
2221 specbind (Qdebug_on_next_call
, Qnil
);
2223 record_unwind_save_match_data ();
2224 if (NILP (Voverriding_local_map_menu_flag
))
2226 specbind (Qoverriding_terminal_local_map
, Qnil
);
2227 specbind (Qoverriding_local_map
, Qnil
);
2230 set_buffer_internal_1 (XBUFFER (buffer
));
2232 /* Run the Lucid hook. */
2233 safe_run_hooks (Qactivate_menubar_hook
);
2235 /* If it has changed current-menubar from previous value,
2236 really recompute the menubar from the value. */
2237 if (! NILP (Vlucid_menu_bar_dirty_flag
))
2238 call0 (Qrecompute_lucid_menubar
);
2239 safe_run_hooks (Qmenu_bar_update_hook
);
2240 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
2242 items
= FRAME_MENU_BAR_ITEMS (f
);
2244 /* Save the frame's previous menu bar contents data. */
2245 if (previous_menu_items_used
)
2246 bcopy (XVECTOR (f
->menu_bar_vector
)->contents
, previous_items
,
2247 previous_menu_items_used
* sizeof (Lisp_Object
));
2249 /* Fill in menu_items with the current menu bar contents.
2250 This can evaluate Lisp code. */
2253 menu_items
= f
->menu_bar_vector
;
2254 menu_items_allocated
= VECTORP (menu_items
) ? ASIZE (menu_items
) : 0;
2255 submenu_start
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
2256 submenu_end
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
2257 submenu_n_panes
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int));
2258 submenu_top_level_items
2259 = (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
2261 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
2263 Lisp_Object key
, string
, maps
;
2267 key
= XVECTOR (items
)->contents
[i
];
2268 string
= XVECTOR (items
)->contents
[i
+ 1];
2269 maps
= XVECTOR (items
)->contents
[i
+ 2];
2273 submenu_start
[i
] = menu_items_used
;
2275 menu_items_n_panes
= 0;
2276 submenu_top_level_items
[i
]
2277 = parse_single_submenu (key
, string
, maps
);
2278 submenu_n_panes
[i
] = menu_items_n_panes
;
2280 submenu_end
[i
] = menu_items_used
;
2283 finish_menu_items ();
2285 /* Convert menu_items into widget_value trees
2286 to display the menu. This cannot evaluate Lisp code. */
2288 wv
= xmalloc_widget_value ();
2289 wv
->name
= "menubar";
2292 wv
->button_type
= BUTTON_TYPE_NONE
;
2296 for (i
= 0; i
< last_i
; i
+= 4)
2298 menu_items_n_panes
= submenu_n_panes
[i
];
2299 wv
= digest_single_submenu (submenu_start
[i
], submenu_end
[i
],
2300 submenu_top_level_items
[i
]);
2304 first_wv
->contents
= wv
;
2305 /* Don't set wv->name here; GC during the loop might relocate it. */
2307 wv
->button_type
= BUTTON_TYPE_NONE
;
2311 set_buffer_internal_1 (prev
);
2313 /* If there has been no change in the Lisp-level contents
2314 of the menu bar, skip redisplaying it. Just exit. */
2316 /* Compare the new menu items with the ones computed last time. */
2317 for (i
= 0; i
< previous_menu_items_used
; i
++)
2318 if (menu_items_used
== i
2319 || (!EQ (previous_items
[i
], XVECTOR (menu_items
)->contents
[i
])))
2321 if (i
== menu_items_used
&& i
== previous_menu_items_used
&& i
!= 0)
2323 /* The menu items have not changed. Don't bother updating
2324 the menus in any form, since it would be a no-op. */
2325 free_menubar_widget_value_tree (first_wv
);
2326 discard_menu_items ();
2327 unbind_to (specpdl_count
, Qnil
);
2331 /* The menu items are different, so store them in the frame. */
2332 f
->menu_bar_vector
= menu_items
;
2333 f
->menu_bar_items_used
= menu_items_used
;
2335 /* This calls restore_menu_items to restore menu_items, etc.,
2336 as they were outside. */
2337 unbind_to (specpdl_count
, Qnil
);
2339 /* Now GC cannot happen during the lifetime of the widget_value,
2340 so it's safe to store data from a Lisp_String. */
2341 wv
= first_wv
->contents
;
2342 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
2345 string
= XVECTOR (items
)->contents
[i
+ 1];
2348 wv
->name
= (char *) SDATA (string
);
2349 update_submenu_strings (wv
->contents
);
2356 /* Make a widget-value tree containing
2357 just the top level menu bar strings. */
2359 wv
= xmalloc_widget_value ();
2360 wv
->name
= "menubar";
2363 wv
->button_type
= BUTTON_TYPE_NONE
;
2367 items
= FRAME_MENU_BAR_ITEMS (f
);
2368 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
2372 string
= XVECTOR (items
)->contents
[i
+ 1];
2376 wv
= xmalloc_widget_value ();
2377 wv
->name
= (char *) SDATA (string
);
2380 wv
->button_type
= BUTTON_TYPE_NONE
;
2382 /* This prevents lwlib from assuming this
2383 menu item is really supposed to be empty. */
2384 /* The EMACS_INT cast avoids a warning.
2385 This value just has to be different from small integers. */
2386 wv
->call_data
= (void *) (EMACS_INT
) (-1);
2391 first_wv
->contents
= wv
;
2395 /* Forget what we thought we knew about what is in the
2396 detailed contents of the menu bar menus.
2397 Changing the top level always destroys the contents. */
2398 f
->menu_bar_items_used
= 0;
2401 /* Create or update the menu bar widget. */
2406 xg_crazy_callback_abort
= 1;
2409 /* The fourth arg is DEEP_P, which says to consider the entire
2410 menu trees we supply, rather than just the menu bar item names. */
2411 xg_modify_menubar_widgets (menubar_widget
,
2415 G_CALLBACK (menubar_selection_callback
),
2416 G_CALLBACK (popup_deactivate_callback
),
2417 G_CALLBACK (menu_highlight_callback
));
2421 GtkWidget
*wvbox
= f
->output_data
.x
->vbox_widget
;
2424 = xg_create_widget ("menubar", "menubar", f
, first_wv
,
2425 G_CALLBACK (menubar_selection_callback
),
2426 G_CALLBACK (popup_deactivate_callback
),
2427 G_CALLBACK (menu_highlight_callback
));
2429 f
->output_data
.x
->menubar_widget
= menubar_widget
;
2433 #else /* not USE_GTK */
2436 /* Disable resizing (done for Motif!) */
2437 lw_allow_resizing (f
->output_data
.x
->widget
, False
);
2439 /* The third arg is DEEP_P, which says to consider the entire
2440 menu trees we supply, rather than just the menu bar item names. */
2441 lw_modify_all_widgets (id
, first_wv
, deep_p
);
2443 /* Re-enable the edit widget to resize. */
2444 lw_allow_resizing (f
->output_data
.x
->widget
, True
);
2448 char menuOverride
[] = "Ctrl<KeyPress>g: MenuGadgetEscape()";
2449 XtTranslations override
= XtParseTranslationTable (menuOverride
);
2451 menubar_widget
= lw_create_widget ("menubar", "menubar", id
, first_wv
,
2452 f
->output_data
.x
->column_widget
,
2454 popup_activate_callback
,
2455 menubar_selection_callback
,
2456 popup_deactivate_callback
,
2457 menu_highlight_callback
);
2458 f
->output_data
.x
->menubar_widget
= menubar_widget
;
2460 /* Make menu pop down on C-g. */
2461 XtOverrideTranslations (menubar_widget
, override
);
2466 = (f
->output_data
.x
->menubar_widget
2467 ? (f
->output_data
.x
->menubar_widget
->core
.height
2468 + f
->output_data
.x
->menubar_widget
->core
.border_width
)
2471 #if 0 /* Experimentally, we now get the right results
2472 for -geometry -0-0 without this. 24 Aug 96, rms. */
2474 if (FRAME_EXTERNAL_MENU_BAR (f
))
2477 XtVaGetValues (f
->output_data
.x
->column_widget
,
2478 XtNinternalBorderWidth
, &ibw
, NULL
);
2479 menubar_size
+= ibw
;
2481 #endif /* USE_LUCID */
2484 f
->output_data
.x
->menubar_height
= menubar_size
;
2486 #endif /* not USE_GTK */
2488 free_menubar_widget_value_tree (first_wv
);
2489 update_frame_menubar (f
);
2492 xg_crazy_callback_abort
= 0;
2498 /* Called from Fx_create_frame to create the initial menubar of a frame
2499 before it is mapped, so that the window is mapped with the menubar already
2500 there instead of us tacking it on later and thrashing the window after it
2504 initialize_frame_menubar (f
)
2507 /* This function is called before the first chance to redisplay
2508 the frame. It has to be, so the frame will have the right size. */
2509 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
2510 set_frame_menubar (f
, 1, 1);
2514 /* Get rid of the menu bar of frame F, and free its storage.
2515 This is used when deleting a frame, and when turning off the menu bar.
2516 For GTK this function is in gtkutil.c. */
2520 free_frame_menubar (f
)
2523 Widget menubar_widget
;
2525 if (! FRAME_X_P (f
))
2528 menubar_widget
= f
->output_data
.x
->menubar_widget
;
2530 f
->output_data
.x
->menubar_height
= 0;
2535 /* Removing the menu bar magically changes the shell widget's x
2536 and y position of (0, 0) which, when the menu bar is turned
2537 on again, leads to pull-down menuss appearing in strange
2538 positions near the upper-left corner of the display. This
2539 happens only with some window managers like twm and ctwm,
2540 but not with other like Motif's mwm or kwm, because the
2541 latter generate ConfigureNotify events when the menu bar
2542 is switched off, which fixes the shell position. */
2543 Position x0
, y0
, x1
, y1
;
2549 if (f
->output_data
.x
->widget
)
2550 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x0
, XtNy
, &y0
, NULL
);
2553 lw_destroy_all_widgets ((LWLIB_ID
) f
->output_data
.x
->id
);
2554 f
->output_data
.x
->menubar_widget
= NULL
;
2557 if (f
->output_data
.x
->widget
)
2559 XtVaGetValues (f
->output_data
.x
->widget
, XtNx
, &x1
, XtNy
, &y1
, NULL
);
2560 if (x1
== 0 && y1
== 0)
2561 XtVaSetValues (f
->output_data
.x
->widget
, XtNx
, x0
, XtNy
, y0
, NULL
);
2568 #endif /* not USE_GTK */
2570 #endif /* USE_X_TOOLKIT || USE_GTK */
2572 /* xmenu_show actually displays a menu using the panes and items in menu_items
2573 and returns the value selected from it.
2574 There are two versions of xmenu_show, one for Xt and one for Xlib.
2575 Both assume input is blocked by the caller. */
2577 /* F is the frame the menu is for.
2578 X and Y are the frame-relative specified position,
2579 relative to the inside upper left corner of the frame F.
2580 FOR_CLICK is nonzero if this menu was invoked for a mouse click.
2581 KEYMAPS is 1 if this menu was specified with keymaps;
2582 in that case, we return a list containing the chosen item's value
2583 and perhaps also the pane's prefix.
2584 TITLE is the specified menu title.
2585 ERROR is a place to store an error message string in case of failure.
2586 (We return nil on failure, but the value doesn't actually matter.) */
2588 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
2590 /* The item selected in the popup menu. */
2591 static Lisp_Object
*volatile menu_item_selection
;
2595 /* Used when position a popup menu. See menu_position_func and
2596 create_and_show_popup_menu below. */
2597 struct next_popup_x_y
2604 /* The menu position function to use if we are not putting a popup
2605 menu where the pointer is.
2606 MENU is the menu to pop up.
2607 X and Y shall on exit contain x/y where the menu shall pop up.
2608 PUSH_IN is not documented in the GTK manual.
2609 USER_DATA is any data passed in when calling gtk_menu_popup.
2610 Here it points to a struct next_popup_x_y where the coordinates
2611 to store in *X and *Y are as well as the frame for the popup.
2613 Here only X and Y are used. */
2615 menu_position_func (menu
, x
, y
, push_in
, user_data
)
2622 struct next_popup_x_y
* data
= (struct next_popup_x_y
*)user_data
;
2624 int disp_width
= FRAME_X_DISPLAY_INFO (data
->f
)->width
;
2625 int disp_height
= FRAME_X_DISPLAY_INFO (data
->f
)->height
;
2630 /* Check if there is room for the menu. If not, adjust x/y so that
2631 the menu is fully visible. */
2632 gtk_widget_size_request (GTK_WIDGET (menu
), &req
);
2633 if (data
->x
+ req
.width
> disp_width
)
2634 *x
-= data
->x
+ req
.width
- disp_width
;
2635 if (data
->y
+ req
.height
> disp_height
)
2636 *y
-= data
->y
+ req
.height
- disp_height
;
2640 popup_selection_callback (widget
, client_data
)
2642 gpointer client_data
;
2644 xg_menu_item_cb_data
*cb_data
= (xg_menu_item_cb_data
*) client_data
;
2646 if (xg_crazy_callback_abort
) return;
2647 if (cb_data
) menu_item_selection
= (Lisp_Object
*) cb_data
->call_data
;
2654 struct Lisp_Save_Value
*p
= XSAVE_VALUE (arg
);
2656 popup_activated_flag
= 0;
2658 gtk_widget_destroy (GTK_WIDGET (p
->pointer
));
2663 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
2665 menu_item_selection will be set to the selection. */
2667 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
)
2669 widget_value
*first_wv
;
2676 GtkMenuPositionFunc pos_func
= 0; /* Pop up at pointer. */
2677 struct next_popup_x_y popup_x_y
;
2678 int specpdl_count
= SPECPDL_INDEX ();
2680 if (! FRAME_X_P (f
))
2683 xg_crazy_callback_abort
= 1;
2684 menu
= xg_create_widget ("popup", first_wv
->name
, f
, first_wv
,
2685 G_CALLBACK (popup_selection_callback
),
2686 G_CALLBACK (popup_deactivate_callback
),
2687 G_CALLBACK (menu_highlight_callback
));
2688 xg_crazy_callback_abort
= 0;
2692 /* Not invoked by a click. pop up at x/y. */
2693 pos_func
= menu_position_func
;
2695 /* Adjust coordinates to be root-window-relative. */
2696 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
2697 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
2703 i
= 0; /* gtk_menu_popup needs this to be 0 for a non-button popup. */
2707 for (i
= 0; i
< 5; i
++)
2708 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
2712 /* Display the menu. */
2713 gtk_widget_show_all (menu
);
2714 gtk_menu_popup (GTK_MENU (menu
), 0, 0, pos_func
, &popup_x_y
, i
, 0);
2716 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
2718 if (GTK_WIDGET_MAPPED (menu
))
2720 /* Set this to one. popup_widget_loop increases it by one, so it becomes
2721 two. show_help_echo uses this to detect popup menus. */
2722 popup_activated_flag
= 1;
2723 /* Process events that apply to the menu. */
2724 popup_widget_loop (1, menu
);
2727 unbind_to (specpdl_count
, Qnil
);
2729 /* Must reset this manually because the button release event is not passed
2730 to Emacs event loop. */
2731 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
2734 #else /* not USE_GTK */
2736 /* We need a unique id for each widget handled by the Lucid Widget
2739 For the main windows, and popup menus, we use this counter,
2740 which we increment each time after use. This starts from 1<<16.
2742 For menu bars, we use numbers starting at 0, counted in
2743 next_menubar_widget_id. */
2744 LWLIB_ID widget_id_tick
;
2747 popup_selection_callback (widget
, id
, client_data
)
2750 XtPointer client_data
;
2752 menu_item_selection
= (Lisp_Object
*) client_data
;
2755 /* ARG is the LWLIB ID of the dialog box, represented
2756 as a Lisp object as (HIGHPART . LOWPART). */
2762 LWLIB_ID id
= (XINT (XCAR (arg
)) << 4 * sizeof (LWLIB_ID
)
2763 | XINT (XCDR (arg
)));
2766 lw_destroy_all_widgets (id
);
2768 popup_activated_flag
= 0;
2773 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
2775 menu_item_selection will be set to the selection. */
2777 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
)
2779 widget_value
*first_wv
;
2787 XButtonPressedEvent dummy
;
2791 if (! FRAME_X_P (f
))
2794 menu_id
= widget_id_tick
++;
2795 menu
= lw_create_widget ("popup", first_wv
->name
, menu_id
, first_wv
,
2796 f
->output_data
.x
->widget
, 1, 0,
2797 popup_selection_callback
,
2798 popup_deactivate_callback
,
2799 menu_highlight_callback
);
2801 dummy
.type
= ButtonPress
;
2803 dummy
.send_event
= 0;
2804 dummy
.display
= FRAME_X_DISPLAY (f
);
2805 dummy
.time
= CurrentTime
;
2806 dummy
.root
= FRAME_X_DISPLAY_INFO (f
)->root_window
;
2807 dummy
.window
= dummy
.root
;
2808 dummy
.subwindow
= dummy
.root
;
2812 /* Adjust coordinates to be root-window-relative. */
2813 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
2814 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
2821 for (i
= 0; i
< 5; i
++)
2822 if (FRAME_X_DISPLAY_INFO (f
)->grabbed
& (1 << i
))
2825 /* Don't allow any geometry request from the user. */
2826 XtSetArg (av
[ac
], XtNgeometry
, 0); ac
++;
2827 XtSetValues (menu
, av
, ac
);
2829 /* Display the menu. */
2830 lw_popup_menu (menu
, (XEvent
*) &dummy
);
2831 popup_activated_flag
= 1;
2832 x_activate_timeout_atimer ();
2835 int fact
= 4 * sizeof (LWLIB_ID
);
2836 int specpdl_count
= SPECPDL_INDEX ();
2837 record_unwind_protect (pop_down_menu
,
2838 Fcons (make_number (menu_id
>> (fact
)),
2839 make_number (menu_id
& ~(-1 << (fact
)))));
2841 /* Process events that apply to the menu. */
2842 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
), menu_id
, 1);
2844 unbind_to (specpdl_count
, Qnil
);
2848 #endif /* not USE_GTK */
2851 xmenu_show (f
, x
, y
, for_click
, keymaps
, title
, error
)
2861 widget_value
*wv
, *save_wv
= 0, *first_wv
= 0, *prev_wv
= 0;
2862 widget_value
**submenu_stack
2863 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
2864 Lisp_Object
*subprefix_stack
2865 = (Lisp_Object
*) alloca (menu_items_used
* sizeof (Lisp_Object
));
2866 int submenu_depth
= 0;
2870 if (! FRAME_X_P (f
))
2875 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
2877 *error
= "Empty menu";
2881 /* Create a tree of widget_value objects
2882 representing the panes and their items. */
2883 wv
= xmalloc_widget_value ();
2887 wv
->button_type
= BUTTON_TYPE_NONE
;
2892 /* Loop over all panes and items, filling in the tree. */
2894 while (i
< menu_items_used
)
2896 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
2898 submenu_stack
[submenu_depth
++] = save_wv
;
2904 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
2907 save_wv
= submenu_stack
[--submenu_depth
];
2911 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
2912 && submenu_depth
!= 0)
2913 i
+= MENU_ITEMS_PANE_LENGTH
;
2914 /* Ignore a nil in the item list.
2915 It's meaningful only for dialog boxes. */
2916 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
2918 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2920 /* Create a new pane. */
2921 Lisp_Object pane_name
, prefix
;
2924 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
2925 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
2927 #ifndef HAVE_MULTILINGUAL_MENU
2928 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
2930 pane_name
= ENCODE_MENU_STRING (pane_name
);
2931 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
2934 pane_string
= (NILP (pane_name
)
2935 ? "" : (char *) SDATA (pane_name
));
2936 /* If there is just one top-level pane, put all its items directly
2937 under the top-level menu. */
2938 if (menu_items_n_panes
== 1)
2941 /* If the pane has a meaningful name,
2942 make the pane a top-level menu item
2943 with its items as a submenu beneath it. */
2944 if (!keymaps
&& strcmp (pane_string
, ""))
2946 wv
= xmalloc_widget_value ();
2950 first_wv
->contents
= wv
;
2951 wv
->name
= pane_string
;
2952 if (keymaps
&& !NILP (prefix
))
2956 wv
->button_type
= BUTTON_TYPE_NONE
;
2961 else if (first_pane
)
2967 i
+= MENU_ITEMS_PANE_LENGTH
;
2971 /* Create a new item within current pane. */
2972 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
, help
;
2973 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
2974 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
2975 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
2976 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
2977 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
2978 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
2979 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
2981 #ifndef HAVE_MULTILINGUAL_MENU
2982 if (STRINGP (item_name
) && STRING_MULTIBYTE (item_name
))
2984 item_name
= ENCODE_MENU_STRING (item_name
);
2985 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
2988 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
2990 descrip
= ENCODE_MENU_STRING (descrip
);
2991 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
2993 #endif /* not HAVE_MULTILINGUAL_MENU */
2995 wv
= xmalloc_widget_value ();
2999 save_wv
->contents
= wv
;
3000 wv
->name
= (char *) SDATA (item_name
);
3001 if (!NILP (descrip
))
3002 wv
->key
= (char *) SDATA (descrip
);
3004 /* If this item has a null value,
3005 make the call_data null so that it won't display a box
3006 when the mouse is on it. */
3008 = (!NILP (def
) ? (void *) &XVECTOR (menu_items
)->contents
[i
] : 0);
3009 wv
->enabled
= !NILP (enable
);
3012 wv
->button_type
= BUTTON_TYPE_NONE
;
3013 else if (EQ (type
, QCtoggle
))
3014 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
3015 else if (EQ (type
, QCradio
))
3016 wv
->button_type
= BUTTON_TYPE_RADIO
;
3020 wv
->selected
= !NILP (selected
);
3022 if (! STRINGP (help
))
3029 i
+= MENU_ITEMS_ITEM_LENGTH
;
3033 /* Deal with the title, if it is non-nil. */
3036 widget_value
*wv_title
= xmalloc_widget_value ();
3037 widget_value
*wv_sep1
= xmalloc_widget_value ();
3038 widget_value
*wv_sep2
= xmalloc_widget_value ();
3040 wv_sep2
->name
= "--";
3041 wv_sep2
->next
= first_wv
->contents
;
3042 wv_sep2
->help
= Qnil
;
3044 wv_sep1
->name
= "--";
3045 wv_sep1
->next
= wv_sep2
;
3046 wv_sep1
->help
= Qnil
;
3048 #ifndef HAVE_MULTILINGUAL_MENU
3049 if (STRING_MULTIBYTE (title
))
3050 title
= ENCODE_MENU_STRING (title
);
3053 wv_title
->name
= (char *) SDATA (title
);
3054 wv_title
->enabled
= TRUE
;
3055 wv_title
->button_type
= BUTTON_TYPE_NONE
;
3056 wv_title
->next
= wv_sep1
;
3057 wv_title
->help
= Qnil
;
3058 first_wv
->contents
= wv_title
;
3061 /* No selection has been chosen yet. */
3062 menu_item_selection
= 0;
3064 /* Actually create and show the menu until popped down. */
3065 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
);
3067 /* Free the widget_value objects we used to specify the contents. */
3068 free_menubar_widget_value_tree (first_wv
);
3070 /* Find the selected item, and its pane, to return
3071 the proper value. */
3072 if (menu_item_selection
!= 0)
3074 Lisp_Object prefix
, entry
;
3076 prefix
= entry
= Qnil
;
3078 while (i
< menu_items_used
)
3080 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
3082 subprefix_stack
[submenu_depth
++] = prefix
;
3086 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
3088 prefix
= subprefix_stack
[--submenu_depth
];
3091 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
3094 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
3095 i
+= MENU_ITEMS_PANE_LENGTH
;
3097 /* Ignore a nil in the item list.
3098 It's meaningful only for dialog boxes. */
3099 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
3104 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
3105 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
3111 entry
= Fcons (entry
, Qnil
);
3113 entry
= Fcons (prefix
, entry
);
3114 for (j
= submenu_depth
- 1; j
>= 0; j
--)
3115 if (!NILP (subprefix_stack
[j
]))
3116 entry
= Fcons (subprefix_stack
[j
], entry
);
3120 i
+= MENU_ITEMS_ITEM_LENGTH
;
3124 else if (!for_click
)
3125 /* Make "Cancel" equivalent to C-g. */
3126 Fsignal (Qquit
, Qnil
);
3133 dialog_selection_callback (widget
, client_data
)
3135 gpointer client_data
;
3137 /* The EMACS_INT cast avoids a warning. There's no problem
3138 as long as pointers have enough bits to hold small integers. */
3139 if ((int) (EMACS_INT
) client_data
!= -1)
3140 menu_item_selection
= (Lisp_Object
*) client_data
;
3142 popup_activated_flag
= 0;
3145 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
3147 menu_item_selection will be set to the selection. */
3149 create_and_show_dialog (f
, first_wv
)
3151 widget_value
*first_wv
;
3155 if (! FRAME_X_P (f
))
3158 menu
= xg_create_widget ("dialog", first_wv
->name
, f
, first_wv
,
3159 G_CALLBACK (dialog_selection_callback
),
3160 G_CALLBACK (popup_deactivate_callback
),
3165 int specpdl_count
= SPECPDL_INDEX ();
3166 record_unwind_protect (pop_down_menu
, make_save_value (menu
, 0));
3168 /* Display the menu. */
3169 gtk_widget_show_all (menu
);
3171 /* Process events that apply to the menu. */
3172 popup_widget_loop (1, menu
);
3174 unbind_to (specpdl_count
, Qnil
);
3178 #else /* not USE_GTK */
3180 dialog_selection_callback (widget
, id
, client_data
)
3183 XtPointer client_data
;
3185 /* The EMACS_INT cast avoids a warning. There's no problem
3186 as long as pointers have enough bits to hold small integers. */
3187 if ((int) (EMACS_INT
) client_data
!= -1)
3188 menu_item_selection
= (Lisp_Object
*) client_data
;
3191 lw_destroy_all_widgets (id
);
3193 popup_activated_flag
= 0;
3197 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
3199 menu_item_selection will be set to the selection. */
3201 create_and_show_dialog (f
, first_wv
)
3203 widget_value
*first_wv
;
3210 dialog_id
= widget_id_tick
++;
3211 lw_create_widget (first_wv
->name
, "dialog", dialog_id
, first_wv
,
3212 f
->output_data
.x
->widget
, 1, 0,
3213 dialog_selection_callback
, 0, 0);
3214 lw_modify_all_widgets (dialog_id
, first_wv
->contents
, True
);
3216 /* Display the dialog box. */
3217 lw_pop_up_all_widgets (dialog_id
);
3218 popup_activated_flag
= 1;
3219 x_activate_timeout_atimer ();
3221 /* Process events that apply to the dialog box.
3222 Also handle timers. */
3224 int count
= SPECPDL_INDEX ();
3225 int fact
= 4 * sizeof (LWLIB_ID
);
3227 /* xdialog_show_unwind is responsible for popping the dialog box down. */
3228 record_unwind_protect (pop_down_menu
,
3229 Fcons (make_number (dialog_id
>> (fact
)),
3230 make_number (dialog_id
& ~(-1 << (fact
)))));
3232 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
),
3235 unbind_to (count
, Qnil
);
3239 #endif /* not USE_GTK */
3241 static char * button_names
[] = {
3242 "button1", "button2", "button3", "button4", "button5",
3243 "button6", "button7", "button8", "button9", "button10" };
3246 xdialog_show (f
, keymaps
, title
, header
, error_name
)
3249 Lisp_Object title
, header
;
3252 int i
, nb_buttons
=0;
3253 char dialog_name
[6];
3255 widget_value
*wv
, *first_wv
= 0, *prev_wv
= 0;
3257 /* Number of elements seen so far, before boundary. */
3259 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
3260 int boundary_seen
= 0;
3262 if (! FRAME_X_P (f
))
3267 if (menu_items_n_panes
> 1)
3269 *error_name
= "Multiple panes in dialog box";
3273 /* Create a tree of widget_value objects
3274 representing the text label and buttons. */
3276 Lisp_Object pane_name
, prefix
;
3278 pane_name
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
];
3279 prefix
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_PREFIX
];
3280 pane_string
= (NILP (pane_name
)
3281 ? "" : (char *) SDATA (pane_name
));
3282 prev_wv
= xmalloc_widget_value ();
3283 prev_wv
->value
= pane_string
;
3284 if (keymaps
&& !NILP (prefix
))
3286 prev_wv
->enabled
= 1;
3287 prev_wv
->name
= "message";
3288 prev_wv
->help
= Qnil
;
3291 /* Loop over all panes and items, filling in the tree. */
3292 i
= MENU_ITEMS_PANE_LENGTH
;
3293 while (i
< menu_items_used
)
3296 /* Create a new item within current pane. */
3297 Lisp_Object item_name
, enable
, descrip
;
3298 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
3299 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
3301 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
3303 if (NILP (item_name
))
3305 free_menubar_widget_value_tree (first_wv
);
3306 *error_name
= "Submenu in dialog items";
3309 if (EQ (item_name
, Qquote
))
3311 /* This is the boundary between left-side elts
3312 and right-side elts. Stop incrementing right_count. */
3317 if (nb_buttons
>= 9)
3319 free_menubar_widget_value_tree (first_wv
);
3320 *error_name
= "Too many dialog items";
3324 wv
= xmalloc_widget_value ();
3326 wv
->name
= (char *) button_names
[nb_buttons
];
3327 if (!NILP (descrip
))
3328 wv
->key
= (char *) SDATA (descrip
);
3329 wv
->value
= (char *) SDATA (item_name
);
3330 wv
->call_data
= (void *) &XVECTOR (menu_items
)->contents
[i
];
3331 wv
->enabled
= !NILP (enable
);
3335 if (! boundary_seen
)
3339 i
+= MENU_ITEMS_ITEM_LENGTH
;
3342 /* If the boundary was not specified,
3343 by default put half on the left and half on the right. */
3344 if (! boundary_seen
)
3345 left_count
= nb_buttons
- nb_buttons
/ 2;
3347 wv
= xmalloc_widget_value ();
3348 wv
->name
= dialog_name
;
3351 /* Frame title: 'Q' = Question, 'I' = Information.
3352 Can also have 'E' = Error if, one day, we want
3353 a popup for errors. */
3355 dialog_name
[0] = 'Q';
3357 dialog_name
[0] = 'I';
3359 /* Dialog boxes use a really stupid name encoding
3360 which specifies how many buttons to use
3361 and how many buttons are on the right. */
3362 dialog_name
[1] = '0' + nb_buttons
;
3363 dialog_name
[2] = 'B';
3364 dialog_name
[3] = 'R';
3365 /* Number of buttons to put on the right. */
3366 dialog_name
[4] = '0' + nb_buttons
- left_count
;
3368 wv
->contents
= first_wv
;
3372 /* No selection has been chosen yet. */
3373 menu_item_selection
= 0;
3375 /* Force a redisplay before showing the dialog. If a frame is created
3376 just before showing the dialog, its contents may not have been fully
3377 drawn, as this depends on timing of events from the X server. Redisplay
3378 is not done when a dialog is shown. If redisplay could be done in the
3379 X event loop (i.e. the X event loop does not run in a signal handler)
3380 this would not be needed. */
3383 /* Actually create and show the dialog. */
3384 create_and_show_dialog (f
, first_wv
);
3386 /* Free the widget_value objects we used to specify the contents. */
3387 free_menubar_widget_value_tree (first_wv
);
3389 /* Find the selected item, and its pane, to return
3390 the proper value. */
3391 if (menu_item_selection
!= 0)
3397 while (i
< menu_items_used
)
3401 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
3404 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
3405 i
+= MENU_ITEMS_PANE_LENGTH
;
3407 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
3409 /* This is the boundary between left-side elts and
3416 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
3417 if (menu_item_selection
== &XVECTOR (menu_items
)->contents
[i
])
3421 entry
= Fcons (entry
, Qnil
);
3423 entry
= Fcons (prefix
, entry
);
3427 i
+= MENU_ITEMS_ITEM_LENGTH
;
3432 /* Make "Cancel" equivalent to C-g. */
3433 Fsignal (Qquit
, Qnil
);
3438 #else /* not USE_X_TOOLKIT && not USE_GTK */
3440 /* The frame of the last activated non-toolkit menu bar.
3441 Used to generate menu help events. */
3443 static struct frame
*menu_help_frame
;
3446 /* Show help HELP_STRING, or clear help if HELP_STRING is null.
3448 PANE is the pane number, and ITEM is the menu item number in
3449 the menu (currently not used).
3451 This cannot be done with generating a HELP_EVENT because
3452 XMenuActivate contains a loop that doesn't let Emacs process
3456 menu_help_callback (help_string
, pane
, item
)
3460 extern Lisp_Object Qmenu_item
;
3461 Lisp_Object
*first_item
;
3462 Lisp_Object pane_name
;
3463 Lisp_Object menu_object
;
3465 first_item
= XVECTOR (menu_items
)->contents
;
3466 if (EQ (first_item
[0], Qt
))
3467 pane_name
= first_item
[MENU_ITEMS_PANE_NAME
];
3468 else if (EQ (first_item
[0], Qquote
))
3469 /* This shouldn't happen, see xmenu_show. */
3470 pane_name
= empty_unibyte_string
;
3472 pane_name
= first_item
[MENU_ITEMS_ITEM_NAME
];
3474 /* (menu-item MENU-NAME PANE-NUMBER) */
3475 menu_object
= Fcons (Qmenu_item
,
3477 Fcons (make_number (pane
), Qnil
)));
3478 show_help_echo (help_string
? build_string (help_string
) : Qnil
,
3479 Qnil
, menu_object
, make_number (item
), 1);
3486 struct Lisp_Save_Value
*p1
= XSAVE_VALUE (Fcar (arg
));
3487 struct Lisp_Save_Value
*p2
= XSAVE_VALUE (Fcdr (arg
));
3489 FRAME_PTR f
= p1
->pointer
;
3490 XMenu
*menu
= p2
->pointer
;
3494 XUngrabPointer (FRAME_X_DISPLAY (f
), CurrentTime
);
3495 XUngrabKeyboard (FRAME_X_DISPLAY (f
), CurrentTime
);
3497 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
3499 #ifdef HAVE_X_WINDOWS
3500 /* Assume the mouse has moved out of the X window.
3501 If it has actually moved in, we will get an EnterNotify. */
3502 x_mouse_leave (FRAME_X_DISPLAY_INFO (f
));
3504 /* State that no mouse buttons are now held.
3505 (The oldXMenu code doesn't track this info for us.)
3506 That is not necessarily true, but the fiction leads to reasonable
3507 results, and it is a pain to ask which are actually held now. */
3508 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
3510 #endif /* HAVE_X_WINDOWS */
3519 xmenu_show (f
, x
, y
, for_click
, keymaps
, title
, error
)
3529 int pane
, selidx
, lpane
, status
;
3530 Lisp_Object entry
, pane_prefix
;
3532 int ulx
, uly
, width
, height
;
3533 int dispwidth
, dispheight
;
3534 int i
, j
, lines
, maxlines
;
3537 unsigned int dummy_uint
;
3538 int specpdl_count
= SPECPDL_INDEX ();
3540 if (! FRAME_X_P (f
))
3544 if (menu_items_n_panes
== 0)
3547 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
3549 *error
= "Empty menu";
3553 /* Figure out which root window F is on. */
3554 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &root
,
3555 &dummy_int
, &dummy_int
, &dummy_uint
, &dummy_uint
,
3556 &dummy_uint
, &dummy_uint
);
3558 /* Make the menu on that window. */
3559 menu
= XMenuCreate (FRAME_X_DISPLAY (f
), root
, "emacs");
3562 *error
= "Can't create menu";
3566 /* Don't GC while we prepare and show the menu,
3567 because we give the oldxmenu library pointers to the
3568 contents of strings. */
3569 inhibit_garbage_collection ();
3571 #ifdef HAVE_X_WINDOWS
3572 /* Adjust coordinates to relative to the outer (window manager) window. */
3573 x
+= FRAME_OUTER_TO_INNER_DIFF_X (f
);
3574 y
+= FRAME_OUTER_TO_INNER_DIFF_Y (f
);
3575 #endif /* HAVE_X_WINDOWS */
3577 /* Adjust coordinates to be root-window-relative. */
3581 /* Create all the necessary panes and their items. */
3582 maxlines
= lines
= i
= 0;
3583 while (i
< menu_items_used
)
3585 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
3587 /* Create a new pane. */
3588 Lisp_Object pane_name
, prefix
;
3591 maxlines
= max (maxlines
, lines
);
3593 pane_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_NAME
];
3594 prefix
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
3595 pane_string
= (NILP (pane_name
)
3596 ? "" : (char *) SDATA (pane_name
));
3597 if (keymaps
&& !NILP (prefix
))
3600 lpane
= XMenuAddPane (FRAME_X_DISPLAY (f
), menu
, pane_string
, TRUE
);
3601 if (lpane
== XM_FAILURE
)
3603 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
3604 *error
= "Can't create pane";
3607 i
+= MENU_ITEMS_PANE_LENGTH
;
3609 /* Find the width of the widest item in this pane. */
3612 while (j
< menu_items_used
)
3615 item
= XVECTOR (menu_items
)->contents
[j
];
3623 width
= SBYTES (item
);
3624 if (width
> maxwidth
)
3627 j
+= MENU_ITEMS_ITEM_LENGTH
;
3630 /* Ignore a nil in the item list.
3631 It's meaningful only for dialog boxes. */
3632 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
3636 /* Create a new item within current pane. */
3637 Lisp_Object item_name
, enable
, descrip
, help
;
3638 unsigned char *item_data
;
3641 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
3642 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
3644 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
3645 help
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_HELP
];
3646 help_string
= STRINGP (help
) ? SDATA (help
) : NULL
;
3648 if (!NILP (descrip
))
3650 int gap
= maxwidth
- SBYTES (item_name
);
3651 /* if alloca is fast, use that to make the space,
3652 to reduce gc needs. */
3654 = (unsigned char *) alloca (maxwidth
3655 + SBYTES (descrip
) + 1);
3656 bcopy (SDATA (item_name
), item_data
,
3657 SBYTES (item_name
));
3658 for (j
= SCHARS (item_name
); j
< maxwidth
; j
++)
3660 bcopy (SDATA (descrip
), item_data
+ j
,
3662 item_data
[j
+ SBYTES (descrip
)] = 0;
3665 item_data
= SDATA (item_name
);
3667 if (XMenuAddSelection (FRAME_X_DISPLAY (f
),
3668 menu
, lpane
, 0, item_data
,
3669 !NILP (enable
), help_string
)
3672 XMenuDestroy (FRAME_X_DISPLAY (f
), menu
);
3673 *error
= "Can't add selection to menu";
3676 i
+= MENU_ITEMS_ITEM_LENGTH
;
3681 maxlines
= max (maxlines
, lines
);
3683 /* All set and ready to fly. */
3684 XMenuRecompute (FRAME_X_DISPLAY (f
), menu
);
3685 dispwidth
= DisplayWidth (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
3686 dispheight
= DisplayHeight (FRAME_X_DISPLAY (f
), FRAME_X_SCREEN_NUMBER (f
));
3687 x
= min (x
, dispwidth
);
3688 y
= min (y
, dispheight
);
3691 XMenuLocate (FRAME_X_DISPLAY (f
), menu
, 0, 0, x
, y
,
3692 &ulx
, &uly
, &width
, &height
);
3693 if (ulx
+width
> dispwidth
)
3695 x
-= (ulx
+ width
) - dispwidth
;
3696 ulx
= dispwidth
- width
;
3698 if (uly
+height
> dispheight
)
3700 y
-= (uly
+ height
) - dispheight
;
3701 uly
= dispheight
- height
;
3703 if (ulx
< 0) x
-= ulx
;
3704 if (uly
< 0) y
-= uly
;
3708 /* If position was not given by a mouse click, adjust so upper left
3709 corner of the menu as a whole ends up at given coordinates. This
3710 is what x-popup-menu says in its documentation. */
3712 y
+= 1.5*height
/(maxlines
+2);
3715 XMenuSetAEQ (menu
, TRUE
);
3716 XMenuSetFreeze (menu
, TRUE
);
3720 XMenuActivateSetWaitFunction (x_menu_wait_for_event
, FRAME_X_DISPLAY (f
));
3723 record_unwind_protect (pop_down_menu
,
3724 Fcons (make_save_value (f
, 0),
3725 make_save_value (menu
, 0)));
3727 /* Help display under X won't work because XMenuActivate contains
3728 a loop that doesn't give Emacs a chance to process it. */
3729 menu_help_frame
= f
;
3730 status
= XMenuActivate (FRAME_X_DISPLAY (f
), menu
, &pane
, &selidx
,
3731 x
, y
, ButtonReleaseMask
, &datap
,
3732 menu_help_callback
);
3738 fprintf (stderr
, "pane= %d line = %d\n", panes
, selidx
);
3741 /* Find the item number SELIDX in pane number PANE. */
3743 while (i
< menu_items_used
)
3745 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
3749 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
3751 i
+= MENU_ITEMS_PANE_LENGTH
;
3760 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
3763 entry
= Fcons (entry
, Qnil
);
3764 if (!NILP (pane_prefix
))
3765 entry
= Fcons (pane_prefix
, entry
);
3771 i
+= MENU_ITEMS_ITEM_LENGTH
;
3777 *error
= "Can't activate menu";
3782 /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
3783 the menu was invoked with a mouse event as POSITION). */
3785 Fsignal (Qquit
, Qnil
);
3790 unbind_to (specpdl_count
, Qnil
);
3795 #endif /* not USE_X_TOOLKIT */
3797 #endif /* HAVE_MENUS */
3799 /* Detect if a dialog or menu has been posted. */
3804 return popup_activated_flag
;
3807 /* The following is used by delayed window autoselection. */
3809 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p
, Smenu_or_popup_active_p
, 0, 0, 0,
3810 doc
: /* Return t if a menu or popup dialog is active. */)
3814 return (popup_activated ()) ? Qt
: Qnil
;
3817 #endif /* HAVE_MENUS */
3823 staticpro (&menu_items
);
3825 menu_items_inuse
= Qnil
;
3827 Qdebug_on_next_call
= intern ("debug-on-next-call");
3828 staticpro (&Qdebug_on_next_call
);
3830 #ifdef USE_X_TOOLKIT
3831 widget_id_tick
= (1<<16);
3832 next_menubar_widget_id
= 1;
3835 defsubr (&Sx_popup_menu
);
3836 defsubr (&Smenu_or_popup_active_p
);
3838 #if defined (USE_GTK) || defined (USE_X_TOOLKIT)
3839 defsubr (&Sx_menu_bar_open_internal
);
3840 Ffset (intern ("accelerate-menu"),
3841 intern (Sx_menu_bar_open_internal
.symbol_name
));
3845 defsubr (&Sx_popup_dialog
);
3849 /* arch-tag: 92ea573c-398e-496e-ac73-2436f7d63242
3850 (do not change this comment) */