comparison src/xmenu.c @ 88155:d7ddb3e565de

sync with trunk
author Henrik Enberg <henrik.enberg@telia.com>
date Mon, 16 Jan 2006 00:03:54 +0000
parents 05ebf4266798
children
comparison
equal deleted inserted replaced
88154:8ce476d3ba36 88155:d7ddb3e565de
1 /* X Communication module for terminals which understand the X protocol. 1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1986, 88, 93, 94, 96, 99, 2000, 2001 2 Copyright (C) 1986, 1988, 1993, 1994, 1996, 1999, 2000, 2001, 2002, 2003,
3 Free Software Foundation, Inc. 3 2004, 2005 Free Software Foundation, Inc.
4 4
5 This file is part of GNU Emacs. 5 This file is part of GNU Emacs.
6 6
7 GNU Emacs is free software; you can redistribute it and/or modify 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 8 it under the terms of the GNU General Public License as published by
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details. 15 GNU General Public License for more details.
16 16
17 You should have received a copy of the GNU General Public License 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 18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02111-1307, USA. */ 20 Boston, MA 02110-1301, USA. */
21 21
22 /* X pop-up deck-of-cards menu facility for GNU Emacs. 22 /* X pop-up deck-of-cards menu facility for GNU Emacs.
23 * 23 *
24 * Written by Jon Arnold and Roman Budzianowski 24 * Written by Jon Arnold and Roman Budzianowski
25 * Mods and rewrite by Robert Krawitz 25 * Mods and rewrite by Robert Krawitz
31 31
32 /* Rewritten for clarity and GC protection by rms in Feb 94. */ 32 /* Rewritten for clarity and GC protection by rms in Feb 94. */
33 33
34 #include <config.h> 34 #include <config.h>
35 35
36 #if 0 /* Why was this included? And without syssignal.h? */
36 /* On 4.3 this loses if it comes after xterm.h. */ 37 /* On 4.3 this loses if it comes after xterm.h. */
37 #include <signal.h> 38 #include <signal.h>
39 #endif
38 40
39 #include <stdio.h> 41 #include <stdio.h>
40 42
41 #include "lisp.h" 43 #include "lisp.h"
42 #include "termhooks.h" 44 #include "termhooks.h"
46 #include "window.h" 48 #include "window.h"
47 #include "blockinput.h" 49 #include "blockinput.h"
48 #include "buffer.h" 50 #include "buffer.h"
49 #include "charset.h" 51 #include "charset.h"
50 #include "coding.h" 52 #include "coding.h"
53 #include "sysselect.h"
51 54
52 #ifdef MSDOS 55 #ifdef MSDOS
53 #include "msdos.h" 56 #include "msdos.h"
54 #endif 57 #endif
55 58
66 #endif 69 #endif
67 70
68 #include "dispextern.h" 71 #include "dispextern.h"
69 72
70 #ifdef HAVE_X_WINDOWS 73 #ifdef HAVE_X_WINDOWS
74 /* Defining HAVE_MULTILINGUAL_MENU would mean that the toolkit menu
75 code accepts the Emacs internal encoding. */
71 #undef HAVE_MULTILINGUAL_MENU 76 #undef HAVE_MULTILINGUAL_MENU
72 #ifdef USE_X_TOOLKIT 77 #ifdef USE_X_TOOLKIT
73 #include "widget.h" 78 #include "widget.h"
74 #include <X11/Xlib.h> 79 #include <X11/Xlib.h>
75 #include <X11/IntrinsicP.h> 80 #include <X11/IntrinsicP.h>
95 Lisp_Object Vmenu_updating_frame; 100 Lisp_Object Vmenu_updating_frame;
96 101
97 Lisp_Object Qdebug_on_next_call; 102 Lisp_Object Qdebug_on_next_call;
98 103
99 extern Lisp_Object Qmenu_bar; 104 extern Lisp_Object Qmenu_bar;
100 extern Lisp_Object Qmouse_click, Qevent_kind;
101 105
102 extern Lisp_Object QCtoggle, QCradio; 106 extern Lisp_Object QCtoggle, QCradio;
103 107
104 extern Lisp_Object Voverriding_local_map; 108 extern Lisp_Object Voverriding_local_map;
105 extern Lisp_Object Voverriding_local_map_menu_flag; 109 extern Lisp_Object Voverriding_local_map_menu_flag;
107 extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; 111 extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
108 112
109 extern Lisp_Object Qmenu_bar_update_hook; 113 extern Lisp_Object Qmenu_bar_update_hook;
110 114
111 #ifdef USE_X_TOOLKIT 115 #ifdef USE_X_TOOLKIT
112 extern void set_frame_menubar (); 116 extern void set_frame_menubar P_ ((FRAME_PTR, int, int));
113 extern XtAppContext Xt_app_con; 117 extern XtAppContext Xt_app_con;
114 118
115 static Lisp_Object xdialog_show (); 119 static Lisp_Object xdialog_show P_ ((FRAME_PTR, int, Lisp_Object, Lisp_Object,
116 static void popup_get_selection (); 120 char **));
121 static void popup_get_selection P_ ((XEvent *, struct x_display_info *,
122 LWLIB_ID, int));
117 123
118 /* Define HAVE_BOXES if menus can handle radio and toggle buttons. */ 124 /* Define HAVE_BOXES if menus can handle radio and toggle buttons. */
119 125
120 #define HAVE_BOXES 1 126 #define HAVE_BOXES 1
121 #endif /* USE_X_TOOLKIT */ 127 #endif /* USE_X_TOOLKIT */
122 128
123 #ifdef USE_GTK 129 #ifdef USE_GTK
124 #include "gtkutil.h" 130 #include "gtkutil.h"
125 #define HAVE_BOXES 1 131 #define HAVE_BOXES 1
126 extern void set_frame_menubar (); 132 extern void set_frame_menubar P_ ((FRAME_PTR, int, int));
127 static Lisp_Object xdialog_show (); 133 static Lisp_Object xdialog_show P_ ((FRAME_PTR, int, Lisp_Object, Lisp_Object,
134 char **));
135 #endif
136
137 /* This is how to deal with multibyte text if HAVE_MULTILINGUAL_MENU
138 isn't defined. The use of HAVE_MULTILINGUAL_MENU could probably be
139 confined to an extended version of this with sections of code below
140 using it unconditionally. */
141 #ifdef USE_GTK
142 /* gtk just uses utf-8. */
143 # define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str)
144 #elif defined HAVE_X_I18N
145 # define ENCODE_MENU_STRING(str) ENCODE_SYSTEM (str)
146 #else
147 # define ENCODE_MENU_STRING(str) string_make_unibyte (str)
128 #endif 148 #endif
129 149
130 static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, 150 static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
131 Lisp_Object, Lisp_Object, Lisp_Object, 151 Lisp_Object, Lisp_Object, Lisp_Object,
132 Lisp_Object, Lisp_Object)); 152 Lisp_Object, Lisp_Object));
134 static Lisp_Object xmenu_show P_ ((struct frame *, int, int, int, int, 154 static Lisp_Object xmenu_show P_ ((struct frame *, int, int, int, int,
135 Lisp_Object, char **)); 155 Lisp_Object, char **));
136 static void keymap_panes P_ ((Lisp_Object *, int, int)); 156 static void keymap_panes P_ ((Lisp_Object *, int, int));
137 static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object, 157 static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
138 int, int)); 158 int, int));
139 static void single_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object *,
140 int, int, int *));
141 static void list_of_panes P_ ((Lisp_Object)); 159 static void list_of_panes P_ ((Lisp_Object));
142 static void list_of_items P_ ((Lisp_Object)); 160 static void list_of_items P_ ((Lisp_Object));
143 161
144 extern EMACS_TIME timer_check P_ ((int));
145 162
146 /* This holds a Lisp vector that holds the results of decoding 163 /* This holds a Lisp vector that holds the results of decoding
147 the keymaps or alist-of-alists that specify a menu. 164 the keymaps or alist-of-alists that specify a menu.
148 165
149 It describes the panes and items within the panes. 166 It describes the panes and items within the panes.
270 { 287 {
271 } 288 }
272 289
273 static Lisp_Object 290 static Lisp_Object
274 unuse_menu_items (dummy) 291 unuse_menu_items (dummy)
275 int dummy; 292 Lisp_Object dummy;
276 { 293 {
277 return menu_items_inuse = Qnil; 294 return menu_items_inuse = Qnil;
278 } 295 }
279 296
280 /* Call when finished using the data for the current menu 297 /* Call when finished using the data for the current menu
408 Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10); 425 Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10);
409 426
410 finish_menu_items (); 427 finish_menu_items ();
411 } 428 }
412 429
430 /* Args passed between single_keymap_panes and single_menu_item. */
431 struct skp
432 {
433 Lisp_Object pending_maps;
434 int maxdepth, notreal;
435 int notbuttons;
436 };
437
438 static void single_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
439 void *));
440
413 /* This is a recursive subroutine of keymap_panes. 441 /* This is a recursive subroutine of keymap_panes.
414 It handles one keymap, KEYMAP. 442 It handles one keymap, KEYMAP.
415 The other arguments are passed along 443 The other arguments are passed along
416 or point to local variables of the previous function. 444 or point to local variables of the previous function.
417 If NOTREAL is nonzero, only check for equivalent key bindings, don't 445 If NOTREAL is nonzero, only check for equivalent key bindings, don't
425 Lisp_Object pane_name; 453 Lisp_Object pane_name;
426 Lisp_Object prefix; 454 Lisp_Object prefix;
427 int notreal; 455 int notreal;
428 int maxdepth; 456 int maxdepth;
429 { 457 {
430 Lisp_Object pending_maps = Qnil; 458 struct skp skp;
431 Lisp_Object tail, item; 459 struct gcpro gcpro1;
432 struct gcpro gcpro1, gcpro2; 460
433 int notbuttons = 0; 461 skp.pending_maps = Qnil;
462 skp.maxdepth = maxdepth;
463 skp.notreal = notreal;
464 skp.notbuttons = 0;
434 465
435 if (maxdepth <= 0) 466 if (maxdepth <= 0)
436 return; 467 return;
437 468
438 push_menu_pane (pane_name, prefix); 469 push_menu_pane (pane_name, prefix);
440 #ifndef HAVE_BOXES 471 #ifndef HAVE_BOXES
441 /* Remember index for first item in this pane so we can go back and 472 /* Remember index for first item in this pane so we can go back and
442 add a prefix when (if) we see the first button. After that, notbuttons 473 add a prefix when (if) we see the first button. After that, notbuttons
443 is set to 0, to mark that we have seen a button and all non button 474 is set to 0, to mark that we have seen a button and all non button
444 items need a prefix. */ 475 items need a prefix. */
445 notbuttons = menu_items_used; 476 skp.notbuttons = menu_items_used;
446 #endif 477 #endif
447 478
448 for (tail = keymap; CONSP (tail); tail = XCDR (tail)) 479 GCPRO1 (skp.pending_maps);
449 { 480 map_keymap (keymap, single_menu_item, Qnil, &skp, 1);
450 GCPRO2 (keymap, pending_maps); 481 UNGCPRO;
451 /* Look at each key binding, and if it is a menu item add it
452 to this menu. */
453 item = XCAR (tail);
454 if (CONSP (item))
455 single_menu_item (XCAR (item), XCDR (item),
456 &pending_maps, notreal, maxdepth, &notbuttons);
457 else if (VECTORP (item))
458 {
459 /* Loop over the char values represented in the vector. */
460 int len = XVECTOR (item)->size;
461 int c;
462 for (c = 0; c < len; c++)
463 {
464 Lisp_Object character;
465 XSETFASTINT (character, c);
466 single_menu_item (character, XVECTOR (item)->contents[c],
467 &pending_maps, notreal, maxdepth, &notbuttons);
468 }
469 }
470 UNGCPRO;
471 }
472 482
473 /* Process now any submenus which want to be panes at this level. */ 483 /* Process now any submenus which want to be panes at this level. */
474 while (!NILP (pending_maps)) 484 while (CONSP (skp.pending_maps))
475 { 485 {
476 Lisp_Object elt, eltcdr, string; 486 Lisp_Object elt, eltcdr, string;
477 elt = Fcar (pending_maps); 487 elt = XCAR (skp.pending_maps);
478 eltcdr = XCDR (elt); 488 eltcdr = XCDR (elt);
479 string = XCAR (eltcdr); 489 string = XCAR (eltcdr);
480 /* We no longer discard the @ from the beginning of the string here. 490 /* We no longer discard the @ from the beginning of the string here.
481 Instead, we do this in xmenu_show. */ 491 Instead, we do this in xmenu_show. */
482 single_keymap_panes (Fcar (elt), string, 492 single_keymap_panes (Fcar (elt), string,
483 XCDR (eltcdr), notreal, maxdepth - 1); 493 XCDR (eltcdr), notreal, maxdepth - 1);
484 pending_maps = Fcdr (pending_maps); 494 skp.pending_maps = XCDR (skp.pending_maps);
485 } 495 }
486 } 496 }
487 497
488 /* This is a subroutine of single_keymap_panes that handles one 498 /* This is a subroutine of single_keymap_panes that handles one
489 keymap entry. 499 keymap entry.
490 KEY is a key in a keymap and ITEM is its binding. 500 KEY is a key in a keymap and ITEM is its binding.
491 PENDING_MAPS_PTR points to a list of keymaps waiting to be made into 501 SKP->PENDING_MAPS_PTR is a list of keymaps waiting to be made into
492 separate panes. 502 separate panes.
493 If NOTREAL is nonzero, only check for equivalent key bindings, don't 503 If SKP->NOTREAL is nonzero, only check for equivalent key bindings, don't
494 evaluate expressions in menu items and don't make any menu. 504 evaluate expressions in menu items and don't make any menu.
495 If we encounter submenus deeper than MAXDEPTH levels, ignore them. 505 If we encounter submenus deeper than SKP->MAXDEPTH levels, ignore them.
496 NOTBUTTONS_PTR is only used when simulating toggle boxes and radio 506 SKP->NOTBUTTONS is only used when simulating toggle boxes and radio
497 buttons. It points to variable notbuttons in single_keymap_panes, 507 buttons. It keeps track of if we have seen a button in this menu or
498 which keeps track of if we have seen a button in this menu or not. */ 508 not. */
499 509
500 static void 510 static void
501 single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth, 511 single_menu_item (key, item, dummy, skp_v)
502 notbuttons_ptr) 512 Lisp_Object key, item, dummy;
503 Lisp_Object key, item; 513 void *skp_v;
504 Lisp_Object *pending_maps_ptr;
505 int maxdepth, notreal;
506 int *notbuttons_ptr;
507 { 514 {
508 Lisp_Object map, item_string, enabled; 515 Lisp_Object map, item_string, enabled;
509 struct gcpro gcpro1, gcpro2; 516 struct gcpro gcpro1, gcpro2;
510 int res; 517 int res;
518 struct skp *skp = skp_v;
511 519
512 /* Parse the menu item and leave the result in item_properties. */ 520 /* Parse the menu item and leave the result in item_properties. */
513 GCPRO2 (key, item); 521 GCPRO2 (key, item);
514 res = parse_menu_item (item, notreal, 0); 522 res = parse_menu_item (item, skp->notreal, 0);
515 UNGCPRO; 523 UNGCPRO;
516 if (!res) 524 if (!res)
517 return; /* Not a menu item. */ 525 return; /* Not a menu item. */
518 526
519 map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP]; 527 map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];
520 528
521 if (notreal) 529 if (skp->notreal)
522 { 530 {
523 /* We don't want to make a menu, just traverse the keymaps to 531 /* We don't want to make a menu, just traverse the keymaps to
524 precompute equivalent key bindings. */ 532 precompute equivalent key bindings. */
525 if (!NILP (map)) 533 if (!NILP (map))
526 single_keymap_panes (map, Qnil, key, 1, maxdepth - 1); 534 single_keymap_panes (map, Qnil, key, 1, skp->maxdepth - 1);
527 return; 535 return;
528 } 536 }
529 537
530 enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE]; 538 enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE];
531 item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME]; 539 item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];
532 540
533 if (!NILP (map) && SREF (item_string, 0) == '@') 541 if (!NILP (map) && SREF (item_string, 0) == '@')
534 { 542 {
535 if (!NILP (enabled)) 543 if (!NILP (enabled))
536 /* An enabled separate pane. Remember this to handle it later. */ 544 /* An enabled separate pane. Remember this to handle it later. */
537 *pending_maps_ptr = Fcons (Fcons (map, Fcons (item_string, key)), 545 skp->pending_maps = Fcons (Fcons (map, Fcons (item_string, key)),
538 *pending_maps_ptr); 546 skp->pending_maps);
539 return; 547 return;
540 } 548 }
541 549
542 #ifndef HAVE_BOXES 550 #ifndef HAVE_BOXES
543 /* Simulate radio buttons and toggle boxes by putting a prefix in 551 /* Simulate radio buttons and toggle boxes by putting a prefix in
548 if (!NILP (type)) 556 if (!NILP (type))
549 { 557 {
550 Lisp_Object selected 558 Lisp_Object selected
551 = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED]; 559 = XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED];
552 560
553 if (*notbuttons_ptr) 561 if (skp->notbuttons)
554 /* The first button. Line up previous items in this menu. */ 562 /* The first button. Line up previous items in this menu. */
555 { 563 {
556 int index = *notbuttons_ptr; /* Index for first item this menu. */ 564 int index = skp->notbuttons; /* Index for first item this menu. */
557 int submenu = 0; 565 int submenu = 0;
558 Lisp_Object tem; 566 Lisp_Object tem;
559 while (index < menu_items_used) 567 while (index < menu_items_used)
560 { 568 {
561 tem 569 tem
581 XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME] 589 XVECTOR (menu_items)->contents[index + MENU_ITEMS_ITEM_NAME]
582 = concat2 (build_string (" "), tem); 590 = concat2 (build_string (" "), tem);
583 index += MENU_ITEMS_ITEM_LENGTH; 591 index += MENU_ITEMS_ITEM_LENGTH;
584 } 592 }
585 } 593 }
586 *notbuttons_ptr = 0; 594 skp->notbuttons = 0;
587 } 595 }
588 596
589 /* Calculate prefix, if any, for this item. */ 597 /* Calculate prefix, if any, for this item. */
590 if (EQ (type, QCtoggle)) 598 if (EQ (type, QCtoggle))
591 prefix = build_string (NILP (selected) ? "[ ] " : "[X] "); 599 prefix = build_string (NILP (selected) ? "[ ] " : "[X] ");
592 else if (EQ (type, QCradio)) 600 else if (EQ (type, QCradio))
593 prefix = build_string (NILP (selected) ? "( ) " : "(*) "); 601 prefix = build_string (NILP (selected) ? "( ) " : "(*) ");
594 } 602 }
595 /* Not a button. If we have earlier buttons, then we need a prefix. */ 603 /* Not a button. If we have earlier buttons, then we need a prefix. */
596 else if (!*notbuttons_ptr && SREF (item_string, 0) != '\0' 604 else if (!skp->notbuttons && SREF (item_string, 0) != '\0'
597 && SREF (item_string, 0) != '-') 605 && SREF (item_string, 0) != '-')
598 prefix = build_string (" "); 606 prefix = build_string (" ");
599 607
600 if (!NILP (prefix)) 608 if (!NILP (prefix))
601 item_string = concat2 (prefix, item_string); 609 item_string = concat2 (prefix, item_string);
602 } 610 }
603 #endif /* not HAVE_BOXES */ 611 #endif /* not HAVE_BOXES */
604 612
605 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) 613 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
606 if (!NILP(map)) 614 if (!NILP (map))
607 /* Indicate visually that this is a submenu. */ 615 /* Indicate visually that this is a submenu. */
608 item_string = concat2 (item_string, build_string (" >")); 616 item_string = concat2 (item_string, build_string (" >"));
609 #endif 617 #endif
610 618
611 push_menu_item (item_string, enabled, key, 619 push_menu_item (item_string, enabled, key,
618 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) 626 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
619 /* Display a submenu using the toolkit. */ 627 /* Display a submenu using the toolkit. */
620 if (! (NILP (map) || NILP (enabled))) 628 if (! (NILP (map) || NILP (enabled)))
621 { 629 {
622 push_submenu_start (); 630 push_submenu_start ();
623 single_keymap_panes (map, Qnil, key, 0, maxdepth - 1); 631 single_keymap_panes (map, Qnil, key, 0, skp->maxdepth - 1);
624 push_submenu_end (); 632 push_submenu_end ();
625 } 633 }
626 #endif 634 #endif
627 } 635 }
628 636
636 { 644 {
637 Lisp_Object tail; 645 Lisp_Object tail;
638 646
639 init_menu_items (); 647 init_menu_items ();
640 648
641 for (tail = menu; !NILP (tail); tail = Fcdr (tail)) 649 for (tail = menu; CONSP (tail); tail = XCDR (tail))
642 { 650 {
643 Lisp_Object elt, pane_name, pane_data; 651 Lisp_Object elt, pane_name, pane_data;
644 elt = Fcar (tail); 652 elt = XCAR (tail);
645 pane_name = Fcar (elt); 653 pane_name = Fcar (elt);
646 CHECK_STRING (pane_name); 654 CHECK_STRING (pane_name);
647 push_menu_pane (pane_name, Qnil); 655 push_menu_pane (ENCODE_MENU_STRING (pane_name), Qnil);
648 pane_data = Fcdr (elt); 656 pane_data = Fcdr (elt);
649 CHECK_CONS (pane_data); 657 CHECK_CONS (pane_data);
650 list_of_items (pane_data); 658 list_of_items (pane_data);
651 } 659 }
652 660
659 list_of_items (pane) 667 list_of_items (pane)
660 Lisp_Object pane; 668 Lisp_Object pane;
661 { 669 {
662 Lisp_Object tail, item, item1; 670 Lisp_Object tail, item, item1;
663 671
664 for (tail = pane; !NILP (tail); tail = Fcdr (tail)) 672 for (tail = pane; CONSP (tail); tail = XCDR (tail))
665 { 673 {
666 item = Fcar (tail); 674 item = XCAR (tail);
667 if (STRINGP (item)) 675 if (STRINGP (item))
668 push_menu_item (item, Qnil, Qnil, Qt, Qnil, Qnil, Qnil, Qnil); 676 push_menu_item (ENCODE_MENU_STRING (item), Qnil, Qnil, Qt,
669 else if (NILP (item)) 677 Qnil, Qnil, Qnil, Qnil);
678 else if (CONSP (item))
679 {
680 item1 = XCAR (item);
681 CHECK_STRING (item1);
682 push_menu_item (ENCODE_MENU_STRING (item1), Qt, XCDR (item),
683 Qt, Qnil, Qnil, Qnil, Qnil);
684 }
685 else
670 push_left_right_boundary (); 686 push_left_right_boundary ();
671 else 687
672 {
673 CHECK_CONS (item);
674 item1 = Fcar (item);
675 CHECK_STRING (item1);
676 push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil, Qnil, Qnil, Qnil);
677 }
678 } 688 }
679 } 689 }
680 690
681 #ifdef HAVE_X_WINDOWS 691 #ifdef HAVE_X_WINDOWS
682 /* Return the mouse position in *X and *Y. The coordinates are window 692 /* Return the mouse position in *X and *Y. The coordinates are window
685 be used for X, as it returns window relative coordinates 695 be used for X, as it returns window relative coordinates
686 for the window where the mouse is in. This could be the menu bar, 696 for the window where the mouse is in. This could be the menu bar,
687 the scroll bar or the edit window. Fx_popup_menu needs to be 697 the scroll bar or the edit window. Fx_popup_menu needs to be
688 sure it is the edit window. */ 698 sure it is the edit window. */
689 static void 699 static void
690 mouse_position_for_popup(f, x, y) 700 mouse_position_for_popup (f, x, y)
691 FRAME_PTR f; 701 FRAME_PTR f;
692 int *x; 702 int *x;
693 int *y; 703 int *y;
694 { 704 {
695 Window root, dummy_window; 705 Window root, dummy_window;
718 728
719 UNBLOCK_INPUT; 729 UNBLOCK_INPUT;
720 730
721 /* xmenu_show expects window coordinates, not root window 731 /* xmenu_show expects window coordinates, not root window
722 coordinates. Translate. */ 732 coordinates. Translate. */
723 *x -= f->output_data.x->left_pos 733 *x -= f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
724 + FRAME_OUTER_TO_INNER_DIFF_X (f); 734 *y -= f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
725 *y -= f->output_data.x->top_pos
726 + FRAME_OUTER_TO_INNER_DIFF_Y (f);
727 } 735 }
728 736
729 #endif /* HAVE_X_WINDOWS */ 737 #endif /* HAVE_X_WINDOWS */
730 738
731 DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0, 739 DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
732 doc: /* Pop up a deck-of-cards menu and return user's selection. 740 doc: /* Pop up a deck-of-cards menu and return user's selection.
733 POSITION is a position specification. This is either a mouse button event 741 POSITION is a position specification. This is either a mouse button event
734 or a list ((XOFFSET YOFFSET) WINDOW) 742 or a list ((XOFFSET YOFFSET) WINDOW)
735 where XOFFSET and YOFFSET are positions in pixels from the top left 743 where XOFFSET and YOFFSET are positions in pixels from the top left
736 corner of WINDOW's frame. (WINDOW may be a frame object instead of a window.) 744 corner of WINDOW. (WINDOW may be a window or a frame object.)
737 This controls the position of the center of the first line 745 This controls the position of the top left of the menu as a whole.
738 in the first pane of the menu, not the top left of the menu as a whole.
739 If POSITION is t, it means to use the current mouse position. 746 If POSITION is t, it means to use the current mouse position.
740 747
741 MENU is a specifier for a menu. For the simplest case, MENU is a keymap. 748 MENU is a specifier for a menu. For the simplest case, MENU is a keymap.
742 The menu items come from key bindings that have a menu string as well as 749 The menu items come from key bindings that have a menu string as well as
743 a definition; actually, the "definition" in such a key binding looks like 750 a definition; actually, the "definition" in such a key binding looks like
747 If REAL-DEFINITION is nil, that puts a nonselectable string in the menu. 754 If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.
748 Otherwise, REAL-DEFINITION should be a valid key binding definition. 755 Otherwise, REAL-DEFINITION should be a valid key binding definition.
749 756
750 You can also use a list of keymaps as MENU. 757 You can also use a list of keymaps as MENU.
751 Then each keymap makes a separate pane. 758 Then each keymap makes a separate pane.
752 When MENU is a keymap or a list of keymaps, the return value 759
753 is a list of events. 760 When MENU is a keymap or a list of keymaps, the return value is the
761 list of events corresponding to the user's choice. Note that
762 `x-popup-menu' does not actually execute the command bound to that
763 sequence of events.
754 764
755 Alternatively, you can specify a menu of multiple panes 765 Alternatively, you can specify a menu of multiple panes
756 with a list of the form (TITLE PANE1 PANE2...), 766 with a list of the form (TITLE PANE1 PANE2...),
757 where each pane is a list of form (TITLE ITEM1 ITEM2...). 767 where each pane is a list of form (TITLE ITEM1 ITEM2...).
758 Each ITEM is normally a cons cell (STRING . VALUE); 768 Each ITEM is normally a cons cell (STRING . VALUE);
759 but a string can appear as an item--that makes a nonselectable line 769 but a string can appear as an item--that makes a nonselectable line
760 in the menu. 770 in the menu.
761 With this form of menu, the return value is VALUE from the chosen item. 771 With this form of menu, the return value is VALUE from the chosen item.
762 772
763 If POSITION is nil, don't display the menu at all, just precalculate the 773 If POSITION is nil, don't display the menu at all, just precalculate the
764 cached information about equivalent key sequences. */) 774 cached information about equivalent key sequences.
775
776 If the user gets rid of the menu without making a valid choice, for
777 instance by clicking the mouse away from a valid choice or by typing
778 keyboard input, then this normally results in a quit and
779 `x-popup-menu' does not return. But if POSITION is a mouse button
780 event (indicating that the user invoked the menu with the mouse) then
781 no quit occurs and `x-popup-menu' returns nil. */)
765 (position, menu) 782 (position, menu)
766 Lisp_Object position, menu; 783 Lisp_Object position, menu;
767 { 784 {
768 Lisp_Object keymap, tem; 785 Lisp_Object keymap, tem;
769 int xpos = 0, ypos = 0; 786 int xpos = 0, ypos = 0;
770 Lisp_Object title; 787 Lisp_Object title;
771 char *error_name; 788 char *error_name = NULL;
772 Lisp_Object selection; 789 Lisp_Object selection;
773 FRAME_PTR f = NULL; 790 FRAME_PTR f = NULL;
774 Lisp_Object x, y, window; 791 Lisp_Object x, y, window;
775 int keymaps = 0; 792 int keymaps = 0;
776 int for_click = 0; 793 int for_click = 0;
794 { 811 {
795 tem = Fcar (position); 812 tem = Fcar (position);
796 if (CONSP (tem)) 813 if (CONSP (tem))
797 { 814 {
798 window = Fcar (Fcdr (position)); 815 window = Fcar (Fcdr (position));
799 x = Fcar (tem); 816 x = XCAR (tem);
800 y = Fcar (Fcdr (tem)); 817 y = Fcar (XCDR (tem));
801 } 818 }
802 else 819 else
803 { 820 {
804 for_click = 1; 821 for_click = 1;
805 tem = Fcar (Fcdr (position)); /* EVENT_START (position) */ 822 tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
870 else if (WINDOWP (window)) 887 else if (WINDOWP (window))
871 { 888 {
872 CHECK_LIVE_WINDOW (window); 889 CHECK_LIVE_WINDOW (window);
873 f = XFRAME (WINDOW_FRAME (XWINDOW (window))); 890 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
874 891
875 xpos = (FONT_WIDTH (FRAME_FONT (f)) 892 xpos = WINDOW_LEFT_EDGE_X (XWINDOW (window));
876 * XFASTINT (XWINDOW (window)->left)); 893 ypos = WINDOW_TOP_EDGE_Y (XWINDOW (window));
877 ypos = (FRAME_LINE_HEIGHT (f)
878 * XFASTINT (XWINDOW (window)->top));
879 } 894 }
880 else 895 else
881 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME, 896 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
882 but I don't want to make one now. */ 897 but I don't want to make one now. */
883 CHECK_WINDOW (window); 898 CHECK_WINDOW (window);
884 899
885 xpos += XINT (x); 900 xpos += XINT (x);
886 ypos += XINT (y); 901 ypos += XINT (y);
887 } 902
888 Vmenu_updating_frame = Qnil; 903 XSETFRAME (Vmenu_updating_frame, f);
904 }
905 else
906 Vmenu_updating_frame = Qnil;
889 #endif /* HAVE_MENUS */ 907 #endif /* HAVE_MENUS */
890 908
891 record_unwind_protect (unuse_menu_items, Qnil); 909 record_unwind_protect (unuse_menu_items, Qnil);
892 title = Qnil; 910 title = Qnil;
893 GCPRO1 (title); 911 GCPRO1 (title);
925 943
926 title = Qnil; 944 title = Qnil;
927 945
928 /* The first keymap that has a prompt string 946 /* The first keymap that has a prompt string
929 supplies the menu title. */ 947 supplies the menu title. */
930 for (tem = menu, i = 0; CONSP (tem); tem = Fcdr (tem)) 948 for (tem = menu, i = 0; CONSP (tem); tem = XCDR (tem))
931 { 949 {
932 Lisp_Object prompt; 950 Lisp_Object prompt;
933 951
934 maps[i++] = keymap = get_keymap (Fcar (tem), 1, 0); 952 maps[i++] = keymap = get_keymap (XCAR (tem), 1, 0);
935 953
936 prompt = Fkeymap_prompt (keymap); 954 prompt = Fkeymap_prompt (keymap);
937 if (NILP (title) && !NILP (prompt)) 955 if (NILP (title) && !NILP (prompt))
938 title = prompt; 956 title = prompt;
939 } 957 }
984 return selection; 1002 return selection;
985 } 1003 }
986 1004
987 #ifdef HAVE_MENUS 1005 #ifdef HAVE_MENUS
988 1006
989 DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 2, 0, 1007 DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
990 doc: /* Pop up a dialog box and return user's selection. 1008 doc: /* Pop up a dialog box and return user's selection.
991 POSITION specifies which frame to use. 1009 POSITION specifies which frame to use.
992 This is normally a mouse button event or a window or frame. 1010 This is normally a mouse button event or a window or frame.
993 If POSITION is t, it means to use the frame the mouse is on. 1011 If POSITION is t, it means to use the frame the mouse is on.
994 The dialog box appears in the middle of the specified frame. 1012 The dialog box appears in the middle of the specified frame.
995 1013
996 CONTENTS specifies the alternatives to display in the dialog box. 1014 CONTENTS specifies the alternatives to display in the dialog box.
997 It is a list of the form (TITLE ITEM1 ITEM2...). 1015 It is a list of the form (DIALOG ITEM1 ITEM2...).
998 Each ITEM is a cons cell (STRING . VALUE). 1016 Each ITEM is a cons cell (STRING . VALUE).
999 The return value is VALUE from the chosen item. 1017 The return value is VALUE from the chosen item.
1000 1018
1001 An ITEM may also be just a string--that makes a nonselectable item. 1019 An ITEM may also be just a string--that makes a nonselectable item.
1002 An ITEM may also be nil--that means to put all preceding items 1020 An ITEM may also be nil--that means to put all preceding items
1003 on the left of the dialog box and all following items on the right. 1021 on the left of the dialog box and all following items on the right.
1004 \(By default, approximately half appear on each side.) */) 1022 \(By default, approximately half appear on each side.)
1005 (position, contents) 1023
1006 Lisp_Object position, contents; 1024 If HEADER is non-nil, the frame title for the box is "Information",
1025 otherwise it is "Question".
1026
1027 If the user gets rid of the dialog box without making a valid choice,
1028 for instance using the window manager, then this produces a quit and
1029 `x-popup-dialog' does not return. */)
1030 (position, contents, header)
1031 Lisp_Object position, contents, header;
1007 { 1032 {
1008 FRAME_PTR f = NULL; 1033 FRAME_PTR f = NULL;
1009 Lisp_Object window; 1034 Lisp_Object window;
1010 1035
1011 check_x (); 1036 check_x ();
1086 /* Decode the dialog items from what was specified. */ 1111 /* Decode the dialog items from what was specified. */
1087 title = Fcar (contents); 1112 title = Fcar (contents);
1088 CHECK_STRING (title); 1113 CHECK_STRING (title);
1089 record_unwind_protect (unuse_menu_items, Qnil); 1114 record_unwind_protect (unuse_menu_items, Qnil);
1090 1115
1116 if (NILP (Fcar (Fcdr (contents))))
1117 /* No buttons specified, add an "Ok" button so users can pop down
1118 the dialog. Also, the lesstif/motif version crashes if there are
1119 no buttons. */
1120 contents = Fcons (title, Fcons (Fcons (build_string ("Ok"), Qt), Qnil));
1121
1091 list_of_panes (Fcons (contents, Qnil)); 1122 list_of_panes (Fcons (contents, Qnil));
1092 1123
1093 /* Display them in a dialog box. */ 1124 /* Display them in a dialog box. */
1094 BLOCK_INPUT; 1125 BLOCK_INPUT;
1095 selection = xdialog_show (f, 0, title, &error_name); 1126 selection = xdialog_show (f, 0, title, header, &error_name);
1096 UNBLOCK_INPUT; 1127 UNBLOCK_INPUT;
1097 1128
1098 unbind_to (specpdl_count, Qnil); 1129 unbind_to (specpdl_count, Qnil);
1099 discard_menu_items (); 1130 discard_menu_items ();
1100 1131
1101 if (error_name) error (error_name); 1132 if (error_name) error (error_name);
1102 return selection; 1133 return selection;
1103 } 1134 }
1104 #endif 1135 #endif
1105 } 1136 }
1137
1138
1139 #ifndef MSDOS
1140
1141 /* Set menu_items_inuse so no other popup menu or dialog is created. */
1142
1143 void
1144 x_menu_set_in_use (in_use)
1145 int in_use;
1146 {
1147 menu_items_inuse = in_use ? Qt : Qnil;
1148 popup_activated_flag = in_use;
1149 }
1150
1151 /* Wait for an X event to arrive or for a timer to expire. */
1152
1153 void
1154 x_menu_wait_for_event (void *data)
1155 {
1156 extern EMACS_TIME timer_check P_ ((int));
1157
1158 /* Another way to do this is to register a timer callback, that can be
1159 done in GTK and Xt. But we have to do it like this when using only X
1160 anyway, and with callbacks we would have three variants for timer handling
1161 instead of the small ifdefs below. */
1162
1163 while (
1164 #ifdef USE_X_TOOLKIT
1165 ! XtAppPending (Xt_app_con)
1166 #elif defined USE_GTK
1167 ! gtk_events_pending ()
1168 #else
1169 ! XPending ((Display*) data)
1170 #endif
1171 )
1172 {
1173 EMACS_TIME next_time = timer_check (1);
1174 long secs = EMACS_SECS (next_time);
1175 long usecs = EMACS_USECS (next_time);
1176 SELECT_TYPE read_fds;
1177 struct x_display_info *dpyinfo;
1178 int n = 0;
1179
1180 FD_ZERO (&read_fds);
1181 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
1182 {
1183 int fd = ConnectionNumber (dpyinfo->display);
1184 FD_SET (fd, &read_fds);
1185 if (fd > n) n = fd;
1186 }
1187
1188 if (secs < 0 || (secs == 0 && usecs == 0))
1189 {
1190 /* Sometimes timer_check returns -1 (no timers) even if there are
1191 timers. So do a timeout anyway. */
1192 EMACS_SET_SECS (next_time, 1);
1193 EMACS_SET_USECS (next_time, 0);
1194 }
1195
1196 select (n + 1, &read_fds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, &next_time);
1197 }
1198 }
1199 #endif /* ! MSDOS */
1200
1106 1201
1107 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) 1202 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
1203
1204 #ifdef USE_X_TOOLKIT
1108 1205
1109 /* Loop in Xt until the menu pulldown or dialog popup has been 1206 /* Loop in Xt until the menu pulldown or dialog popup has been
1110 popped down (deactivated). This is used for x-popup-menu 1207 popped down (deactivated). This is used for x-popup-menu
1111 and x-popup-dialog; it is not used for the menu bar. 1208 and x-popup-dialog; it is not used for the menu bar.
1112 1209
1113 If DO_TIMERS is nonzero, run timers.
1114
1115 NOTE: All calls to popup_get_selection should be protected 1210 NOTE: All calls to popup_get_selection should be protected
1116 with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */ 1211 with BLOCK_INPUT, UNBLOCK_INPUT wrappers. */
1117 1212
1118 #ifdef USE_X_TOOLKIT
1119 static void 1213 static void
1120 popup_get_selection (initial_event, dpyinfo, id, do_timers) 1214 popup_get_selection (initial_event, dpyinfo, id, do_timers)
1121 XEvent *initial_event; 1215 XEvent *initial_event;
1122 struct x_display_info *dpyinfo; 1216 struct x_display_info *dpyinfo;
1123 LWLIB_ID id; 1217 LWLIB_ID id;
1125 { 1219 {
1126 XEvent event; 1220 XEvent event;
1127 1221
1128 while (popup_activated_flag) 1222 while (popup_activated_flag)
1129 { 1223 {
1130 /* If we have no events to run, consider timers. */
1131 if (do_timers && !XtAppPending (Xt_app_con))
1132 timer_check (1);
1133
1134 if (initial_event) 1224 if (initial_event)
1135 { 1225 {
1136 event = *initial_event; 1226 event = *initial_event;
1137 initial_event = 0; 1227 initial_event = 0;
1138 } 1228 }
1139 else 1229 else
1140 XtAppNextEvent (Xt_app_con, &event); 1230 {
1231 if (do_timers) x_menu_wait_for_event (0);
1232 XtAppNextEvent (Xt_app_con, &event);
1233 }
1141 1234
1142 /* Make sure we don't consider buttons grabbed after menu goes. 1235 /* Make sure we don't consider buttons grabbed after menu goes.
1143 And make sure to deactivate for any ButtonRelease, 1236 And make sure to deactivate for any ButtonRelease,
1144 even if XtDispatchEvent doesn't do that. */ 1237 even if XtDispatchEvent doesn't do that. */
1145 if (event.type == ButtonRelease 1238 if (event.type == ButtonRelease
1155 key is pressed and the button is released. So reset key state 1248 key is pressed and the button is released. So reset key state
1156 so Motif thinks this is the case. */ 1249 so Motif thinks this is the case. */
1157 event.xbutton.state = 0; 1250 event.xbutton.state = 0;
1158 #endif 1251 #endif
1159 } 1252 }
1160 /* If the user presses a key, deactivate the menu. 1253 /* Pop down on C-g and Escape. */
1161 The user is likely to do that if we get wedged.
1162 This is mostly for Lucid, Motif pops down the menu on ESC. */
1163 else if (event.type == KeyPress 1254 else if (event.type == KeyPress
1164 && dpyinfo->display == event.xbutton.display) 1255 && dpyinfo->display == event.xbutton.display)
1165 { 1256 {
1166 KeySym keysym = XLookupKeysym (&event.xkey, 0); 1257 KeySym keysym = XLookupKeysym (&event.xkey, 0);
1167 if (!IsModifierKey (keysym)) 1258
1259 if ((keysym == XK_g && (event.xkey.state & ControlMask) != 0)
1260 || keysym == XK_Escape) /* Any escape, ignore modifiers. */
1168 popup_activated_flag = 0; 1261 popup_activated_flag = 0;
1169 } 1262 }
1170 1263
1171 x_dispatch_event (&event, event.xany.display); 1264 x_dispatch_event (&event, event.xany.display);
1172 } 1265 }
1175 #endif /* USE_X_TOOLKIT */ 1268 #endif /* USE_X_TOOLKIT */
1176 1269
1177 #ifdef USE_GTK 1270 #ifdef USE_GTK
1178 /* Loop util popup_activated_flag is set to zero in a callback. 1271 /* Loop util popup_activated_flag is set to zero in a callback.
1179 Used for popup menus and dialogs. */ 1272 Used for popup menus and dialogs. */
1273
1180 static void 1274 static void
1181 popup_widget_loop () 1275 popup_widget_loop (do_timers, widget)
1276 int do_timers;
1277 GtkWidget *widget;
1182 { 1278 {
1183 ++popup_activated_flag; 1279 ++popup_activated_flag;
1184 1280
1185 /* Process events in the Gtk event loop until done. */ 1281 /* Process events in the Gtk event loop until done. */
1186 while (popup_activated_flag) 1282 while (popup_activated_flag)
1187 { 1283 {
1284 if (do_timers) x_menu_wait_for_event (0);
1188 gtk_main_iteration (); 1285 gtk_main_iteration ();
1189 } 1286 }
1190 } 1287 }
1191 #endif 1288 #endif
1192 1289
1210 { 1307 {
1211 if (!f->output_data.x->saved_menu_event->type) 1308 if (!f->output_data.x->saved_menu_event->type)
1212 return; 1309 return;
1213 1310
1214 #ifdef USE_GTK 1311 #ifdef USE_GTK
1215 if (! xg_win_to_widget (f->output_data.x->saved_menu_event->xany.window)) 1312 if (! xg_win_to_widget (FRAME_X_DISPLAY (f),
1313 f->output_data.x->saved_menu_event->xany.window))
1216 return; 1314 return;
1217 #endif 1315 #endif
1218 1316
1219 set_frame_menubar (f, 0, 1); 1317 set_frame_menubar (f, 0, 1);
1220 BLOCK_INPUT; 1318 BLOCK_INPUT;
1296 XSETFRAME (frame, f); 1394 XSETFRAME (frame, f);
1297 kbd_buffer_store_help_event (frame, help); 1395 kbd_buffer_store_help_event (frame, help);
1298 } 1396 }
1299 else 1397 else
1300 { 1398 {
1399 #if 0 /* This code doesn't do anything useful. ++kfs */
1301 /* WIDGET is the popup menu. It's parent is the frame's 1400 /* WIDGET is the popup menu. It's parent is the frame's
1302 widget. See which frame that is. */ 1401 widget. See which frame that is. */
1303 xt_or_gtk_widget frame_widget = XtParent (widget); 1402 xt_or_gtk_widget frame_widget = XtParent (widget);
1304 Lisp_Object tail; 1403 Lisp_Object tail;
1305 1404
1309 if (GC_FRAMEP (frame) 1408 if (GC_FRAMEP (frame)
1310 && (f = XFRAME (frame), 1409 && (f = XFRAME (frame),
1311 FRAME_X_P (f) && f->output_data.x->widget == frame_widget)) 1410 FRAME_X_P (f) && f->output_data.x->widget == frame_widget))
1312 break; 1411 break;
1313 } 1412 }
1314 1413 #endif
1315 show_help_echo (help, Qnil, Qnil, Qnil, 1); 1414 show_help_echo (help, Qnil, Qnil, Qnil, 1);
1316 } 1415 }
1317 } 1416 }
1318 1417
1319 /* Callback called when menu items are highlighted/unhighlighted 1418 /* Callback called when menu items are highlighted/unhighlighted
1365 #endif 1464 #endif
1366 1465
1367 /* Find the menu selection and store it in the keyboard buffer. 1466 /* Find the menu selection and store it in the keyboard buffer.
1368 F is the frame the menu is on. 1467 F is the frame the menu is on.
1369 MENU_BAR_ITEMS_USED is the length of VECTOR. 1468 MENU_BAR_ITEMS_USED is the length of VECTOR.
1370 VECTOR is an array of menu events for the whole menu. 1469 VECTOR is an array of menu events for the whole menu. */
1371 */ 1470
1372 void 1471 static void
1373 find_and_call_menu_selection (f, menu_bar_items_used, vector, client_data) 1472 find_and_call_menu_selection (f, menu_bar_items_used, vector, client_data)
1374 FRAME_PTR f; 1473 FRAME_PTR f;
1375 int menu_bar_items_used; 1474 int menu_bar_items_used;
1376 Lisp_Object vector; 1475 Lisp_Object vector;
1377 void *client_data; 1476 void *client_data;
1412 if ((int) (EMACS_INT) client_data == i) 1511 if ((int) (EMACS_INT) client_data == i)
1413 { 1512 {
1414 int j; 1513 int j;
1415 struct input_event buf; 1514 struct input_event buf;
1416 Lisp_Object frame; 1515 Lisp_Object frame;
1516 EVENT_INIT (buf);
1417 1517
1418 XSETFRAME (frame, f); 1518 XSETFRAME (frame, f);
1419 buf.kind = MENU_BAR_EVENT; 1519 buf.kind = MENU_BAR_EVENT;
1420 buf.frame_or_window = frame; 1520 buf.frame_or_window = frame;
1421 buf.arg = frame; 1521 buf.arg = frame;
1472 if (xg_crazy_callback_abort) 1572 if (xg_crazy_callback_abort)
1473 return; 1573 return;
1474 1574
1475 if (! cb_data || ! cb_data->cl_data || ! cb_data->cl_data->f) 1575 if (! cb_data || ! cb_data->cl_data || ! cb_data->cl_data->f)
1476 return; 1576 return;
1577
1578 /* For a group of radio buttons, GTK calls the selection callback first
1579 for the item that was active before the selection and then for the one that
1580 is active after the selection. For C-h k this means we get the help on
1581 the deselected item and then the selected item is executed. Prevent that
1582 by ignoring the non-active item. */
1583 if (GTK_IS_RADIO_MENU_ITEM (widget)
1584 && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
1585 return;
1586
1587 /* When a menu is popped down, X generates a focus event (i.e. focus
1588 goes back to the frame below the menu). Since GTK buffers events,
1589 we force it out here before the menu selection event. Otherwise
1590 sit-for will exit at once if the focus event follows the menu selection
1591 event. */
1592
1593 BLOCK_INPUT;
1594 while (gtk_events_pending ())
1595 gtk_main_iteration ();
1596 UNBLOCK_INPUT;
1477 1597
1478 find_and_call_menu_selection (cb_data->cl_data->f, 1598 find_and_call_menu_selection (cb_data->cl_data->f,
1479 cb_data->cl_data->menu_bar_items_used, 1599 cb_data->cl_data->menu_bar_items_used,
1480 cb_data->cl_data->menu_bar_vector, 1600 cb_data->cl_data->menu_bar_vector,
1481 cb_data->call_data); 1601 cb_data->call_data);
1658 prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; 1778 prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
1659 1779
1660 #ifndef HAVE_MULTILINGUAL_MENU 1780 #ifndef HAVE_MULTILINGUAL_MENU
1661 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name)) 1781 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
1662 { 1782 {
1663 pane_name = ENCODE_SYSTEM (pane_name); 1783 pane_name = ENCODE_MENU_STRING (pane_name);
1664 AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name; 1784 AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
1665 } 1785 }
1666 #endif 1786 #endif
1667 pane_string = (NILP (pane_name) 1787 pane_string = (NILP (pane_name)
1668 ? "" : (char *) SDATA (pane_name)); 1788 ? "" : (char *) SDATA (pane_name));
1679 wv = xmalloc_widget_value (); 1799 wv = xmalloc_widget_value ();
1680 if (save_wv) 1800 if (save_wv)
1681 save_wv->next = wv; 1801 save_wv->next = wv;
1682 else 1802 else
1683 first_wv->contents = wv; 1803 first_wv->contents = wv;
1684 wv->name = pane_string; 1804 wv->lname = pane_name;
1685 /* Ignore the @ that means "separate pane". 1805 /* Set value to 1 so update_submenu_strings can handle '@' */
1686 This is a kludge, but this isn't worth more time. */ 1806 wv->value = (char *)1;
1687 if (!NILP (prefix) && wv->name[0] == '@')
1688 wv->name++;
1689 wv->value = 0;
1690 wv->enabled = 1; 1807 wv->enabled = 1;
1691 wv->button_type = BUTTON_TYPE_NONE; 1808 wv->button_type = BUTTON_TYPE_NONE;
1692 wv->help = Qnil; 1809 wv->help = Qnil;
1693 } 1810 }
1694 save_wv = wv; 1811 save_wv = wv;
1710 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); 1827 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
1711 1828
1712 #ifndef HAVE_MULTILINGUAL_MENU 1829 #ifndef HAVE_MULTILINGUAL_MENU
1713 if (STRING_MULTIBYTE (item_name)) 1830 if (STRING_MULTIBYTE (item_name))
1714 { 1831 {
1715 item_name = ENCODE_SYSTEM (item_name); 1832 item_name = ENCODE_MENU_STRING (item_name);
1716 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; 1833 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
1717 } 1834 }
1718 1835
1719 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) 1836 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
1720 { 1837 {
1721 descrip = ENCODE_SYSTEM (descrip); 1838 descrip = ENCODE_MENU_STRING (descrip);
1722 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; 1839 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
1723 } 1840 }
1724 #endif /* not HAVE_MULTILINGUAL_MENU */ 1841 #endif /* not HAVE_MULTILINGUAL_MENU */
1725 1842
1726 wv = xmalloc_widget_value (); 1843 wv = xmalloc_widget_value ();
1727 if (prev_wv) 1844 if (prev_wv)
1728 prev_wv->next = wv; 1845 prev_wv->next = wv;
1729 else 1846 else
1730 save_wv->contents = wv; 1847 save_wv->contents = wv;
1731 1848
1732 wv->name = (char *) SDATA (item_name); 1849 wv->lname = item_name;
1733 if (!NILP (descrip)) 1850 if (!NILP (descrip))
1734 wv->key = (char *) SDATA (descrip); 1851 wv->lkey = descrip;
1735 wv->value = 0; 1852 wv->value = 0;
1736 /* The EMACS_INT cast avoids a warning. There's no problem 1853 /* The EMACS_INT cast avoids a warning. There's no problem
1737 as long as pointers have enough bits to hold small integers. */ 1854 as long as pointers have enough bits to hold small integers. */
1738 wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0); 1855 wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0);
1739 wv->enabled = !NILP (enable); 1856 wv->enabled = !NILP (enable);
1768 return wv; 1885 return wv;
1769 } 1886 }
1770 1887
1771 return first_wv; 1888 return first_wv;
1772 } 1889 }
1890
1891 /* Walk through the widget_value tree starting at FIRST_WV and update
1892 the char * pointers from the corresponding lisp values.
1893 We do this after building the whole tree, since GC may happen while the
1894 tree is constructed, and small strings are relocated. So we must wait
1895 until no GC can happen before storing pointers into lisp values. */
1896 static void
1897 update_submenu_strings (first_wv)
1898 widget_value *first_wv;
1899 {
1900 widget_value *wv;
1901
1902 for (wv = first_wv; wv; wv = wv->next)
1903 {
1904 if (STRINGP (wv->lname))
1905 {
1906 wv->name = (char *) SDATA (wv->lname);
1907
1908 /* Ignore the @ that means "separate pane".
1909 This is a kludge, but this isn't worth more time. */
1910 if (wv->value == (char *)1)
1911 {
1912 if (wv->name[0] == '@')
1913 wv->name++;
1914 wv->value = 0;
1915 }
1916 }
1917
1918 if (STRINGP (wv->lkey))
1919 wv->key = (char *) SDATA (wv->lkey);
1920
1921 if (wv->contents)
1922 update_submenu_strings (wv->contents);
1923 }
1924 }
1925
1773 1926
1774 /* Recompute all the widgets of frame F, when the menu bar has been 1927 /* Recompute all the widgets of frame F, when the menu bar has been
1775 changed. Value is non-zero if widgets were updated. */ 1928 changed. Value is non-zero if widgets were updated. */
1776 1929
1777 static int 1930 static int
1788 return 0; 1941 return 0;
1789 1942
1790 BLOCK_INPUT; 1943 BLOCK_INPUT;
1791 /* Save the size of the frame because the pane widget doesn't accept 1944 /* Save the size of the frame because the pane widget doesn't accept
1792 to resize itself. So force it. */ 1945 to resize itself. So force it. */
1793 columns = f->width; 1946 columns = FRAME_COLS (f);
1794 rows = f->height; 1947 rows = FRAME_LINES (f);
1795 1948
1796 /* Do the voodoo which means "I'm changing lots of things, don't try 1949 /* Do the voodoo which means "I'm changing lots of things, don't try
1797 to refigure sizes until I'm done." */ 1950 to refigure sizes until I'm done." */
1798 lw_refigure_widget (x->column_widget, False); 1951 lw_refigure_widget (x->column_widget, False);
1799 1952
1833 #ifdef USE_X_TOOLKIT 1986 #ifdef USE_X_TOOLKIT
1834 LWLIB_ID id; 1987 LWLIB_ID id;
1835 #endif 1988 #endif
1836 Lisp_Object items; 1989 Lisp_Object items;
1837 widget_value *wv, *first_wv, *prev_wv = 0; 1990 widget_value *wv, *first_wv, *prev_wv = 0;
1838 int i, last_i; 1991 int i, last_i = 0;
1839 int *submenu_start, *submenu_end; 1992 int *submenu_start, *submenu_end;
1840 int *submenu_top_level_items, *submenu_n_panes; 1993 int *submenu_top_level_items, *submenu_n_panes;
1841 1994
1842 1995
1843 XSETFRAME (Vmenu_updating_frame, f); 1996 XSETFRAME (Vmenu_updating_frame, f);
1857 { 2010 {
1858 deep_p = 1; 2011 deep_p = 1;
1859 f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent)); 2012 f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent));
1860 f->output_data.x->saved_menu_event->type = 0; 2013 f->output_data.x->saved_menu_event->type = 0;
1861 } 2014 }
2015
2016 #ifdef USE_GTK
2017 /* If we have detached menus, we must update deep so detached menus
2018 also gets updated. */
2019 deep_p = deep_p || xg_have_tear_offs ();
2020 #endif
1862 2021
1863 if (deep_p) 2022 if (deep_p)
1864 { 2023 {
1865 /* Make a widget-value tree representing the entire menu trees. */ 2024 /* Make a widget-value tree representing the entire menu trees. */
1866 2025
1881 specbind (Qinhibit_quit, Qt); 2040 specbind (Qinhibit_quit, Qt);
1882 /* Don't let the debugger step into this code 2041 /* Don't let the debugger step into this code
1883 because it is not reentrant. */ 2042 because it is not reentrant. */
1884 specbind (Qdebug_on_next_call, Qnil); 2043 specbind (Qdebug_on_next_call, Qnil);
1885 2044
1886 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil)); 2045 record_unwind_save_match_data ();
1887 record_unwind_protect (unuse_menu_items, Qnil); 2046 record_unwind_protect (unuse_menu_items, Qnil);
1888 if (NILP (Voverriding_local_map_menu_flag)) 2047 if (NILP (Voverriding_local_map_menu_flag))
1889 { 2048 {
1890 specbind (Qoverriding_terminal_local_map, Qnil); 2049 specbind (Qoverriding_terminal_local_map, Qnil);
1891 specbind (Qoverriding_local_map, Qnil); 2050 specbind (Qoverriding_local_map, Qnil);
1994 for (i = 0; i < XVECTOR (items)->size; i += 4) 2153 for (i = 0; i < XVECTOR (items)->size; i += 4)
1995 { 2154 {
1996 Lisp_Object string; 2155 Lisp_Object string;
1997 string = XVECTOR (items)->contents[i + 1]; 2156 string = XVECTOR (items)->contents[i + 1];
1998 if (NILP (string)) 2157 if (NILP (string))
1999 break; 2158 break;
2000 wv->name = (char *) SDATA (string); 2159 wv->name = (char *) SDATA (string);
2001 wv = wv->next; 2160 update_submenu_strings (wv->contents);
2161 wv = wv->next;
2002 } 2162 }
2003 2163
2004 f->menu_bar_vector = menu_items; 2164 f->menu_bar_vector = menu_items;
2005 f->menu_bar_items_used = menu_items_used; 2165 f->menu_bar_items_used = menu_items_used;
2006 discard_menu_items (); 2166 discard_menu_items ();
2058 2218
2059 #ifdef USE_GTK 2219 #ifdef USE_GTK
2060 xg_crazy_callback_abort = 1; 2220 xg_crazy_callback_abort = 1;
2061 if (menubar_widget) 2221 if (menubar_widget)
2062 { 2222 {
2063 /* The third arg is DEEP_P, which says to consider the entire 2223 /* The fourth arg is DEEP_P, which says to consider the entire
2064 menu trees we supply, rather than just the menu bar item names. */ 2224 menu trees we supply, rather than just the menu bar item names. */
2065 xg_modify_menubar_widgets (menubar_widget, 2225 xg_modify_menubar_widgets (menubar_widget,
2066 f, 2226 f,
2067 first_wv, 2227 first_wv,
2068 deep_p, 2228 deep_p,
2097 /* Re-enable the edit widget to resize. */ 2257 /* Re-enable the edit widget to resize. */
2098 lw_allow_resizing (f->output_data.x->widget, True); 2258 lw_allow_resizing (f->output_data.x->widget, True);
2099 } 2259 }
2100 else 2260 else
2101 { 2261 {
2262 char menuOverride[] = "Ctrl<KeyPress>g: MenuGadgetEscape()";
2263 XtTranslations override = XtParseTranslationTable (menuOverride);
2264
2102 menubar_widget = lw_create_widget ("menubar", "menubar", id, first_wv, 2265 menubar_widget = lw_create_widget ("menubar", "menubar", id, first_wv,
2103 f->output_data.x->column_widget, 2266 f->output_data.x->column_widget,
2104 0, 2267 0,
2105 popup_activate_callback, 2268 popup_activate_callback,
2106 menubar_selection_callback, 2269 menubar_selection_callback,
2107 popup_deactivate_callback, 2270 popup_deactivate_callback,
2108 menu_highlight_callback); 2271 menu_highlight_callback);
2109 f->output_data.x->menubar_widget = menubar_widget; 2272 f->output_data.x->menubar_widget = menubar_widget;
2273
2274 /* Make menu pop down on C-g. */
2275 XtOverrideTranslations (menubar_widget, override);
2110 } 2276 }
2111 2277
2112 { 2278 {
2113 int menubar_size 2279 int menubar_size
2114 = (f->output_data.x->menubar_widget 2280 = (f->output_data.x->menubar_widget
2266 { 2432 {
2267 struct next_popup_x_y* data = (struct next_popup_x_y*)user_data; 2433 struct next_popup_x_y* data = (struct next_popup_x_y*)user_data;
2268 GtkRequisition req; 2434 GtkRequisition req;
2269 int disp_width = FRAME_X_DISPLAY_INFO (data->f)->width; 2435 int disp_width = FRAME_X_DISPLAY_INFO (data->f)->width;
2270 int disp_height = FRAME_X_DISPLAY_INFO (data->f)->height; 2436 int disp_height = FRAME_X_DISPLAY_INFO (data->f)->height;
2271 2437
2272 *x = data->x; 2438 *x = data->x;
2273 *y = data->y; 2439 *y = data->y;
2274 2440
2275 /* Check if there is room for the menu. If not, adjust x/y so that 2441 /* Check if there is room for the menu. If not, adjust x/y so that
2276 the menu is fully visible. */ 2442 the menu is fully visible. */
2288 { 2454 {
2289 xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data; 2455 xg_menu_item_cb_data *cb_data = (xg_menu_item_cb_data*) client_data;
2290 2456
2291 if (xg_crazy_callback_abort) return; 2457 if (xg_crazy_callback_abort) return;
2292 if (cb_data) menu_item_selection = (Lisp_Object *) cb_data->call_data; 2458 if (cb_data) menu_item_selection = (Lisp_Object *) cb_data->call_data;
2459 }
2460
2461 static Lisp_Object
2462 pop_down_menu (arg)
2463 Lisp_Object arg;
2464 {
2465 struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
2466
2467 popup_activated_flag = 0;
2468 BLOCK_INPUT;
2469 gtk_widget_destroy (GTK_WIDGET (p->pointer));
2470 UNBLOCK_INPUT;
2471 return Qnil;
2293 } 2472 }
2294 2473
2295 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the 2474 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
2296 menu pops down. 2475 menu pops down.
2297 menu_item_selection will be set to the selection. */ 2476 menu_item_selection will be set to the selection. */
2305 { 2484 {
2306 int i; 2485 int i;
2307 GtkWidget *menu; 2486 GtkWidget *menu;
2308 GtkMenuPositionFunc pos_func = 0; /* Pop up at pointer. */ 2487 GtkMenuPositionFunc pos_func = 0; /* Pop up at pointer. */
2309 struct next_popup_x_y popup_x_y; 2488 struct next_popup_x_y popup_x_y;
2489 int specpdl_count = SPECPDL_INDEX ();
2310 2490
2311 xg_crazy_callback_abort = 1; 2491 xg_crazy_callback_abort = 1;
2312 menu = xg_create_widget ("popup", first_wv->name, f, first_wv, 2492 menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
2313 G_CALLBACK (popup_selection_callback), 2493 G_CALLBACK (popup_selection_callback),
2314 G_CALLBACK (popup_deactivate_callback), 2494 G_CALLBACK (popup_deactivate_callback),
2315 G_CALLBACK (menu_highlight_callback)); 2495 G_CALLBACK (menu_highlight_callback));
2316 xg_crazy_callback_abort = 0; 2496 xg_crazy_callback_abort = 0;
2317 2497
2318 for (i = 0; i < 5; i++)
2319 if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
2320 break;
2321
2322 if (! for_click) 2498 if (! for_click)
2323 { 2499 {
2324 /* Not invoked by a click. pop up at x/y. */ 2500 /* Not invoked by a click. pop up at x/y. */
2325 pos_func = menu_position_func; 2501 pos_func = menu_position_func;
2326 2502
2327 /* Adjust coordinates to be root-window-relative. */ 2503 /* Adjust coordinates to be root-window-relative. */
2328 x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f); 2504 x += f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
2329 y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f); 2505 y += f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
2330 2506
2331 popup_x_y.x = x; 2507 popup_x_y.x = x;
2332 popup_x_y.y = y; 2508 popup_x_y.y = y;
2333 popup_x_y.f = f; 2509 popup_x_y.f = f;
2510
2511 i = 0; /* gtk_menu_popup needs this to be 0 for a non-button popup. */
2512 }
2513 else
2514 {
2515 for (i = 0; i < 5; i++)
2516 if (FRAME_X_DISPLAY_INFO (f)->grabbed & (1 << i))
2517 break;
2334 } 2518 }
2335 2519
2336 /* Display the menu. */ 2520 /* Display the menu. */
2337 gtk_widget_show_all (menu); 2521 gtk_widget_show_all (menu);
2338 gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0); 2522 gtk_menu_popup (GTK_MENU (menu), 0, 0, pos_func, &popup_x_y, i, 0);
2339 2523
2340 xg_did_tearoff = 0; 2524 record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
2341 /* Set this to one. popup_widget_loop increases it by one, so it becomes 2525
2342 two. show_help_echo uses this to detect popup menus. */ 2526 if (GTK_WIDGET_MAPPED (menu))
2343 popup_activated_flag = 1; 2527 {
2344 /* Process events that apply to the menu. */ 2528 /* Set this to one. popup_widget_loop increases it by one, so it becomes
2345 popup_widget_loop (); 2529 two. show_help_echo uses this to detect popup menus. */
2346 2530 popup_activated_flag = 1;
2347 if (xg_did_tearoff) 2531 /* Process events that apply to the menu. */
2348 xg_keep_popup (menu, xg_did_tearoff); 2532 popup_widget_loop (1, menu);
2349 else 2533 }
2350 gtk_widget_destroy (menu); 2534
2535 unbind_to (specpdl_count, Qnil);
2351 2536
2352 /* Must reset this manually because the button release event is not passed 2537 /* Must reset this manually because the button release event is not passed
2353 to Emacs event loop. */ 2538 to Emacs event loop. */
2354 FRAME_X_DISPLAY_INFO (f)->grabbed = 0; 2539 FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
2355 } 2540 }
2371 Widget widget; 2556 Widget widget;
2372 LWLIB_ID id; 2557 LWLIB_ID id;
2373 XtPointer client_data; 2558 XtPointer client_data;
2374 { 2559 {
2375 menu_item_selection = (Lisp_Object *) client_data; 2560 menu_item_selection = (Lisp_Object *) client_data;
2561 }
2562
2563 /* ARG is the LWLIB ID of the dialog box, represented
2564 as a Lisp object as (HIGHPART . LOWPART). */
2565
2566 static Lisp_Object
2567 pop_down_menu (arg)
2568 Lisp_Object arg;
2569 {
2570 LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
2571 | XINT (XCDR (arg)));
2572
2573 BLOCK_INPUT;
2574 lw_destroy_all_widgets (id);
2575 UNBLOCK_INPUT;
2576 popup_activated_flag = 0;
2577
2578 return Qnil;
2376 } 2579 }
2377 2580
2378 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the 2581 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
2379 menu pops down. 2582 menu pops down.
2380 menu_item_selection will be set to the selection. */ 2583 menu_item_selection will be set to the selection. */
2390 Arg av[2]; 2593 Arg av[2];
2391 int ac = 0; 2594 int ac = 0;
2392 XButtonPressedEvent dummy; 2595 XButtonPressedEvent dummy;
2393 LWLIB_ID menu_id; 2596 LWLIB_ID menu_id;
2394 Widget menu; 2597 Widget menu;
2395 Window child;
2396 2598
2397 menu_id = widget_id_tick++; 2599 menu_id = widget_id_tick++;
2398 menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv, 2600 menu = lw_create_widget ("popup", first_wv->name, menu_id, first_wv,
2399 f->output_data.x->widget, 1, 0, 2601 f->output_data.x->widget, 1, 0,
2400 popup_selection_callback, 2602 popup_selection_callback,
2411 dummy.subwindow = dummy.root; 2613 dummy.subwindow = dummy.root;
2412 dummy.x = x; 2614 dummy.x = x;
2413 dummy.y = y; 2615 dummy.y = y;
2414 2616
2415 /* Adjust coordinates to be root-window-relative. */ 2617 /* Adjust coordinates to be root-window-relative. */
2416 x += f->output_data.x->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f); 2618 x += f->left_pos + FRAME_OUTER_TO_INNER_DIFF_X (f);
2417 y += f->output_data.x->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f); 2619 y += f->top_pos + FRAME_OUTER_TO_INNER_DIFF_Y (f);
2418 2620
2419 dummy.x_root = x; 2621 dummy.x_root = x;
2420 dummy.y_root = y; 2622 dummy.y_root = y;
2421 2623
2422 dummy.state = 0; 2624 dummy.state = 0;
2431 2633
2432 /* Display the menu. */ 2634 /* Display the menu. */
2433 lw_popup_menu (menu, (XEvent *) &dummy); 2635 lw_popup_menu (menu, (XEvent *) &dummy);
2434 popup_activated_flag = 1; 2636 popup_activated_flag = 1;
2435 2637
2436 /* Process events that apply to the menu. */ 2638 {
2437 popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 0); 2639 int fact = 4 * sizeof (LWLIB_ID);
2438 2640 int specpdl_count = SPECPDL_INDEX ();
2439 /* fp turned off the following statement and wrote a comment 2641 record_unwind_protect (pop_down_menu,
2440 that it is unnecessary--that the menu has already disappeared. 2642 Fcons (make_number (menu_id >> (fact)),
2441 Nowadays the menu disappears ok, all right, but 2643 make_number (menu_id & ~(-1 << (fact)))));
2442 we need to delete the widgets or multiple ones will pile up. */ 2644
2443 lw_destroy_all_widgets (menu_id); 2645 /* Process events that apply to the menu. */
2646 popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), menu_id, 1);
2647
2648 unbind_to (specpdl_count, Qnil);
2649 }
2444 } 2650 }
2445 2651
2446 #endif /* not USE_GTK */ 2652 #endif /* not USE_GTK */
2447 2653
2448 static Lisp_Object 2654 static Lisp_Object
2520 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX); 2726 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
2521 2727
2522 #ifndef HAVE_MULTILINGUAL_MENU 2728 #ifndef HAVE_MULTILINGUAL_MENU
2523 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name)) 2729 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
2524 { 2730 {
2525 pane_name = ENCODE_SYSTEM (pane_name); 2731 pane_name = ENCODE_MENU_STRING (pane_name);
2526 AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name; 2732 AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
2527 } 2733 }
2528 #endif 2734 #endif
2529 pane_string = (NILP (pane_name) 2735 pane_string = (NILP (pane_name)
2530 ? "" : (char *) SDATA (pane_name)); 2736 ? "" : (char *) SDATA (pane_name));
2574 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP); 2780 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
2575 2781
2576 #ifndef HAVE_MULTILINGUAL_MENU 2782 #ifndef HAVE_MULTILINGUAL_MENU
2577 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name)) 2783 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
2578 { 2784 {
2579 item_name = ENCODE_SYSTEM (item_name); 2785 item_name = ENCODE_MENU_STRING (item_name);
2580 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; 2786 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
2581 } 2787 }
2582 2788
2583 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) 2789 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
2584 { 2790 {
2585 descrip = ENCODE_SYSTEM (descrip); 2791 descrip = ENCODE_MENU_STRING (descrip);
2586 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; 2792 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
2587 } 2793 }
2588 #endif /* not HAVE_MULTILINGUAL_MENU */ 2794 #endif /* not HAVE_MULTILINGUAL_MENU */
2589 2795
2590 wv = xmalloc_widget_value (); 2796 wv = xmalloc_widget_value ();
2640 wv_sep1->next = wv_sep2; 2846 wv_sep1->next = wv_sep2;
2641 wv_sep1->help = Qnil; 2847 wv_sep1->help = Qnil;
2642 2848
2643 #ifndef HAVE_MULTILINGUAL_MENU 2849 #ifndef HAVE_MULTILINGUAL_MENU
2644 if (STRING_MULTIBYTE (title)) 2850 if (STRING_MULTIBYTE (title))
2645 title = ENCODE_SYSTEM (title); 2851 title = ENCODE_MENU_STRING (title);
2646 #endif 2852 #endif
2647 2853
2648 wv_title->name = (char *) SDATA (title); 2854 wv_title->name = (char *) SDATA (title);
2649 wv_title->enabled = TRUE; 2855 wv_title->enabled = TRUE;
2650 wv_title->button_type = BUTTON_TYPE_NONE; 2856 wv_title->button_type = BUTTON_TYPE_NONE;
2714 } 2920 }
2715 i += MENU_ITEMS_ITEM_LENGTH; 2921 i += MENU_ITEMS_ITEM_LENGTH;
2716 } 2922 }
2717 } 2923 }
2718 } 2924 }
2925 else if (!for_click)
2926 /* Make "Cancel" equivalent to C-g. */
2927 Fsignal (Qquit, Qnil);
2719 2928
2720 return Qnil; 2929 return Qnil;
2721 } 2930 }
2722 2931
2723 #ifdef USE_GTK 2932 #ifdef USE_GTK
2749 G_CALLBACK (popup_deactivate_callback), 2958 G_CALLBACK (popup_deactivate_callback),
2750 0); 2959 0);
2751 2960
2752 if (menu) 2961 if (menu)
2753 { 2962 {
2963 int specpdl_count = SPECPDL_INDEX ();
2964 record_unwind_protect (pop_down_menu, make_save_value (menu, 0));
2965
2754 /* Display the menu. */ 2966 /* Display the menu. */
2755 gtk_widget_show_all (menu); 2967 gtk_widget_show_all (menu);
2756 2968
2757 /* Process events that apply to the menu. */ 2969 /* Process events that apply to the menu. */
2758 popup_widget_loop (); 2970 popup_widget_loop (1, menu);
2759 2971
2760 gtk_widget_destroy (menu); 2972 unbind_to (specpdl_count, Qnil);
2761 } 2973 }
2762 } 2974 }
2763 2975
2764 #else /* not USE_GTK */ 2976 #else /* not USE_GTK */
2765 static void 2977 static void
2775 2987
2776 BLOCK_INPUT; 2988 BLOCK_INPUT;
2777 lw_destroy_all_widgets (id); 2989 lw_destroy_all_widgets (id);
2778 UNBLOCK_INPUT; 2990 UNBLOCK_INPUT;
2779 popup_activated_flag = 0; 2991 popup_activated_flag = 0;
2780 }
2781
2782
2783 /* ARG is the LWLIB ID of the dialog box, represented
2784 as a Lisp object as (HIGHPART . LOWPART). */
2785
2786 Lisp_Object
2787 xdialog_show_unwind (arg)
2788 Lisp_Object arg;
2789 {
2790 LWLIB_ID id = (XINT (XCAR (arg)) << 4 * sizeof (LWLIB_ID)
2791 | XINT (XCDR (arg)));
2792 BLOCK_INPUT;
2793 lw_destroy_all_widgets (id);
2794 UNBLOCK_INPUT;
2795 popup_activated_flag = 0;
2796 return Qnil;
2797 } 2992 }
2798 2993
2799 2994
2800 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the 2995 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
2801 dialog pops down. 2996 dialog pops down.
2822 { 3017 {
2823 int count = SPECPDL_INDEX (); 3018 int count = SPECPDL_INDEX ();
2824 int fact = 4 * sizeof (LWLIB_ID); 3019 int fact = 4 * sizeof (LWLIB_ID);
2825 3020
2826 /* xdialog_show_unwind is responsible for popping the dialog box down. */ 3021 /* xdialog_show_unwind is responsible for popping the dialog box down. */
2827 record_unwind_protect (xdialog_show_unwind, 3022 record_unwind_protect (pop_down_menu,
2828 Fcons (make_number (dialog_id >> (fact)), 3023 Fcons (make_number (dialog_id >> (fact)),
2829 make_number (dialog_id & ~(-1 << (fact))))); 3024 make_number (dialog_id & ~(-1 << (fact)))));
2830 3025
2831 popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id, 1); 3026 popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f),
3027 dialog_id, 1);
2832 3028
2833 unbind_to (count, Qnil); 3029 unbind_to (count, Qnil);
2834 } 3030 }
2835 } 3031 }
2836 3032
2839 static char * button_names [] = { 3035 static char * button_names [] = {
2840 "button1", "button2", "button3", "button4", "button5", 3036 "button1", "button2", "button3", "button4", "button5",
2841 "button6", "button7", "button8", "button9", "button10" }; 3037 "button6", "button7", "button8", "button9", "button10" };
2842 3038
2843 static Lisp_Object 3039 static Lisp_Object
2844 xdialog_show (f, keymaps, title, error) 3040 xdialog_show (f, keymaps, title, header, error_name)
2845 FRAME_PTR f; 3041 FRAME_PTR f;
2846 int keymaps; 3042 int keymaps;
2847 Lisp_Object title; 3043 Lisp_Object title, header;
2848 char **error; 3044 char **error_name;
2849 { 3045 {
2850 int i, nb_buttons=0; 3046 int i, nb_buttons=0;
2851 char dialog_name[6]; 3047 char dialog_name[6];
2852 3048
2853 widget_value *wv, *first_wv = 0, *prev_wv = 0; 3049 widget_value *wv, *first_wv = 0, *prev_wv = 0;
2855 /* Number of elements seen so far, before boundary. */ 3051 /* Number of elements seen so far, before boundary. */
2856 int left_count = 0; 3052 int left_count = 0;
2857 /* 1 means we've seen the boundary between left-hand elts and right-hand. */ 3053 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
2858 int boundary_seen = 0; 3054 int boundary_seen = 0;
2859 3055
2860 *error = NULL; 3056 *error_name = NULL;
2861 3057
2862 if (menu_items_n_panes > 1) 3058 if (menu_items_n_panes > 1)
2863 { 3059 {
2864 *error = "Multiple panes in dialog box"; 3060 *error_name = "Multiple panes in dialog box";
2865 return Qnil; 3061 return Qnil;
2866 } 3062 }
2867 3063
2868 /* Create a tree of widget_value objects 3064 /* Create a tree of widget_value objects
2869 representing the text label and buttons. */ 3065 representing the text label and buttons. */
2896 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY]; 3092 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
2897 3093
2898 if (NILP (item_name)) 3094 if (NILP (item_name))
2899 { 3095 {
2900 free_menubar_widget_value_tree (first_wv); 3096 free_menubar_widget_value_tree (first_wv);
2901 *error = "Submenu in dialog items"; 3097 *error_name = "Submenu in dialog items";
2902 return Qnil; 3098 return Qnil;
2903 } 3099 }
2904 if (EQ (item_name, Qquote)) 3100 if (EQ (item_name, Qquote))
2905 { 3101 {
2906 /* This is the boundary between left-side elts 3102 /* This is the boundary between left-side elts
2910 continue; 3106 continue;
2911 } 3107 }
2912 if (nb_buttons >= 9) 3108 if (nb_buttons >= 9)
2913 { 3109 {
2914 free_menubar_widget_value_tree (first_wv); 3110 free_menubar_widget_value_tree (first_wv);
2915 *error = "Too many dialog items"; 3111 *error_name = "Too many dialog items";
2916 return Qnil; 3112 return Qnil;
2917 } 3113 }
2918 3114
2919 wv = xmalloc_widget_value (); 3115 wv = xmalloc_widget_value ();
2920 prev_wv->next = wv; 3116 prev_wv->next = wv;
2940 left_count = nb_buttons - nb_buttons / 2; 3136 left_count = nb_buttons - nb_buttons / 2;
2941 3137
2942 wv = xmalloc_widget_value (); 3138 wv = xmalloc_widget_value ();
2943 wv->name = dialog_name; 3139 wv->name = dialog_name;
2944 wv->help = Qnil; 3140 wv->help = Qnil;
3141
3142 /* Frame title: 'Q' = Question, 'I' = Information.
3143 Can also have 'E' = Error if, one day, we want
3144 a popup for errors. */
3145 if (NILP(header))
3146 dialog_name[0] = 'Q';
3147 else
3148 dialog_name[0] = 'I';
3149
2945 /* Dialog boxes use a really stupid name encoding 3150 /* Dialog boxes use a really stupid name encoding
2946 which specifies how many buttons to use 3151 which specifies how many buttons to use
2947 and how many buttons are on the right. 3152 and how many buttons are on the right. */
2948 The Q means something also. */
2949 dialog_name[0] = 'Q';
2950 dialog_name[1] = '0' + nb_buttons; 3153 dialog_name[1] = '0' + nb_buttons;
2951 dialog_name[2] = 'B'; 3154 dialog_name[2] = 'B';
2952 dialog_name[3] = 'R'; 3155 dialog_name[3] = 'R';
2953 /* Number of buttons to put on the right. */ 3156 /* Number of buttons to put on the right. */
2954 dialog_name[4] = '0' + nb_buttons - left_count; 3157 dialog_name[4] = '0' + nb_buttons - left_count;
3006 } 3209 }
3007 i += MENU_ITEMS_ITEM_LENGTH; 3210 i += MENU_ITEMS_ITEM_LENGTH;
3008 } 3211 }
3009 } 3212 }
3010 } 3213 }
3214 else
3215 /* Make "Cancel" equivalent to C-g. */
3216 Fsignal (Qquit, Qnil);
3011 3217
3012 return Qnil; 3218 return Qnil;
3013 } 3219 }
3014 3220
3015 #else /* not USE_X_TOOLKIT && not USE_GTK */ 3221 #else /* not USE_X_TOOLKIT && not USE_GTK */
3054 Fcons (make_number (pane), Qnil))); 3260 Fcons (make_number (pane), Qnil)));
3055 show_help_echo (help_string ? build_string (help_string) : Qnil, 3261 show_help_echo (help_string ? build_string (help_string) : Qnil,
3056 Qnil, menu_object, make_number (item), 1); 3262 Qnil, menu_object, make_number (item), 1);
3057 } 3263 }
3058 3264
3265 static Lisp_Object
3266 pop_down_menu (arg)
3267 Lisp_Object arg;
3268 {
3269 struct Lisp_Save_Value *p1 = XSAVE_VALUE (Fcar (arg));
3270 struct Lisp_Save_Value *p2 = XSAVE_VALUE (Fcdr (arg));
3271
3272 FRAME_PTR f = p1->pointer;
3273 XMenu *menu = p2->pointer;
3274
3275 BLOCK_INPUT;
3276 #ifndef MSDOS
3277 XUngrabPointer (FRAME_X_DISPLAY (f), CurrentTime);
3278 XUngrabKeyboard (FRAME_X_DISPLAY (f), CurrentTime);
3279 #endif
3280 XMenuDestroy (FRAME_X_DISPLAY (f), menu);
3281
3282 #ifdef HAVE_X_WINDOWS
3283 /* Assume the mouse has moved out of the X window.
3284 If it has actually moved in, we will get an EnterNotify. */
3285 x_mouse_leave (FRAME_X_DISPLAY_INFO (f));
3286
3287 /* State that no mouse buttons are now held.
3288 (The oldXMenu code doesn't track this info for us.)
3289 That is not necessarily true, but the fiction leads to reasonable
3290 results, and it is a pain to ask which are actually held now. */
3291 FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
3292
3293 #endif /* HAVE_X_WINDOWS */
3294
3295 UNBLOCK_INPUT;
3296
3297 return Qnil;
3298 }
3299
3059 3300
3060 static Lisp_Object 3301 static Lisp_Object
3061 xmenu_show (f, x, y, for_click, keymaps, title, error) 3302 xmenu_show (f, x, y, for_click, keymaps, title, error)
3062 FRAME_PTR f; 3303 FRAME_PTR f;
3063 int x, y; 3304 int x, y;
3071 int pane, selidx, lpane, status; 3312 int pane, selidx, lpane, status;
3072 Lisp_Object entry, pane_prefix; 3313 Lisp_Object entry, pane_prefix;
3073 char *datap; 3314 char *datap;
3074 int ulx, uly, width, height; 3315 int ulx, uly, width, height;
3075 int dispwidth, dispheight; 3316 int dispwidth, dispheight;
3076 int i, j; 3317 int i, j, lines, maxlines;
3077 int maxwidth; 3318 int maxwidth;
3078 int dummy_int; 3319 int dummy_int;
3079 unsigned int dummy_uint; 3320 unsigned int dummy_uint;
3321 int specpdl_count = SPECPDL_INDEX ();
3080 3322
3081 *error = 0; 3323 *error = 0;
3082 if (menu_items_n_panes == 0) 3324 if (menu_items_n_panes == 0)
3083 return Qnil; 3325 return Qnil;
3084 3326
3099 { 3341 {
3100 *error = "Can't create menu"; 3342 *error = "Can't create menu";
3101 return Qnil; 3343 return Qnil;
3102 } 3344 }
3103 3345
3346 /* Don't GC while we prepare and show the menu,
3347 because we give the oldxmenu library pointers to the
3348 contents of strings. */
3349 inhibit_garbage_collection ();
3350
3104 #ifdef HAVE_X_WINDOWS 3351 #ifdef HAVE_X_WINDOWS
3105 /* Adjust coordinates to relative to the outer (window manager) window. */ 3352 /* Adjust coordinates to relative to the outer (window manager) window. */
3106 { 3353 x += FRAME_OUTER_TO_INNER_DIFF_X (f);
3107 Window child; 3354 y += FRAME_OUTER_TO_INNER_DIFF_Y (f);
3108 int win_x = 0, win_y = 0;
3109
3110 /* Find the position of the outside upper-left corner of
3111 the inner window, with respect to the outer window. */
3112 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
3113 {
3114 BLOCK_INPUT;
3115 XTranslateCoordinates (FRAME_X_DISPLAY (f),
3116
3117 /* From-window, to-window. */
3118 f->output_data.x->window_desc,
3119 f->output_data.x->parent_desc,
3120
3121 /* From-position, to-position. */
3122 0, 0, &win_x, &win_y,
3123
3124 /* Child of window. */
3125 &child);
3126 UNBLOCK_INPUT;
3127 x += win_x;
3128 y += win_y;
3129 }
3130 }
3131 #endif /* HAVE_X_WINDOWS */ 3355 #endif /* HAVE_X_WINDOWS */
3132 3356
3133 /* Adjust coordinates to be root-window-relative. */ 3357 /* Adjust coordinates to be root-window-relative. */
3134 x += f->output_data.x->left_pos; 3358 x += f->left_pos;
3135 y += f->output_data.x->top_pos; 3359 y += f->top_pos;
3136 3360
3137 /* Create all the necessary panes and their items. */ 3361 /* Create all the necessary panes and their items. */
3138 i = 0; 3362 maxlines = lines = i = 0;
3139 while (i < menu_items_used) 3363 while (i < menu_items_used)
3140 { 3364 {
3141 if (EQ (XVECTOR (menu_items)->contents[i], Qt)) 3365 if (EQ (XVECTOR (menu_items)->contents[i], Qt))
3142 { 3366 {
3143 /* Create a new pane. */ 3367 /* Create a new pane. */
3144 Lisp_Object pane_name, prefix; 3368 Lisp_Object pane_name, prefix;
3145 char *pane_string; 3369 char *pane_string;
3146 3370
3371 maxlines = max (maxlines, lines);
3372 lines = 0;
3147 pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME]; 3373 pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
3148 prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX]; 3374 prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
3149 pane_string = (NILP (pane_name) 3375 pane_string = (NILP (pane_name)
3150 ? "" : (char *) SDATA (pane_name)); 3376 ? "" : (char *) SDATA (pane_name));
3151 if (keymaps && !NILP (prefix)) 3377 if (keymaps && !NILP (prefix))
3234 XMenuDestroy (FRAME_X_DISPLAY (f), menu); 3460 XMenuDestroy (FRAME_X_DISPLAY (f), menu);
3235 *error = "Can't add selection to menu"; 3461 *error = "Can't add selection to menu";
3236 return Qnil; 3462 return Qnil;
3237 } 3463 }
3238 i += MENU_ITEMS_ITEM_LENGTH; 3464 i += MENU_ITEMS_ITEM_LENGTH;
3465 lines++;
3239 } 3466 }
3240 } 3467 }
3468
3469 maxlines = max (maxlines, lines);
3241 3470
3242 /* All set and ready to fly. */ 3471 /* All set and ready to fly. */
3243 XMenuRecompute (FRAME_X_DISPLAY (f), menu); 3472 XMenuRecompute (FRAME_X_DISPLAY (f), menu);
3244 dispwidth = DisplayWidth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f)); 3473 dispwidth = DisplayWidth (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f));
3245 dispheight = DisplayHeight (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f)); 3474 dispheight = DisplayHeight (FRAME_X_DISPLAY (f), FRAME_X_SCREEN_NUMBER (f));
3260 uly = dispheight - height; 3489 uly = dispheight - height;
3261 } 3490 }
3262 if (ulx < 0) x -= ulx; 3491 if (ulx < 0) x -= ulx;
3263 if (uly < 0) y -= uly; 3492 if (uly < 0) y -= uly;
3264 3493
3494 if (! for_click)
3495 {
3496 /* If position was not given by a mouse click, adjust so upper left
3497 corner of the menu as a whole ends up at given coordinates. This
3498 is what x-popup-menu says in its documentation. */
3499 x += width/2;
3500 y += 1.5*height/(maxlines+2);
3501 }
3502
3265 XMenuSetAEQ (menu, TRUE); 3503 XMenuSetAEQ (menu, TRUE);
3266 XMenuSetFreeze (menu, TRUE); 3504 XMenuSetFreeze (menu, TRUE);
3267 pane = selidx = 0; 3505 pane = selidx = 0;
3506
3507 #ifndef MSDOS
3508 XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f));
3509 #endif
3510
3511 record_unwind_protect (pop_down_menu,
3512 Fcons (make_save_value (f, 0),
3513 make_save_value (menu, 0)));
3268 3514
3269 /* Help display under X won't work because XMenuActivate contains 3515 /* Help display under X won't work because XMenuActivate contains
3270 a loop that doesn't give Emacs a chance to process it. */ 3516 a loop that doesn't give Emacs a chance to process it. */
3271 menu_help_frame = f; 3517 menu_help_frame = f;
3272 status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx, 3518 status = XMenuActivate (FRAME_X_DISPLAY (f), menu, &pane, &selidx,
3273 x, y, ButtonReleaseMask, &datap, 3519 x, y, ButtonReleaseMask, &datap,
3274 menu_help_callback); 3520 menu_help_callback);
3275
3276
3277 #ifdef HAVE_X_WINDOWS
3278 /* Assume the mouse has moved out of the X window.
3279 If it has actually moved in, we will get an EnterNotify. */
3280 x_mouse_leave (FRAME_X_DISPLAY_INFO (f));
3281 #endif
3282 3521
3283 switch (status) 3522 switch (status)
3284 { 3523 {
3285 case XM_SUCCESS: 3524 case XM_SUCCESS:
3286 #ifdef XDEBUG 3525 #ifdef XDEBUG
3323 break; 3562 break;
3324 3563
3325 case XM_FAILURE: 3564 case XM_FAILURE:
3326 *error = "Can't activate menu"; 3565 *error = "Can't activate menu";
3327 case XM_IA_SELECT: 3566 case XM_IA_SELECT:
3328 case XM_NO_SELECT:
3329 entry = Qnil; 3567 entry = Qnil;
3330 break; 3568 break;
3331 } 3569 case XM_NO_SELECT:
3332 XMenuDestroy (FRAME_X_DISPLAY (f), menu); 3570 /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
3333 3571 the menu was invoked with a mouse event as POSITION). */
3334 #ifdef HAVE_X_WINDOWS 3572 if (! for_click)
3335 /* State that no mouse buttons are now held. 3573 Fsignal (Qquit, Qnil);
3336 (The oldXMenu code doesn't track this info for us.) 3574 entry = Qnil;
3337 That is not necessarily true, but the fiction leads to reasonable 3575 break;
3338 results, and it is a pain to ask which are actually held now. */ 3576 }
3339 FRAME_X_DISPLAY_INFO (f)->grabbed = 0; 3577
3340 #endif 3578 unbind_to (specpdl_count, Qnil);
3341 3579
3342 return entry; 3580 return entry;
3343 } 3581 }
3344 3582
3345 #endif /* not USE_X_TOOLKIT */ 3583 #endif /* not USE_X_TOOLKIT */
3369 defsubr (&Sx_popup_menu); 3607 defsubr (&Sx_popup_menu);
3370 #ifdef HAVE_MENUS 3608 #ifdef HAVE_MENUS
3371 defsubr (&Sx_popup_dialog); 3609 defsubr (&Sx_popup_dialog);
3372 #endif 3610 #endif
3373 } 3611 }
3612
3613 /* arch-tag: 92ea573c-398e-496e-ac73-2436f7d63242
3614 (do not change this comment) */