aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1994-01-26 07:20:15 +0000
committerRichard M. Stallman1994-01-26 07:20:15 +0000
commit18686d472bdb9124009c741e03f04cfc9e2e31fa (patch)
treec6ccc17e7189d4253aaa8425698e4e64062388a6 /src
parent3afe33e7ec3d31d67e920aeffde0eda8b6b16a9c (diff)
downloademacs-18686d472bdb9124009c741e03f04cfc9e2e31fa.tar.gz
emacs-18686d472bdb9124009c741e03f04cfc9e2e31fa.zip
Find lwlib.h and xlwmenuP.h in ../lwlib.
Reshuffle functions; put new ones in #ifdef USE_X_TOOLKIT. (Fx_popup_menu): Add USE_X_TOOLKIT conditional around new decls. (string_width): New function. (event_is_in_menu_item, map_event_to_object): Likewise. (set_menu_items, free_menu_items, popup_selection_callback): Likewise. (popup_down_callback, free_menubar_widget_value_tree): Likewise. (update_one_frame_psheets, set_frame_menubar): Likewise. (Fx_popup_menu, xmenu_show): Handle USE_X_TOOLKIT. (dispatch_dummy_expose): New function. (XMenu_xpos, XMenu_ypos): Change the values of the constant assignment. (xmenu_show): Change the way to make the menubar to redraw itself by generating a dummy expose event.
Diffstat (limited to 'src')
-rw-r--r--src/xmenu.c667
1 files changed, 656 insertions, 11 deletions
diff --git a/src/xmenu.c b/src/xmenu.c
index cb47294be96..c4980ff17b7 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -24,14 +24,16 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
24 * 24 *
25 */ 25 */
26 26
27#ifdef XDEBUG 27/* Modified by Fred Pierresteguy on December 93
28 to make the popup menus and menubar use the Xt. */
29
28#include <stdio.h> 30#include <stdio.h>
29#endif
30 31
31/* On 4.3 this loses if it comes after xterm.h. */ 32/* On 4.3 this loses if it comes after xterm.h. */
32#include <signal.h> 33#include <signal.h>
33#include <config.h> 34#include <config.h>
34#include "lisp.h" 35#include "lisp.h"
36#include "termhooks.h"
35#include "frame.h" 37#include "frame.h"
36#include "window.h" 38#include "window.h"
37#include "keyboard.h" 39#include "keyboard.h"
@@ -55,6 +57,16 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
55#include <X/XMenu.h> 57#include <X/XMenu.h>
56#endif 58#endif
57 59
60#ifdef USE_X_TOOLKIT
61#include <X11/Xlib.h>
62#include <X11/IntrinsicP.h>
63#include <X11/CoreP.h>
64#include <X11/StringDefs.h>
65#include <X11/Xaw/Paned.h>
66#include "../lwlib/lwlib.h"
67#include "../lwlib/xlwmenuP.h"
68#endif /* USE_X_TOOLKIT */
69
58#define min(x,y) (((x) < (y)) ? (x) : (y)) 70#define min(x,y) (((x) < (y)) ? (x) : (y))
59#define max(x,y) (((x) > (y)) ? (x) : (y)) 71#define max(x,y) (((x) > (y)) ? (x) : (y))
60 72
@@ -72,8 +84,17 @@ extern Display *x_current_display;
72#endif /* not HAVE_X11 */ 84#endif /* not HAVE_X11 */
73 85
74extern Lisp_Object Qmenu_enable; 86extern Lisp_Object Qmenu_enable;
87extern Lisp_Object Qmenu_bar;
75Lisp_Object xmenu_show (); 88Lisp_Object xmenu_show ();
76extern int x_error_handler (); 89extern int x_error_handler ();
90#ifdef USE_X_TOOLKIT
91static widget_value *set_menu_items ();
92static int string_width ();
93static void free_menu_items ();
94#endif
95
96/* we need a unique id for each popup menu and dialog box */
97unsigned int popup_id_tick;
77 98
78/*************************************************************/ 99/*************************************************************/
79 100
@@ -85,6 +106,7 @@ xmenu_quit ()
85} 106}
86#endif 107#endif
87 108
109
88DEFUN ("x-popup-menu",Fx_popup_menu, Sx_popup_menu, 1, 2, 0, 110DEFUN ("x-popup-menu",Fx_popup_menu, Sx_popup_menu, 1, 2, 0,
89 "Pop up a deck-of-cards menu and return user's selection.\n\ 111 "Pop up a deck-of-cards menu and return user's selection.\n\
90POSITION is a position specification. This is either a mouse button event\n\ 112POSITION is a position specification. This is either a mouse button event\n\
@@ -113,7 +135,7 @@ With this form of menu, the return value is VALUE from the chosen item.")
113 (position, menu) 135 (position, menu)
114 Lisp_Object position, menu; 136 Lisp_Object position, menu;
115{ 137{
116 int number_of_panes; 138 int number_of_panes, panes;
117 Lisp_Object XMenu_return, keymap, tem; 139 Lisp_Object XMenu_return, keymap, tem;
118 int XMenu_xpos, XMenu_ypos; 140 int XMenu_xpos, XMenu_ypos;
119 char **menus; 141 char **menus;
@@ -125,9 +147,12 @@ With this form of menu, the return value is VALUE from the chosen item.")
125 char *title; 147 char *title;
126 char *error_name; 148 char *error_name;
127 Lisp_Object ltitle, selection; 149 Lisp_Object ltitle, selection;
128 int i, j; 150 int i, j, menubarp = 0;
129 FRAME_PTR f; 151 FRAME_PTR f;
130 Lisp_Object x, y, window; 152 Lisp_Object x, y, window;
153#ifdef USE_X_TOOLKIT
154 widget_value *val, *vw = 0;
155#endif /* USE_X_TOOLKIT */
131 156
132 /* Decode the first argument: find the window and the coordinates. */ 157 /* Decode the first argument: find the window and the coordinates. */
133 tem = Fcar (position); 158 tem = Fcar (position);
@@ -151,7 +176,7 @@ With this form of menu, the return value is VALUE from the chosen item.")
151 if (XTYPE (window) == Lisp_Frame) 176 if (XTYPE (window) == Lisp_Frame)
152 { 177 {
153 f = XFRAME (window); 178 f = XFRAME (window);
154 179
155 XMenu_xpos = 0; 180 XMenu_xpos = 0;
156 XMenu_ypos = 0; 181 XMenu_ypos = 0;
157 } 182 }
@@ -159,15 +184,78 @@ With this form of menu, the return value is VALUE from the chosen item.")
159 { 184 {
160 CHECK_LIVE_WINDOW (window, 0); 185 CHECK_LIVE_WINDOW (window, 0);
161 f = XFRAME (WINDOW_FRAME (XWINDOW (window))); 186 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
162 187
163 XMenu_xpos = FONT_WIDTH (f->display.x->font) * XWINDOW (window)->left; 188 XMenu_xpos = FONT_WIDTH (f->display.x->font)
164 XMenu_ypos = FONT_HEIGHT (f->display.x->font) * XWINDOW (window)->top; 189 * XWINDOW (window)->left;
190 XMenu_ypos = FONT_HEIGHT (f->display.x->font)
191 * XWINDOW (window)->top;
165 } 192 }
166 else 193 else
167 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME, 194 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
168 but I don't want to make one now. */ 195 but I don't want to make one now. */
169 CHECK_WINDOW (window, 0); 196 CHECK_WINDOW (window, 0);
170 197
198#ifdef USE_X_TOOLKIT
199 tem = Fcar (Fcdr (Fcar (Fcdr (position))));
200 if (XTYPE (Fcar (position)) != Lisp_Cons
201 && CONSP (tem)
202 && EQ (Fcar (tem), Qmenu_bar))
203 {
204 /* We are in the menubar */
205 XlwMenuWidget mw;
206 int w1 = 0, w2;
207
208 mw = (XlwMenuWidget)f->display.x->menubar_widget;
209 menubarp = 1;
210 for (vw = mw->menu.old_stack [0]->contents; vw; vw = vw->next)
211 {
212 w2 = w1;
213 w1 += string_width (mw, vw->name)
214 + 2 * (mw->menu.horizontal_spacing +
215 mw->menu.shadow_thickness);
216 if (XINT (x) < w1)
217 {
218 XMenu_xpos = w2 + 4;
219 XMenu_ypos = 0;
220 break;
221 }
222 }
223 }
224 else
225 {
226 XMenu_xpos += FONT_WIDTH (f->display.x->font) * XINT (x);
227 XMenu_ypos += FONT_HEIGHT (f->display.x->font) * XINT (y);
228 }
229
230 BLOCK_INPUT;
231 XMenu_xpos += (f->display.x->widget->core.x
232 + f->display.x->widget->core.border_width);
233 XMenu_ypos += (f->display.x->widget->core.y
234 + f->display.x->widget->core.border_width
235 + f->display.x->menubar_widget->core.height);
236 UNBLOCK_INPUT;
237
238 val = set_menu_items (menu, &prefixes, &panes, &names,
239 &enables, &menus, &items, &number_of_panes, &obj_list,
240 &title, &error_name);
241 selection = xmenu_show (f, val, XMenu_xpos, XMenu_ypos,
242 menubarp, vw);
243
244 free_menu_items (names, enables, menus, items, number_of_panes, obj_list,
245 title, error_name);
246
247 if (selection != NUL)
248 { /* selected something */
249 XMenu_return = selection;
250 }
251 else
252 { /* nothing selected */
253 XMenu_return = Qnil;
254 }
255
256 return XMenu_return;
257
258#else /* not USE_X_TOOLKIT */
171#ifdef HAVE_X11 259#ifdef HAVE_X11
172 { 260 {
173 Window child; 261 Window child;
@@ -194,7 +282,7 @@ With this form of menu, the return value is VALUE from the chosen item.")
194 XMenu_ypos += win_y; 282 XMenu_ypos += win_y;
195 } 283 }
196 } 284 }
197#endif 285#endif /* HAVE_X11 */
198 286
199 XMenu_xpos += FONT_WIDTH (f->display.x->font) * XINT (x); 287 XMenu_xpos += FONT_WIDTH (f->display.x->font) * XINT (x);
200 XMenu_ypos += FONT_HEIGHT (f->display.x->font) * XINT (y); 288 XMenu_ypos += FONT_HEIGHT (f->display.x->font) * XINT (y);
@@ -202,6 +290,7 @@ With this form of menu, the return value is VALUE from the chosen item.")
202 XMenu_xpos += f->display.x->left_pos; 290 XMenu_xpos += f->display.x->left_pos;
203 XMenu_ypos += f->display.x->top_pos; 291 XMenu_ypos += f->display.x->top_pos;
204 292
293
205 keymap = Fkeymapp (menu); 294 keymap = Fkeymapp (menu);
206 tem = Qnil; 295 tem = Qnil;
207 if (XTYPE (menu) == Lisp_Cons) 296 if (XTYPE (menu) == Lisp_Cons)
@@ -275,6 +364,7 @@ With this form of menu, the return value is VALUE from the chosen item.")
275 fprintf (stderr, " Item %d %s\n", j, names[i][j]); 364 fprintf (stderr, " Item %d %s\n", j, names[i][j]);
276 } 365 }
277#endif 366#endif
367
278 BLOCK_INPUT; 368 BLOCK_INPUT;
279 { 369 {
280 Window root; 370 Window root;
@@ -296,7 +386,6 @@ With this form of menu, the return value is VALUE from the chosen item.")
296 &dummy_window)) 386 &dummy_window))
297 /* But XGetGeometry said root was the root window of f's screen! */ 387 /* But XGetGeometry said root was the root window of f's screen! */
298 abort (); 388 abort ();
299
300 selection = xmenu_show (root, XMenu_xpos, XMenu_ypos, names, enables, 389 selection = xmenu_show (root, XMenu_xpos, XMenu_ypos, names, enables,
301 menus, prefixes, items, number_of_panes, obj_list, 390 menus, prefixes, items, number_of_panes, obj_list,
302 title, &error_name); 391 title, &error_name);
@@ -326,14 +415,566 @@ With this form of menu, the return value is VALUE from the chosen item.")
326 /* free (title); */ 415 /* free (title); */
327 if (error_name) error (error_name); 416 if (error_name) error (error_name);
328 return XMenu_return; 417 return XMenu_return;
418#endif /* not USE_X_TOOLKIT */
419}
420
421#ifdef USE_X_TOOLKIT
422
423static void
424dispatch_dummy_expose (w, x, y)
425 Widget w;
426 int x;
427 int y;
428{
429 XExposeEvent dummy;
430
431 dummy.type = Expose;
432 dummy.window = XtWindow (w);
433 dummy.count = 0;
434 dummy.serial = 0;
435 dummy.send_event = 0;
436 dummy.display = XtDisplay (w);
437 dummy.x = x;
438 dummy.y = y;
439
440 XtDispatchEvent (&dummy);
441}
442
443static int
444string_width (mw, s)
445 XlwMenuWidget mw;
446 char* s;
447{
448 XCharStruct xcs;
449 int drop;
450
451 XTextExtents (mw->menu.font, s, strlen (s), &drop, &drop, &drop, &xcs);
452 return xcs.width;
329} 453}
330 454
455static int
456event_is_in_menu_item (mw, event, name, string_w)
457 XlwMenuWidget mw;
458 struct input_event *event;
459 char *name;
460 int *string_w;
461{
462 *string_w += string_width (mw, name)
463 + 2 * (mw->menu.horizontal_spacing + mw->menu.shadow_thickness);
464 return (XINT (event->x) < *string_w);
465}
466
467
468Lisp_Object
469map_event_to_object (event, f)
470 struct input_event *event;
471 FRAME_PTR f;
472{
473 int i,j, string_w;
474 window_state* ws;
475 XlwMenuWidget mw = (XlwMenuWidget) f->display.x->menubar_widget;
476 widget_value *val;
477
478
479 string_w = 0;
480 /* Find the window */
481 for (val = mw->menu.old_stack [0]->contents; val; val = val->next)
482 {
483 ws = &mw->menu.windows [0];
484 if (ws && event_is_in_menu_item (mw, event, val->name, &string_w))
485 {
486 Lisp_Object items;
487 items = FRAME_MENU_BAR_ITEMS (f);
488 for (; CONSP (items); items = XCONS (items)->cdr)
489 if (!strcmp (val->name,
490 XSTRING (Fcar (Fcdr (Fcar (items))))->data))
491 return items;
492 }
493 }
494 return Qnil;
495}
496
497static widget_value *
498set_menu_items (menu, prefixes, panes, names, enables, menus,
499 items, number_of_panes, obj_list, title, error_name)
500 Lisp_Object menu;
501 Lisp_Object **prefixes;
502 int *panes;
503 char ***names[];
504 int ***enables;
505 char ***menus;
506 int **items;
507 int *number_of_panes;
508 Lisp_Object ***obj_list;
509 char **title;
510 char **error_name;
511{
512 Lisp_Object keymap, tem;
513 Lisp_Object ltitle, selection;
514 int i, j;
515 widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
516 int last, selidx, lpane, status;
517 int lines, sofar;
518
519 keymap = Fkeymapp (menu);
520 tem = Qnil;
521
522 if (XTYPE (menu) == Lisp_Cons)
523 tem = Fkeymapp (Fcar (menu));
524 if (!NILP (keymap))
525 {
526 /* We were given a keymap. Extract menu info from the keymap. */
527 Lisp_Object prompt;
528 keymap = get_keymap (menu);
529
530 /* Search for a string appearing directly as an element of the keymap.
531 That string is the title of the menu. */
532 prompt = map_prompt (keymap);
533 if (!NILP (prompt))
534 *title = (char *) XSTRING (prompt)->data;
535
536 /* Extract the detailed info to make one pane. */
537 *number_of_panes = keymap_panes (obj_list, menus, names, enables,
538 items, prefixes, menu, 1);
539 /* The menu title seems to be ignored,
540 so put it in the pane title. */
541 if ((*menus)[0] == 0)
542 (*menus)[0] = *title;
543 }
544 else if (!NILP (tem))
545 {
546 /* We were given a list of keymaps. */
547 Lisp_Object prompt;
548 int nmaps = XFASTINT (Flength (menu));
549 Lisp_Object *maps
550 = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
551 int i;
552 *title = 0;
553
554 /* The first keymap that has a prompt string
555 supplies the menu title. */
556 for (tem = menu, i = 0; XTYPE (tem) == Lisp_Cons; tem = Fcdr (tem))
557 {
558 maps[i++] = keymap = get_keymap (Fcar (tem));
559
560 prompt = map_prompt (keymap);
561 if (*title == 0 && !NILP (prompt))
562 *title = (char *) XSTRING (prompt)->data;
563 }
564
565 /* Extract the detailed info to make one pane. */
566 *number_of_panes = keymap_panes (obj_list, menus, names, enables,
567 items, prefixes, maps, nmaps);
568 /* The menu title seems to be ignored,
569 so put it in the pane title. */
570 if ((*menus)[0] == 0)
571 (*menus)[0] = *title;
572 }
573 else
574 {
575 /* We were given an old-fashioned menu. */
576 ltitle = Fcar (menu);
577 CHECK_STRING (ltitle, 1);
578 *title = (char *) XSTRING (ltitle)->data;
579 *prefixes = 0;
580 *number_of_panes = list_of_panes (obj_list, menus, names, enables,
581 items, Fcdr (menu));
582 }
583
584 *error_name = 0;
585 if (*number_of_panes == 0)
586 return 0;
587
588 *error_name = (char *) 0; /* Initialize error pointer to null */
589
590 wv = malloc_widget_value ();
591 wv->name = "menu";
592 wv->value = 0;
593 wv->enabled = 1;
594 first_wv = wv;
595
596 for (*panes = 0, lines = 0; *panes < *number_of_panes;
597 lines += (*items)[*panes], (*panes)++)
598 ;
599 /* datap = (struct indices *) xmalloc (lines * sizeof (struct indices)); */
600 /* datap = (char *) xmalloc (lines * sizeof (char));
601 datap_save = datap;*/
602
603 for (*panes = 0, sofar = 0; *panes < *number_of_panes;
604 sofar += (*items)[*panes], (*panes)++)
605 {
606 if (strcmp((*menus)[*panes], ""))
607 {
608 wv = malloc_widget_value ();
609 if (save_wv)
610 save_wv->next = wv;
611 else
612 first_wv->contents = wv;
613 wv->name = (*menus)[*panes];
614 wv->value = 0;
615 wv->enabled = 1;
616 }
617 prev_wv = 0;
618 save_wv = wv;
619
620 for (selidx = 0; selidx < (*items)[*panes]; selidx++)
621 {
622 wv = malloc_widget_value ();
623 if (prev_wv)
624 prev_wv->next = wv;
625 else
626 save_wv->contents = wv;
627 wv->name = (*names)[*panes][selidx];
628 wv->value = 0;
629 selection = (*obj_list)[*panes][selidx];
630 if (*prefixes != 0)
631 {
632 selection = Fcons (selection, Qnil);
633 if (!NILP ((*prefixes)[*panes]))
634 selection = Fcons ((*prefixes)[*panes], selection);
635 }
636 wv->call_data = LISP_TO_VOID(selection);
637 wv->enabled = (*enables)[*panes][selidx];
638 prev_wv = wv;
639 }
640 }
641
642 return (first_wv);
643}
644
645static void
646free_menu_items (names, enables, menus, items, number_of_panes,
647 obj_list, title, error_name)
648 char **names[];
649 int *enables[];
650 char **menus;
651 int *items;
652 int number_of_panes;
653 Lisp_Object **obj_list;
654 char *title;
655 char *error_name;
656{
657 int i;
658 /* now free up the strings */
659 for (i = 0; i < number_of_panes; i++)
660 {
661 xfree (names[i]);
662 xfree (enables[i]);
663 xfree (obj_list[i]);
664 }
665 xfree (menus);
666 xfree (obj_list);
667 xfree (names);
668 xfree (enables);
669 xfree (items);
670 /* free (title); */
671 if (error_name) error (error_name);
672
673}
674
675static Lisp_Object menu_item_selection;
676
677static void
678popup_selection_callback (widget, id, client_data)
679 Widget widget;
680 LWLIB_ID id;
681 XtPointer client_data;
682{
683#if 0
684 last_popup_selection_callback_id = id;
685 menubar_selection_callback (widget, id, client_data);
686 /* lw_destroy_all_widgets() will be called from popup_down_callback() */
687#endif
688 VOID_TO_LISP (menu_item_selection, client_data);
689}
690
691static void
692popup_down_callback (widget, id, client_data)
693 Widget widget;
694 LWLIB_ID id;
695 XtPointer client_data;
696{
697#if 0
698 if (popup_menu_up_p == 0) abort ();
699 popup_menu_up_p--;
700 /* if this isn't called immediately after the selection callback, then
701 there wasn't a menu selection. */
702 if (id != last_popup_selection_callback_id)
703 menubar_selection_callback (widget, id, (XtPointer) -1);
704#endif
705 BLOCK_INPUT;
706 lw_destroy_all_widgets (id);
707 UNBLOCK_INPUT;
708/* ungcpro_popup_callbacks (make_number (id)); */
709}
710
711/* This recursively calls free_widget_value() on the tree of widgets.
712 It must free all data that was malloc'ed for these widget_values.
713 Currently, emacs only allocates new storage for the `key' slot.
714 All other slots are pointers into the data of Lisp_Strings, and
715 must be left alone.
716 */
717void
718free_menubar_widget_value_tree (wv)
719 widget_value *wv;
720{
721 if (! wv) return;
722 if (wv->key) xfree (wv->key);
723
724 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
725
726 if (wv->contents && (wv->contents != (widget_value*)1))
727 {
728 free_menubar_widget_value_tree (wv->contents);
729 wv->contents = (widget_value *) 0xDEADBEEF;
730 }
731 if (wv->next)
732 {
733 free_menubar_widget_value_tree (wv->next);
734 wv->next = (widget_value *) 0xDEADBEEF;
735 }
736 BLOCK_INPUT;
737 free_widget_value (wv);
738 UNBLOCK_INPUT;
739}
740
741static void
742update_one_frame_psheets (f)
743 FRAME_PTR f;
744{
745 struct x_display *x = f->display.x;
746
747 int menubar_changed;
748
749 menubar_changed = (x->menubar_widget
750 && !XtIsManaged (x->menubar_widget));
751
752 if (! (menubar_changed))
753 return;
754
755 BLOCK_INPUT;
756 XawPanedSetRefigureMode (x->column_widget, 0);
757
758 /* the order in which children are managed is the top to
759 bottom order in which they are displayed in the paned window.
760 First, remove the text-area widget.
761 */
762 XtUnmanageChild (x->edit_widget);
763
764 /* remove the menubar that is there now, and put up the menubar that
765 should be there.
766 */
767 if (menubar_changed)
768 {
769 XtManageChild (x->menubar_widget);
770 XtMapWidget (x->menubar_widget);
771 XtVaSetValues (x->menubar_widget, XtNmappedWhenManaged, 1, 0);
772 }
773
774
775 /* Re-manage the text-area widget */
776 XtManageChild (x->edit_widget);
777
778 /* and now thrash the sizes */
779 XawPanedSetRefigureMode (x->column_widget, 1);
780 UNBLOCK_INPUT;
781}
782
783void
784set_frame_menubar (f)
785 FRAME_PTR f;
786{
787 Widget menubar_widget = f->display.x->menubar_widget;
788 int id = (int) f;
789 Lisp_Object tail;
790 widget_value *wv, *save_wv, *first_wv, *prev_wv = 0;
791
792 BLOCK_INPUT;
793
794 wv = malloc_widget_value ();
795 wv->name = "menubar";
796 wv->value = 0;
797 wv->enabled = 1;
798 save_wv = first_wv = wv;
799
800
801 for (tail = FRAME_MENU_BAR_ITEMS (f); CONSP (tail); tail = XCONS (tail)->cdr)
802 {
803 Lisp_Object string;
804
805 string = Fcar (Fcdr (Fcar (tail)));
806
807 wv = malloc_widget_value ();
808 if (prev_wv)
809 prev_wv->next = wv;
810 else
811 save_wv->contents = wv;
812 wv->name = XSTRING (string)->data;
813 wv->value = 0;
814 wv->enabled = 1;
815 prev_wv = wv;
816 }
817
818 if (menubar_widget)
819 lw_modify_all_widgets (id, first_wv, False);
820 else
821 {
822 menubar_widget = lw_create_widget ("menubar", "menubar",
823 id, first_wv,
824 f->display.x->column_widget,
825 0, 0,
826 0, 0);
827 f->display.x->menubar_widget = menubar_widget;
828 XtVaSetValues (menubar_widget,
829 XtNshowGrip, 0,
830 XtNresizeToPreferred, 1,
831 XtNallowResize, 1,
832 0);
833 }
834
835 free_menubar_widget_value_tree (first_wv);
836
837 update_one_frame_psheets (f);
838
839 UNBLOCK_INPUT;
840}
841#endif /* USE_X_TOOLKIT */
842
331struct indices { 843struct indices {
332 int pane; 844 int pane;
333 int line; 845 int line;
334}; 846};
335 847
848extern void process_expose_from_menu ();
849
850#ifdef USE_X_TOOLKIT
851extern XtAppContext Xt_app_con;
852
336Lisp_Object 853Lisp_Object
854xmenu_show (f, val, x, y, menubarp, vw)
855 FRAME_PTR f;
856 widget_value *val;
857 int x;
858 int y;
859 int menubarp;
860 widget_value *vw;
861{
862 int menu_id, id = (int)f;
863 Lisp_Object selection;
864 Widget menu;
865
866 /*
867 * Define and allocate a foreign event queue to hold events
868 * that don't belong to XMenu. These events are later restored
869 * to the X event queue.
870 */
871 typedef struct _xmeventque
872 {
873 XEvent event;
874 struct _xmeventque *next;
875 } XMEventQue;
876
877 XMEventQue *feq = NULL; /* Foreign event queue. */
878 XMEventQue *feq_tmp; /* Foreign event queue temporary. */
879
880 BLOCK_INPUT;
881 menu_id = ++popup_id_tick;
882 menu = lw_create_widget ("popup", val->name, menu_id, val,
883 f->display.x->widget, 1, 0,
884 popup_selection_callback, popup_down_callback);
885 free_menubar_widget_value_tree (val);
886
887 /* reset the selection */
888 menu_item_selection = Qnil;
889
890 {
891 XButtonPressedEvent dummy;
892 XlwMenuWidget mw;
893
894 mw = ((XlwMenuWidget)
895 ((CompositeWidget)menu)->composite.children[0]);
896
897 dummy.type = ButtonPress;
898 dummy.serial = 0;
899 dummy.send_event = 0;
900 dummy.display = XtDisplay (menu);
901 dummy.window = XtWindow (XtParent (menu));
902 dummy.time = CurrentTime;
903 dummy.button = 0;
904 dummy.x_root = x;
905 dummy.y_root = y;
906
907 if (menubarp)
908 {
909#if 0
910 /* we are in the menubar */
911 XtUnmapWidget (f->display.x->menubar_widget);
912 vw->call_data = (XtPointer) 1;
913 XtMapWidget (f->display.x->menubar_widget);
914#else
915 vw->call_data = (XtPointer) 1;
916 dispatch_dummy_expose (f->display.x->menubar_widget, x, y);
917#endif
918 }
919
920
921 /* We activate directly the lucid implementation */
922 pop_up_menu (mw, &dummy);
923 }
924
925 /* Enters XEvent loop */
926 while (1)
927 {
928
929 XEvent event;
930 XtAppNextEvent (Xt_app_con, &event);
931 if (event.type == ButtonRelease)
932 {
933 XtDispatchEvent (&event);
934 break;
935 }
936 else
937 if (event.type == Expose)
938 process_expose_from_menu (event);
939 XtDispatchEvent (&event);
940 feq_tmp = (XMEventQue *) malloc (sizeof (XMEventQue));
941
942 if (feq_tmp == NULL)
943 return(Qnil);
944
945 feq_tmp->event = event;
946 feq_tmp->next = feq;
947 feq = feq_tmp;
948 }
949
950 if (menubarp)
951 {
952#if 1
953 XtUnmapWidget (f->display.x->menubar_widget);
954 vw->call_data = (XtPointer) 0;
955 XtMapWidget (f->display.x->menubar_widget);
956#else
957 vw->call_data = (XtPointer) 0;
958 dispatch_dummy_expose (f->display.x->menubar_widget, 0, 0);
959 XFlushQueue ();
960#endif
961 }
962
963 /* Return any foreign events that were queued to the X event queue. */
964 while (feq != NULL)
965 {
966 feq_tmp = feq;
967 XPutBackEvent (XDISPLAY &feq_tmp->event);
968 feq = feq_tmp->next;
969 free ((char *)feq_tmp);
970 }
971
972 UNBLOCK_INPUT;
973
974 return menu_item_selection;
975}
976
977#else /* not USE_X_TOOLKIT */
337xmenu_show (parent, startx, starty, line_list, enable_list, pane_list, 978xmenu_show (parent, startx, starty, line_list, enable_list, pane_list,
338 prefixes, line_cnt, pane_cnt, item_list, title, error) 979 prefixes, line_cnt, pane_cnt, item_list, title, error)
339 Window parent; 980 Window parent;
@@ -363,6 +1004,7 @@ xmenu_show (parent, startx, starty, line_list, enable_list, pane_list,
363 1004
364 BLOCK_INPUT; 1005 BLOCK_INPUT;
365 *error = (char *) 0; /* Initialize error pointer to null */ 1006 *error = (char *) 0; /* Initialize error pointer to null */
1007
366 GXMenu = XMenuCreate (XDISPLAY parent, "emacs"); 1008 GXMenu = XMenuCreate (XDISPLAY parent, "emacs");
367 if (GXMenu == NUL) 1009 if (GXMenu == NUL)
368 { 1010 {
@@ -370,7 +1012,7 @@ xmenu_show (parent, startx, starty, line_list, enable_list, pane_list,
370 UNBLOCK_INPUT; 1012 UNBLOCK_INPUT;
371 return (0); 1013 return (0);
372 } 1014 }
373 1015
374 for (panes = 0, lines = 0; panes < pane_cnt; 1016 for (panes = 0, lines = 0; panes < pane_cnt;
375 lines += line_cnt[panes], panes++) 1017 lines += line_cnt[panes], panes++)
376 ; 1018 ;
@@ -390,6 +1032,7 @@ xmenu_show (parent, startx, starty, line_list, enable_list, pane_list,
390 UNBLOCK_INPUT; 1032 UNBLOCK_INPUT;
391 return (0); 1033 return (0);
392 } 1034 }
1035
393 for (selidx = 0; selidx < line_cnt[panes]; selidx++) 1036 for (selidx = 0; selidx < line_cnt[panes]; selidx++)
394 { 1037 {
395 /* add the selection stuff to the menus */ 1038 /* add the selection stuff to the menus */
@@ -466,9 +1109,11 @@ xmenu_show (parent, startx, starty, line_list, enable_list, pane_list,
466 /* free (datap_save);*/ 1109 /* free (datap_save);*/
467 return (entry); 1110 return (entry);
468} 1111}
1112#endif /* not USE_X_TOOLKIT */
469 1113
470syms_of_xmenu () 1114syms_of_xmenu ()
471{ 1115{
1116 popup_id_tick = (1<<16);
472 defsubr (&Sx_popup_menu); 1117 defsubr (&Sx_popup_menu);
473} 1118}
474 1119