This source file includes following definitions.
- pgtk_menu_set_in_use
- DEFUN
- popup_widget_loop
- pgtk_activate_menubar
- popup_deactivate_callback
- show_help_event
- menu_highlight_callback
- menubar_selection_callback
- update_frame_menubar
- set_frame_menubar
- initialize_frame_menubar
- popup_selection_callback
- pop_down_menu
- create_and_show_popup_menu
- cleanup_widget_value_tree
- pgtk_menu_show
- dialog_selection_callback
- create_and_show_dialog
- pgtk_dialog_show
- pgtk_popup_dialog
- popup_activated
- DEFUN
- syms_of_pgtkmenu
- syms_of_pgtkmenu_for_pdumper
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 #include <config.h>
26
27 #include "lisp.h"
28 #include "frame.h"
29 #include "window.h"
30 #include "character.h"
31 #include "buffer.h"
32 #include "keymap.h"
33 #include "coding.h"
34 #include "commands.h"
35 #include "blockinput.h"
36 #include "termhooks.h"
37 #include "keyboard.h"
38 #include "menu.h"
39 #include "pdumper.h"
40 #include "xgselect.h"
41
42 #include "gtkutil.h"
43 #include <gtk/gtk.h>
44
45
46
47 static int popup_activated_flag;
48
49
50
51 void
52 pgtk_menu_set_in_use (bool in_use)
53 {
54 Lisp_Object frames, frame;
55
56 menu_items_inuse = in_use;
57 popup_activated_flag = in_use;
58
59
60 FOR_EACH_FRAME (frames, frame)
61 {
62 struct frame *f = XFRAME (frame);
63
64 if (in_use && FRAME_Z_GROUP_ABOVE (f))
65 pgtk_set_z_group (f, Qabove_suspended, Qabove);
66 else if (!in_use && FRAME_Z_GROUP_ABOVE_SUSPENDED (f))
67 pgtk_set_z_group (f, Qabove, Qabove_suspended);
68 }
69 }
70
71 DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, Sx_menu_bar_open_internal, 0, 1, "i",
72 doc: )
73 (Lisp_Object frame)
74 {
75 GtkWidget *menubar;
76 struct frame *f;
77
78 block_input ();
79 f = decode_window_system_frame (frame);
80
81 if (FRAME_EXTERNAL_MENU_BAR (f))
82 set_frame_menubar (f, true);
83
84 menubar = FRAME_X_OUTPUT (f)->menubar_widget;
85 if (menubar)
86 {
87
88 GList *children = gtk_container_get_children (GTK_CONTAINER (menubar));
89
90 if (children)
91 {
92 g_signal_emit_by_name (children->data, "activate_item");
93 g_list_free (children);
94 }
95 }
96 unblock_input ();
97
98 return Qnil;
99 }
100
101
102
103
104 static void
105 popup_widget_loop (bool do_timers, GtkWidget *widget)
106 {
107 ++popup_activated_flag;
108
109
110 while (popup_activated_flag)
111 gtk_main_iteration ();
112 }
113
114 void
115 pgtk_activate_menubar (struct frame *f)
116 {
117 set_frame_menubar (f, true);
118
119 popup_activated_flag = 1;
120
121
122 }
123
124
125
126
127 static void
128 popup_deactivate_callback (GtkWidget *widget, gpointer client_data)
129 {
130 pgtk_menu_set_in_use (false);
131 }
132
133
134
135
136 static void
137 show_help_event (struct frame *f, GtkWidget *widget, Lisp_Object help)
138 {
139
140
141
142
143
144
145
146
147
148 }
149
150
151
152
153
154
155
156 static void
157 menu_highlight_callback (GtkWidget *widget, gpointer call_data)
158 {
159 xg_menu_item_cb_data *cb_data;
160 Lisp_Object help;
161
162 cb_data = g_object_get_data (G_OBJECT (widget), XG_ITEM_DATA);
163 if (!cb_data)
164 return;
165
166 help = call_data ? cb_data->help : Qnil;
167
168
169
170
171
172
173
174 show_help_event (popup_activated_flag <= 1 ? cb_data->cl_data->f : NULL,
175 widget, help);
176 }
177
178
179
180
181
182 static bool xg_crazy_callback_abort;
183
184
185
186
187
188 static void
189 menubar_selection_callback (GtkWidget *widget, gpointer client_data)
190 {
191 xg_menu_item_cb_data *cb_data = client_data;
192
193 if (xg_crazy_callback_abort)
194 return;
195
196 if (!cb_data || !cb_data->cl_data || !cb_data->cl_data->f)
197 return;
198
199
200
201
202
203
204 if (GTK_IS_RADIO_MENU_ITEM (widget)
205 && !gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
206 return;
207
208
209
210
211
212
213
214 block_input ();
215 while (gtk_events_pending ())
216 gtk_main_iteration ();
217 unblock_input ();
218
219 find_and_call_menu_selection (cb_data->cl_data->f,
220 cb_data->cl_data->menu_bar_items_used,
221 cb_data->cl_data->menu_bar_vector,
222 cb_data->call_data);
223 }
224
225
226
227
228 static void
229 update_frame_menubar (struct frame *f)
230 {
231 xg_update_frame_menubar (f);
232 }
233
234
235
236
237
238 void
239 set_frame_menubar (struct frame *f, bool deep_p)
240 {
241 GtkWidget *menubar_widget;
242 Lisp_Object items;
243 widget_value *wv, *first_wv, *prev_wv = 0;
244 int i;
245 int *submenu_start, *submenu_end;
246 bool *submenu_top_level_items;
247 int *submenu_n_panes;
248
249
250 menubar_widget = f->output_data.pgtk->menubar_widget;
251
252 XSETFRAME (Vmenu_updating_frame, f);
253
254 if (!menubar_widget)
255 deep_p = true;
256
257 if (deep_p)
258 {
259 struct buffer *prev = current_buffer;
260 Lisp_Object buffer;
261 specpdl_ref specpdl_count = SPECPDL_INDEX ();
262 int previous_menu_items_used = f->menu_bar_items_used;
263 Lisp_Object *previous_items
264 = alloca (previous_menu_items_used * sizeof *previous_items);
265 int subitems;
266
267
268
269 if (!menubar_widget)
270 previous_menu_items_used = 0;
271
272 buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents;
273 specbind (Qinhibit_quit, Qt);
274
275
276 specbind (Qdebug_on_next_call, Qnil);
277
278 record_unwind_save_match_data ();
279 if (NILP (Voverriding_local_map_menu_flag))
280 {
281 specbind (Qoverriding_terminal_local_map, Qnil);
282 specbind (Qoverriding_local_map, Qnil);
283 }
284
285 set_buffer_internal_1 (XBUFFER (buffer));
286
287
288 safe_run_hooks (Qactivate_menubar_hook);
289
290
291
292 safe_run_hooks (Qmenu_bar_update_hook);
293 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
294
295 items = FRAME_MENU_BAR_ITEMS (f);
296
297
298 if (previous_menu_items_used)
299 memcpy (previous_items, xvector_contents (f->menu_bar_vector),
300 previous_menu_items_used * word_size);
301
302
303
304 save_menu_items ();
305
306 menu_items = f->menu_bar_vector;
307 menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
308 subitems = ASIZE (items) / 4;
309 submenu_start = alloca ((subitems + 1) * sizeof *submenu_start);
310 submenu_end = alloca (subitems * sizeof *submenu_end);
311 submenu_n_panes = alloca (subitems * sizeof *submenu_n_panes);
312 submenu_top_level_items = alloca (subitems
313 * sizeof *submenu_top_level_items);
314 init_menu_items ();
315 for (i = 0; i < subitems; i++)
316 {
317 Lisp_Object key, string, maps;
318
319 key = AREF (items, 4 * i);
320 string = AREF (items, 4 * i + 1);
321 maps = AREF (items, 4 * i + 2);
322 if (NILP (string))
323 break;
324
325 submenu_start[i] = menu_items_used;
326
327 menu_items_n_panes = 0;
328 submenu_top_level_items[i]
329 = parse_single_submenu (key, string, maps);
330 submenu_n_panes[i] = menu_items_n_panes;
331
332 submenu_end[i] = menu_items_used;
333 }
334
335 submenu_start[i] = -1;
336 finish_menu_items ();
337
338
339
340
341 wv = make_widget_value ("menubar", NULL, true, Qnil);
342 wv->button_type = BUTTON_TYPE_NONE;
343 first_wv = wv;
344
345 for (i = 0; submenu_start[i] >= 0; i++)
346 {
347 menu_items_n_panes = submenu_n_panes[i];
348 wv = digest_single_submenu (submenu_start[i], submenu_end[i],
349 submenu_top_level_items[i]);
350 if (prev_wv)
351 prev_wv->next = wv;
352 else
353 first_wv->contents = wv;
354
355 wv->enabled = true;
356 wv->button_type = BUTTON_TYPE_NONE;
357 prev_wv = wv;
358 }
359
360 set_buffer_internal_1 (prev);
361
362
363
364
365
366 for (i = 0; i < previous_menu_items_used; i++)
367 if (menu_items_used == i
368 || (!EQ (previous_items[i], AREF (menu_items, i))))
369 break;
370 if (i == menu_items_used && i == previous_menu_items_used && i != 0)
371 {
372
373
374 free_menubar_widget_value_tree (first_wv);
375 discard_menu_items ();
376 unbind_to (specpdl_count, Qnil);
377 return;
378 }
379
380
381 fset_menu_bar_vector (f, menu_items);
382 f->menu_bar_items_used = menu_items_used;
383
384
385 unbind_to (specpdl_count, Qnil);
386
387
388
389 wv = first_wv->contents;
390 for (i = 0; i < ASIZE (items); i += 4)
391 {
392 Lisp_Object string;
393 string = AREF (items, i + 1);
394 if (NILP (string))
395 break;
396 wv->name = SSDATA (string);
397 update_submenu_strings (wv->contents);
398 wv = wv->next;
399 }
400
401 }
402 else
403 {
404
405
406
407 wv = make_widget_value ("menubar", NULL, true, Qnil);
408 wv->button_type = BUTTON_TYPE_NONE;
409 first_wv = wv;
410
411 items = FRAME_MENU_BAR_ITEMS (f);
412 for (i = 0; i < ASIZE (items); i += 4)
413 {
414 Lisp_Object string;
415
416 string = AREF (items, i + 1);
417 if (NILP (string))
418 break;
419
420 wv = make_widget_value (SSDATA (string), NULL, true, Qnil);
421 wv->button_type = BUTTON_TYPE_NONE;
422
423
424
425
426 wv->call_data = (void *) (intptr_t) (-1);
427
428 if (prev_wv)
429 prev_wv->next = wv;
430 else
431 first_wv->contents = wv;
432 prev_wv = wv;
433 }
434
435
436
437
438 f->menu_bar_items_used = 0;
439 }
440
441 block_input ();
442
443 xg_crazy_callback_abort = true;
444 if (menubar_widget)
445 {
446
447
448 xg_modify_menubar_widgets (menubar_widget,
449 f,
450 first_wv,
451 deep_p,
452 G_CALLBACK (menubar_selection_callback),
453 G_CALLBACK (popup_deactivate_callback),
454 G_CALLBACK (menu_highlight_callback));
455 }
456 else
457 {
458 menubar_widget
459 = xg_create_widget ("menubar", "menubar", f, first_wv,
460 G_CALLBACK (menubar_selection_callback),
461 G_CALLBACK (popup_deactivate_callback),
462 G_CALLBACK (menu_highlight_callback));
463
464 f->output_data.pgtk->menubar_widget = menubar_widget;
465 }
466
467 free_menubar_widget_value_tree (first_wv);
468 update_frame_menubar (f);
469
470 xg_crazy_callback_abort = false;
471
472 unblock_input ();
473 }
474
475
476
477
478
479
480 void
481 initialize_frame_menubar (struct frame *f)
482 {
483
484
485 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
486 set_frame_menubar (f, true);
487 }
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508 static Lisp_Object *volatile menu_item_selection;
509
510 static void
511 popup_selection_callback (GtkWidget *widget, gpointer client_data)
512 {
513 xg_menu_item_cb_data *cb_data = client_data;
514
515 if (xg_crazy_callback_abort)
516 return;
517 if (cb_data)
518 menu_item_selection = cb_data->call_data;
519 }
520
521 static void
522 pop_down_menu (void *arg)
523 {
524 popup_activated_flag = 0;
525 block_input ();
526 gtk_widget_destroy (GTK_WIDGET (arg));
527 unblock_input ();
528 }
529
530
531
532
533 static void
534 create_and_show_popup_menu (struct frame *f, widget_value * first_wv,
535 int x, int y, bool for_click)
536 {
537 GtkWidget *menu;
538 specpdl_ref specpdl_count = SPECPDL_INDEX ();
539
540 eassert (FRAME_PGTK_P (f));
541
542 xg_crazy_callback_abort = true;
543 menu = xg_create_widget ("popup", first_wv->name, f, first_wv,
544 G_CALLBACK (popup_selection_callback),
545 G_CALLBACK (popup_deactivate_callback),
546 G_CALLBACK (menu_highlight_callback));
547 xg_crazy_callback_abort = false;
548
549
550 gtk_widget_show_all (menu);
551
552 if (for_click)
553 gtk_menu_popup_at_pointer (GTK_MENU (menu),
554 FRAME_DISPLAY_INFO (f)->last_click_event);
555 else
556 {
557 GdkRectangle rect;
558 rect.x = x;
559 rect.y = y;
560 rect.width = 1;
561 rect.height = 1;
562 gtk_menu_popup_at_rect (GTK_MENU (menu),
563 gtk_widget_get_window (FRAME_GTK_WIDGET (f)),
564 &rect,
565 GDK_GRAVITY_NORTH_WEST, GDK_GRAVITY_NORTH_WEST,
566 FRAME_DISPLAY_INFO (f)->last_click_event);
567 }
568
569 record_unwind_protect_ptr (pop_down_menu, menu);
570
571 if (gtk_widget_get_mapped (menu))
572 {
573
574
575 popup_activated_flag = 1;
576
577 popup_widget_loop (true, menu);
578 }
579
580 unbind_to (specpdl_count, Qnil);
581
582
583
584 FRAME_DISPLAY_INFO (f)->grabbed = 0;
585 }
586
587 static void
588 cleanup_widget_value_tree (void *arg)
589 {
590 free_menubar_widget_value_tree (arg);
591 }
592
593 Lisp_Object
594 pgtk_menu_show (struct frame *f, int x, int y, int menuflags,
595 Lisp_Object title, const char **error_name)
596 {
597 int i;
598 widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
599 widget_value **submenu_stack
600 = alloca (menu_items_used * sizeof *submenu_stack);
601 Lisp_Object *subprefix_stack
602 = alloca (menu_items_used * sizeof *subprefix_stack);
603 int submenu_depth = 0;
604
605 specpdl_ref specpdl_count = SPECPDL_INDEX ();
606
607 eassert (FRAME_PGTK_P (f));
608
609 *error_name = NULL;
610
611 if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
612 {
613 *error_name = "Empty menu";
614 return Qnil;
615 }
616
617 block_input ();
618
619
620
621 wv = make_widget_value ("menu", NULL, true, Qnil);
622 wv->button_type = BUTTON_TYPE_NONE;
623 first_wv = wv;
624 bool first_pane = true;
625
626
627 i = 0;
628 while (i < menu_items_used)
629 {
630 if (NILP (AREF (menu_items, i)))
631 {
632 submenu_stack[submenu_depth++] = save_wv;
633 save_wv = prev_wv;
634 prev_wv = 0;
635 first_pane = true;
636 i++;
637 }
638 else if (EQ (AREF (menu_items, i), Qlambda))
639 {
640 prev_wv = save_wv;
641 save_wv = submenu_stack[--submenu_depth];
642 first_pane = false;
643 i++;
644 }
645 else if (EQ (AREF (menu_items, i), Qt) && submenu_depth != 0)
646 i += MENU_ITEMS_PANE_LENGTH;
647
648
649 else if (EQ (AREF (menu_items, i), Qquote))
650 i += 1;
651 else if (EQ (AREF (menu_items, i), Qt))
652 {
653
654 Lisp_Object pane_name, prefix;
655 const char *pane_string;
656
657 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
658 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
659
660 #ifndef HAVE_MULTILINGUAL_MENU
661 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
662 {
663 pane_name = ENCODE_MENU_STRING (pane_name);
664 ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
665 }
666 #endif
667 pane_string = (NILP (pane_name) ? "" : SSDATA (pane_name));
668
669
670 if (menu_items_n_panes == 1)
671 pane_string = "";
672
673
674
675
676 if (!(menuflags & MENU_KEYMAPS) && strcmp (pane_string, ""))
677 {
678 wv = make_widget_value (pane_string, NULL, true, Qnil);
679 if (save_wv)
680 save_wv->next = wv;
681 else
682 first_wv->contents = wv;
683 if ((menuflags & MENU_KEYMAPS) && !NILP (prefix))
684 wv->name++;
685 wv->button_type = BUTTON_TYPE_NONE;
686 save_wv = wv;
687 prev_wv = 0;
688 }
689 else if (first_pane)
690 {
691 save_wv = wv;
692 prev_wv = 0;
693 }
694 first_pane = false;
695 i += MENU_ITEMS_PANE_LENGTH;
696 }
697 else
698 {
699
700 Lisp_Object item_name, enable, descrip, def, type, selected, help;
701 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
702 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
703 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
704 def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
705 type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
706 selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
707 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
708
709 #ifndef HAVE_MULTILINGUAL_MENU
710 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
711 {
712 item_name = ENCODE_MENU_STRING (item_name);
713 ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
714 }
715
716 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
717 {
718 descrip = ENCODE_MENU_STRING (descrip);
719 ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
720 }
721 #endif
722
723 wv = make_widget_value (SSDATA (item_name), NULL, !NILP (enable),
724 STRINGP (help) ? help : Qnil);
725 if (prev_wv)
726 prev_wv->next = wv;
727 else
728 save_wv->contents = wv;
729 if (!NILP (descrip))
730 wv->key = SSDATA (descrip);
731
732
733
734 wv->call_data = !NILP (def) ? aref_addr (menu_items, i) : 0;
735
736 if (NILP (type))
737 wv->button_type = BUTTON_TYPE_NONE;
738 else if (EQ (type, QCtoggle))
739 wv->button_type = BUTTON_TYPE_TOGGLE;
740 else if (EQ (type, QCradio))
741 wv->button_type = BUTTON_TYPE_RADIO;
742 else
743 emacs_abort ();
744
745 wv->selected = !NILP (selected);
746
747 prev_wv = wv;
748
749 i += MENU_ITEMS_ITEM_LENGTH;
750 }
751 }
752
753
754 if (!NILP (title))
755 {
756 widget_value *wv_title;
757 widget_value *wv_sep1 = make_widget_value ("--", NULL, false, Qnil);
758 widget_value *wv_sep2 = make_widget_value ("--", NULL, false, Qnil);
759
760 wv_sep2->next = first_wv->contents;
761 wv_sep1->next = wv_sep2;
762
763 #ifndef HAVE_MULTILINGUAL_MENU
764 if (STRING_MULTIBYTE (title))
765 title = ENCODE_MENU_STRING (title);
766 #endif
767
768 wv_title = make_widget_value (SSDATA (title), NULL, true, Qnil);
769 wv_title->button_type = BUTTON_TYPE_NONE;
770 wv_title->next = wv_sep1;
771 first_wv->contents = wv_title;
772 }
773
774
775 menu_item_selection = 0;
776
777
778
779 record_unwind_protect_ptr (cleanup_widget_value_tree, first_wv);
780
781
782 create_and_show_popup_menu (f, first_wv, x, y, menuflags & MENU_FOR_CLICK);
783
784 unbind_to (specpdl_count, Qnil);
785
786
787
788 if (menu_item_selection != 0)
789 {
790 Lisp_Object prefix, entry;
791
792 prefix = entry = Qnil;
793 i = 0;
794 while (i < menu_items_used)
795 {
796 if (NILP (AREF (menu_items, i)))
797 {
798 subprefix_stack[submenu_depth++] = prefix;
799 prefix = entry;
800 i++;
801 }
802 else if (EQ (AREF (menu_items, i), Qlambda))
803 {
804 prefix = subprefix_stack[--submenu_depth];
805 i++;
806 }
807 else if (EQ (AREF (menu_items, i), Qt))
808 {
809 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
810 i += MENU_ITEMS_PANE_LENGTH;
811 }
812
813
814 else if (EQ (AREF (menu_items, i), Qquote))
815 i += 1;
816 else
817 {
818 entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
819 if (menu_item_selection == aref_addr (menu_items, i))
820 {
821 if (menuflags & MENU_KEYMAPS)
822 {
823 int j;
824
825 entry = list1 (entry);
826 if (!NILP (prefix))
827 entry = Fcons (prefix, entry);
828 for (j = submenu_depth - 1; j >= 0; j--)
829 if (!NILP (subprefix_stack[j]))
830 entry = Fcons (subprefix_stack[j], entry);
831 }
832 unblock_input ();
833 return entry;
834 }
835 i += MENU_ITEMS_ITEM_LENGTH;
836 }
837 }
838 }
839 else if (!(menuflags & MENU_FOR_CLICK))
840 {
841 unblock_input ();
842
843 quit ();
844 }
845
846 unblock_input ();
847 return Qnil;
848 }
849
850 static void
851 dialog_selection_callback (GtkWidget *widget, gpointer client_data)
852 {
853
854
855 if ((intptr_t) client_data != -1)
856 menu_item_selection = client_data;
857
858 popup_activated_flag = 0;
859 }
860
861
862
863
864 static void
865 create_and_show_dialog (struct frame *f, widget_value *first_wv)
866 {
867 GtkWidget *menu;
868
869 eassert (FRAME_PGTK_P (f));
870
871 menu = xg_create_widget ("dialog", first_wv->name, f, first_wv,
872 G_CALLBACK (dialog_selection_callback),
873 G_CALLBACK (popup_deactivate_callback), 0);
874
875 if (menu)
876 {
877 specpdl_ref specpdl_count = SPECPDL_INDEX ();
878 record_unwind_protect_ptr (pop_down_menu, menu);
879
880
881 gtk_widget_show_all (menu);
882
883
884 popup_widget_loop (true, menu);
885
886 unbind_to (specpdl_count, Qnil);
887 }
888 }
889
890 static const char *button_names[] = {
891 "button1", "button2", "button3", "button4", "button5",
892 "button6", "button7", "button8", "button9", "button10"
893 };
894
895 Lisp_Object
896 pgtk_dialog_show (struct frame *f, Lisp_Object title,
897 Lisp_Object header, const char **error_name)
898 {
899 int i, nb_buttons = 0;
900 char dialog_name[6];
901
902 widget_value *wv, *first_wv = 0, *prev_wv = 0;
903
904
905 int left_count = 0;
906
907 bool boundary_seen = false;
908
909 specpdl_ref specpdl_count = SPECPDL_INDEX ();
910
911 eassert (FRAME_PGTK_P (f));
912
913 *error_name = NULL;
914
915 if (menu_items_n_panes > 1)
916 {
917 *error_name = "Multiple panes in dialog box";
918 return Qnil;
919 }
920
921
922
923 {
924 Lisp_Object pane_name;
925 const char *pane_string;
926 pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
927 pane_string = (NILP (pane_name) ? "" : SSDATA (pane_name));
928 prev_wv = make_widget_value ("message", (char *) pane_string, true, Qnil);
929 first_wv = prev_wv;
930
931
932 i = MENU_ITEMS_PANE_LENGTH;
933 while (i < menu_items_used)
934 {
935
936
937 Lisp_Object item_name, enable, descrip;
938 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
939 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
940 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
941
942 if (NILP (item_name))
943 {
944 free_menubar_widget_value_tree (first_wv);
945 *error_name = "Submenu in dialog items";
946 return Qnil;
947 }
948 if (EQ (item_name, Qquote))
949 {
950
951
952 boundary_seen = true;
953 i++;
954 continue;
955 }
956 if (nb_buttons >= 9)
957 {
958 free_menubar_widget_value_tree (first_wv);
959 *error_name = "Too many dialog items";
960 return Qnil;
961 }
962
963 wv = make_widget_value (button_names[nb_buttons],
964 SSDATA (item_name), !NILP (enable), Qnil);
965 prev_wv->next = wv;
966 if (!NILP (descrip))
967 wv->key = SSDATA (descrip);
968 wv->call_data = aref_addr (menu_items, i);
969 prev_wv = wv;
970
971 if (!boundary_seen)
972 left_count++;
973
974 nb_buttons++;
975 i += MENU_ITEMS_ITEM_LENGTH;
976 }
977
978
979
980 if (!boundary_seen)
981 left_count = nb_buttons - nb_buttons / 2;
982
983 wv = make_widget_value (dialog_name, NULL, false, Qnil);
984
985
986
987
988 if (NILP (header))
989 dialog_name[0] = 'Q';
990 else
991 dialog_name[0] = 'I';
992
993
994
995
996 dialog_name[1] = '0' + nb_buttons;
997 dialog_name[2] = 'B';
998 dialog_name[3] = 'R';
999
1000 dialog_name[4] = '0' + nb_buttons - left_count;
1001 dialog_name[5] = 0;
1002 wv->contents = first_wv;
1003 first_wv = wv;
1004 }
1005
1006
1007 menu_item_selection = 0;
1008
1009
1010
1011 record_unwind_protect_ptr (cleanup_widget_value_tree, first_wv);
1012
1013
1014 create_and_show_dialog (f, first_wv);
1015
1016 unbind_to (specpdl_count, Qnil);
1017
1018
1019
1020 if (menu_item_selection != 0)
1021 {
1022 i = 0;
1023 while (i < menu_items_used)
1024 {
1025 Lisp_Object entry;
1026
1027 if (EQ (AREF (menu_items, i), Qt))
1028 i += MENU_ITEMS_PANE_LENGTH;
1029 else if (EQ (AREF (menu_items, i), Qquote))
1030 {
1031
1032
1033 ++i;
1034 }
1035 else
1036 {
1037 entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
1038 if (menu_item_selection == aref_addr (menu_items, i))
1039 return entry;
1040 i += MENU_ITEMS_ITEM_LENGTH;
1041 }
1042 }
1043 }
1044 else
1045
1046 quit ();
1047
1048 return Qnil;
1049 }
1050
1051 Lisp_Object
1052 pgtk_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
1053 {
1054 Lisp_Object title;
1055 const char *error_name;
1056 Lisp_Object selection;
1057 specpdl_ref specpdl_count = SPECPDL_INDEX ();
1058
1059 check_window_system (f);
1060
1061
1062 title = Fcar (contents);
1063 CHECK_STRING (title);
1064 record_unwind_protect_void (unuse_menu_items);
1065
1066 if (NILP (Fcar (Fcdr (contents))))
1067
1068
1069
1070 contents = list2 (title, Fcons (build_string ("Ok"), Qt));
1071
1072 list_of_panes (list1 (contents));
1073
1074
1075 block_input ();
1076 selection = pgtk_dialog_show (f, title, header, &error_name);
1077 unblock_input ();
1078
1079 unbind_to (specpdl_count, Qnil);
1080 discard_menu_items ();
1081
1082 if (error_name)
1083 error ("%s", error_name);
1084 return selection;
1085 }
1086
1087
1088
1089
1090 int
1091 popup_activated (void)
1092 {
1093 return popup_activated_flag;
1094 }
1095
1096
1097
1098 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
1099 doc:
1100 )
1101 (void)
1102 {
1103 return (popup_activated ())? Qt : Qnil;
1104 }
1105
1106 static void syms_of_pgtkmenu_for_pdumper (void);
1107
1108 void
1109 syms_of_pgtkmenu (void)
1110 {
1111 DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
1112 defsubr (&Smenu_or_popup_active_p);
1113
1114 DEFSYM (Qframe_monitor_workarea, "frame-monitor-workarea");
1115
1116 defsubr (&Sx_menu_bar_open_internal);
1117 Ffset (intern_c_string ("accelerate-menu"),
1118 intern_c_string (Sx_menu_bar_open_internal.s.symbol_name));
1119
1120 pdumper_do_now_and_after_load (syms_of_pgtkmenu_for_pdumper);
1121 }
1122
1123 static void
1124 syms_of_pgtkmenu_for_pdumper (void)
1125 {
1126 }