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