1 /* Menu support for GNU Emacs on the Microsoft W32 API.
2 Copyright (C) 1986, 88, 93, 94, 96, 98, 1999 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
26 #include "termhooks.h"
31 #include "blockinput.h"
36 /* This may include sys/types.h, and that somehow loses
37 if this is not done before the other system files. */
40 /* Load sys/types.h if not already loaded.
41 In some systems loading it twice is suicidal. */
43 #include <sys/types.h>
46 #include "dispextern.h"
48 #undef HAVE_MULTILINGUAL_MENU
49 #undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
51 /******************************************************************/
52 /* Definitions copied from lwlib.h */
54 typedef void * XtPointer
;
64 /* This structure is based on the one in ../lwlib/lwlib.h, modified
66 typedef struct _widget_value
70 /* value (meaning depend on widget type) */
72 /* keyboard equivalent. no implications for XtTranslations */
74 /* Help string or nil if none.
75 GC finds this string through the frame's menu_bar_vector
76 or through menu_items. */
80 /* true if selected */
82 /* The type of a button. */
83 enum button_type button_type
;
84 /* true if menu title */
87 /* true if was edited (maintained by get_value) */
89 /* true if has changed (maintained by lw library) */
91 /* true if this widget itself has changed,
92 but not counting the other widgets found in the `next' field. */
93 change_type this_one_change
;
95 /* Contents of the sub-widgets, also selected slot for checkbox */
96 struct _widget_value
* contents
;
97 /* data passed to callback */
99 /* next one in the list */
100 struct _widget_value
* next
;
102 /* slot for the toolkit dependent part. Always initialize to NULL. */
104 /* tell us if we should free the toolkit data slot when freeing the
105 widget_value itself. */
106 Boolean free_toolkit_data
;
108 /* we resource the widget_value structures; this points to the next
109 one on the free list if this one has been deallocated.
111 struct _widget_value
*free_list
;
115 /* LocalAlloc/Free is a reasonably good allocator. */
116 #define malloc_widget_value() (void*)LocalAlloc (LMEM_ZEROINIT, sizeof (widget_value))
117 #define free_widget_value(wv) LocalFree (wv)
119 /******************************************************************/
126 static HMENU current_popup_menu
;
128 FARPROC get_menu_item_info
;
129 FARPROC set_menu_item_info
;
131 Lisp_Object Vmenu_updating_frame
;
133 Lisp_Object Qdebug_on_next_call
;
135 extern Lisp_Object Qmenu_bar
;
136 extern Lisp_Object Qmouse_click
, Qevent_kind
;
138 extern Lisp_Object QCtoggle
, QCradio
;
140 extern Lisp_Object Voverriding_local_map
;
141 extern Lisp_Object Voverriding_local_map_menu_flag
;
143 extern Lisp_Object Qoverriding_local_map
, Qoverriding_terminal_local_map
;
145 extern Lisp_Object Qmenu_bar_update_hook
;
147 void set_frame_menubar ();
149 static void push_menu_item
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
,
150 Lisp_Object
, Lisp_Object
, Lisp_Object
,
151 Lisp_Object
, Lisp_Object
));
153 static Lisp_Object
w32_dialog_show ();
155 static Lisp_Object
w32_menu_show ();
157 static void keymap_panes ();
158 static void single_keymap_panes ();
159 static void single_menu_item ();
160 static void list_of_panes ();
161 static void list_of_items ();
162 void w32_free_menu_strings (HWND
);
164 /* This holds a Lisp vector that holds the results of decoding
165 the keymaps or alist-of-alists that specify a menu.
167 It describes the panes and items within the panes.
169 Each pane is described by 3 elements in the vector:
170 t, the pane name, the pane's prefix key.
171 Then follow the pane's items, with 5 elements per item:
172 the item string, the enable flag, the item's value,
173 the definition, and the equivalent keyboard key's description string.
175 In some cases, multiple levels of menus may be described.
176 A single vector slot containing nil indicates the start of a submenu.
177 A single vector slot containing lambda indicates the end of a submenu.
178 The submenu follows a menu item which is the way to reach the submenu.
180 A single vector slot containing quote indicates that the
181 following items should appear on the right of a dialog box.
183 Using a Lisp vector to hold this information while we decode it
184 takes care of protecting all the data from GC. */
186 #define MENU_ITEMS_PANE_NAME 1
187 #define MENU_ITEMS_PANE_PREFIX 2
188 #define MENU_ITEMS_PANE_LENGTH 3
192 MENU_ITEMS_ITEM_NAME
= 0,
193 MENU_ITEMS_ITEM_ENABLE
,
194 MENU_ITEMS_ITEM_VALUE
,
195 MENU_ITEMS_ITEM_EQUIV_KEY
,
196 MENU_ITEMS_ITEM_DEFINITION
,
197 MENU_ITEMS_ITEM_TYPE
,
198 MENU_ITEMS_ITEM_SELECTED
,
199 MENU_ITEMS_ITEM_HELP
,
200 MENU_ITEMS_ITEM_LENGTH
203 static Lisp_Object menu_items
;
205 /* Number of slots currently allocated in menu_items. */
206 static int menu_items_allocated
;
208 /* This is the index in menu_items of the first empty slot. */
209 static int menu_items_used
;
211 /* The number of panes currently recorded in menu_items,
212 excluding those within submenus. */
213 static int menu_items_n_panes
;
215 /* Current depth within submenus. */
216 static int menu_items_submenu_depth
;
218 /* Flag which when set indicates a dialog or menu has been posted by
219 Xt on behalf of one of the widget sets. */
220 static int popup_activated_flag
;
222 static int next_menubar_widget_id
;
224 /* This is set nonzero after the user activates the menu bar, and set
225 to zero again after the menu bars are redisplayed by prepare_menu_bar.
226 While it is nonzero, all calls to set_frame_menubar go deep.
228 I don't understand why this is needed, but it does seem to be
229 needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
231 int pending_menu_activation
;
234 /* Return the frame whose ->output_data.w32->menubar_widget equals
237 static struct frame
*
238 menubar_id_to_frame (id
)
241 Lisp_Object tail
, frame
;
244 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
247 if (!GC_FRAMEP (frame
))
250 if (!FRAME_WINDOW_P (f
))
252 if (f
->output_data
.w32
->menubar_widget
== id
)
258 /* Initialize the menu_items structure if we haven't already done so.
259 Also mark it as currently empty. */
264 if (NILP (menu_items
))
266 menu_items_allocated
= 60;
267 menu_items
= Fmake_vector (make_number (menu_items_allocated
), Qnil
);
271 menu_items_n_panes
= 0;
272 menu_items_submenu_depth
= 0;
275 /* Call at the end of generating the data in menu_items.
276 This fills in the number of items in the last pane. */
283 /* Call when finished using the data for the current menu
287 discard_menu_items ()
289 /* Free the structure if it is especially large.
290 Otherwise, hold on to it, to save time. */
291 if (menu_items_allocated
> 200)
294 menu_items_allocated
= 0;
298 /* Make the menu_items vector twice as large. */
304 int old_size
= menu_items_allocated
;
307 menu_items_allocated
*= 2;
308 menu_items
= Fmake_vector (make_number (menu_items_allocated
), Qnil
);
309 bcopy (XVECTOR (old
)->contents
, XVECTOR (menu_items
)->contents
,
310 old_size
* sizeof (Lisp_Object
));
313 /* Begin a submenu. */
316 push_submenu_start ()
318 if (menu_items_used
+ 1 > menu_items_allocated
)
321 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qnil
;
322 menu_items_submenu_depth
++;
330 if (menu_items_used
+ 1 > menu_items_allocated
)
333 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qlambda
;
334 menu_items_submenu_depth
--;
337 /* Indicate boundary between left and right. */
340 push_left_right_boundary ()
342 if (menu_items_used
+ 1 > menu_items_allocated
)
345 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qquote
;
348 /* Start a new menu pane in menu_items.
349 NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
352 push_menu_pane (name
, prefix_vec
)
353 Lisp_Object name
, prefix_vec
;
355 if (menu_items_used
+ MENU_ITEMS_PANE_LENGTH
> menu_items_allocated
)
358 if (menu_items_submenu_depth
== 0)
359 menu_items_n_panes
++;
360 XVECTOR (menu_items
)->contents
[menu_items_used
++] = Qt
;
361 XVECTOR (menu_items
)->contents
[menu_items_used
++] = name
;
362 XVECTOR (menu_items
)->contents
[menu_items_used
++] = prefix_vec
;
365 /* Push one menu item into the current pane. NAME is the string to
366 display. ENABLE if non-nil means this item can be selected. KEY
367 is the key generated by choosing this item, or nil if this item
368 doesn't really have a definition. DEF is the definition of this
369 item. EQUIV is the textual description of the keyboard equivalent
370 for this item (or nil if none). TYPE is the type of this menu
371 item, one of nil, `toggle' or `radio'. */
374 push_menu_item (name
, enable
, key
, def
, equiv
, type
, selected
, help
)
375 Lisp_Object name
, enable
, key
, def
, equiv
, type
, selected
, help
;
377 if (menu_items_used
+ MENU_ITEMS_ITEM_LENGTH
> menu_items_allocated
)
380 XVECTOR (menu_items
)->contents
[menu_items_used
++] = name
;
381 XVECTOR (menu_items
)->contents
[menu_items_used
++] = enable
;
382 XVECTOR (menu_items
)->contents
[menu_items_used
++] = key
;
383 XVECTOR (menu_items
)->contents
[menu_items_used
++] = equiv
;
384 XVECTOR (menu_items
)->contents
[menu_items_used
++] = def
;
385 XVECTOR (menu_items
)->contents
[menu_items_used
++] = type
;
386 XVECTOR (menu_items
)->contents
[menu_items_used
++] = selected
;
387 XVECTOR (menu_items
)->contents
[menu_items_used
++] = help
;
390 /* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
391 and generate menu panes for them in menu_items.
392 If NOTREAL is nonzero,
393 don't bother really computing whether an item is enabled. */
396 keymap_panes (keymaps
, nmaps
, notreal
)
397 Lisp_Object
*keymaps
;
405 /* Loop over the given keymaps, making a pane for each map.
406 But don't make a pane that is empty--ignore that map instead.
407 P is the number of panes we have made so far. */
408 for (mapno
= 0; mapno
< nmaps
; mapno
++)
409 single_keymap_panes (keymaps
[mapno
],
410 Fkeymap_prompt (keymaps
[mapno
]), Qnil
, notreal
, 10);
412 finish_menu_items ();
415 /* This is a recursive subroutine of keymap_panes.
416 It handles one keymap, KEYMAP.
417 The other arguments are passed along
418 or point to local variables of the previous function.
419 If NOTREAL is nonzero, only check for equivalent key bindings, don't
420 evaluate expressions in menu items and don't make any menu.
422 If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
425 single_keymap_panes (keymap
, pane_name
, prefix
, notreal
, maxdepth
)
427 Lisp_Object pane_name
;
432 Lisp_Object pending_maps
= Qnil
;
433 Lisp_Object tail
, item
;
434 struct gcpro gcpro1
, gcpro2
;
439 push_menu_pane (pane_name
, prefix
);
441 for (tail
= keymap
; CONSP (tail
); tail
= XCDR (tail
))
443 GCPRO2 (keymap
, pending_maps
);
444 /* Look at each key binding, and if it is a menu item add it
448 single_menu_item (XCAR (item
), XCDR (item
),
449 &pending_maps
, notreal
, maxdepth
);
450 else if (VECTORP (item
))
452 /* Loop over the char values represented in the vector. */
453 int len
= XVECTOR (item
)->size
;
455 for (c
= 0; c
< len
; c
++)
457 Lisp_Object character
;
458 XSETFASTINT (character
, c
);
459 single_menu_item (character
, XVECTOR (item
)->contents
[c
],
460 &pending_maps
, notreal
, maxdepth
);
466 /* Process now any submenus which want to be panes at this level. */
467 while (!NILP (pending_maps
))
469 Lisp_Object elt
, eltcdr
, string
;
470 elt
= Fcar (pending_maps
);
472 string
= XCAR (eltcdr
);
473 /* We no longer discard the @ from the beginning of the string here.
474 Instead, we do this in w32_menu_show. */
475 single_keymap_panes (Fcar (elt
), string
,
476 XCDR (eltcdr
), notreal
, maxdepth
- 1);
477 pending_maps
= Fcdr (pending_maps
);
481 /* This is a subroutine of single_keymap_panes that handles one
483 KEY is a key in a keymap and ITEM is its binding.
484 PENDING_MAPS_PTR points to a list of keymaps waiting to be made into
486 If NOTREAL is nonzero, only check for equivalent key bindings, don't
487 evaluate expressions in menu items and don't make any menu.
488 If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
491 single_menu_item (key
, item
, pending_maps_ptr
, notreal
, maxdepth
)
492 Lisp_Object key
, item
;
493 Lisp_Object
*pending_maps_ptr
;
494 int maxdepth
, notreal
;
496 Lisp_Object map
, item_string
, enabled
;
497 struct gcpro gcpro1
, gcpro2
;
500 /* Parse the menu item and leave the result in item_properties. */
502 res
= parse_menu_item (item
, notreal
, 0);
505 return; /* Not a menu item. */
507 map
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_MAP
];
511 /* We don't want to make a menu, just traverse the keymaps to
512 precompute equivalent key bindings. */
514 single_keymap_panes (map
, Qnil
, key
, 1, maxdepth
- 1);
518 enabled
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_ENABLE
];
519 item_string
= XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_NAME
];
521 if (!NILP (map
) && XSTRING (item_string
)->data
[0] == '@')
524 /* An enabled separate pane. Remember this to handle it later. */
525 *pending_maps_ptr
= Fcons (Fcons (map
, Fcons (item_string
, key
)),
530 push_menu_item (item_string
, enabled
, key
,
531 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_DEF
],
532 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_KEYEQ
],
533 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_TYPE
],
534 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_SELECTED
],
535 XVECTOR (item_properties
)->contents
[ITEM_PROPERTY_HELP
]);
537 /* Display a submenu using the toolkit. */
538 if (! (NILP (map
) || NILP (enabled
)))
540 push_submenu_start ();
541 single_keymap_panes (map
, Qnil
, key
, 0, maxdepth
- 1);
546 /* Push all the panes and items of a menu described by the
547 alist-of-alists MENU.
548 This handles old-fashioned calls to x-popup-menu. */
558 for (tail
= menu
; !NILP (tail
); tail
= Fcdr (tail
))
560 Lisp_Object elt
, pane_name
, pane_data
;
562 pane_name
= Fcar (elt
);
563 CHECK_STRING (pane_name
);
564 push_menu_pane (pane_name
, Qnil
);
565 pane_data
= Fcdr (elt
);
566 CHECK_CONS (pane_data
);
567 list_of_items (pane_data
);
570 finish_menu_items ();
573 /* Push the items in a single pane defined by the alist PANE. */
579 Lisp_Object tail
, item
, item1
;
581 for (tail
= pane
; !NILP (tail
); tail
= Fcdr (tail
))
585 push_menu_item (item
, Qnil
, Qnil
, Qt
, Qnil
, Qnil
, Qnil
, Qnil
);
586 else if (NILP (item
))
587 push_left_right_boundary ();
592 CHECK_STRING (item1
);
593 push_menu_item (item1
, Qt
, Fcdr (item
), Qt
, Qnil
, Qnil
, Qnil
, Qnil
);
598 DEFUN ("x-popup-menu", Fx_popup_menu
, Sx_popup_menu
, 2, 2, 0,
599 doc
: /* Pop up a deck-of-cards menu and return user's selection.
600 POSITION is a position specification. This is either a mouse button
601 event or a list ((XOFFSET YOFFSET) WINDOW) where XOFFSET and YOFFSET
602 are positions in pixels from the top left corner of WINDOW's frame
603 \(WINDOW may be a frame object instead of a window). This controls the
604 position of the center of the first line in the first pane of the
605 menu, not the top left of the menu as a whole. If POSITION is t, it
606 means to use the current mouse position.
608 MENU is a specifier for a menu. For the simplest case, MENU is a keymap.
609 The menu items come from key bindings that have a menu string as well as
610 a definition; actually, the \"definition\" in such a key binding looks like
611 \(STRING . REAL-DEFINITION). To give the menu a title, put a string into
612 the keymap as a top-level element.
614 If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.
615 Otherwise, REAL-DEFINITION should be a valid key binding definition.
617 You can also use a list of keymaps as MENU. Then each keymap makes a
618 separate pane. When MENU is a keymap or a list of keymaps, the return
619 value is a list of events.
621 Alternatively, you can specify a menu of multiple panes with a list of
622 the form (TITLE PANE1 PANE2...), where each pane is a list of
623 form (TITLE ITEM1 ITEM2...).
624 Each ITEM is normally a cons cell (STRING . VALUE); but a string can
625 appear as an item--that makes a nonselectable line in the menu.
626 With this form of menu, the return value is VALUE from the chosen item.
628 If POSITION is nil, don't display the menu at all, just precalculate the
629 cached information about equivalent key sequences. */)
631 Lisp_Object position
, menu
;
633 Lisp_Object keymap
, tem
;
634 int xpos
= 0, ypos
= 0;
637 Lisp_Object selection
;
639 Lisp_Object x
, y
, window
;
645 if (! NILP (position
))
649 /* Decode the first argument: find the window and the coordinates. */
650 if (EQ (position
, Qt
)
651 || (CONSP (position
) && (EQ (XCAR (position
), Qmenu_bar
)
652 || EQ (XCAR (position
), Qtool_bar
))))
654 /* Use the mouse's current position. */
655 FRAME_PTR new_f
= SELECTED_FRAME ();
656 Lisp_Object bar_window
;
657 enum scroll_bar_part part
;
660 if (mouse_position_hook
)
661 (*mouse_position_hook
) (&new_f
, 1, &bar_window
,
662 &part
, &x
, &y
, &time
);
664 XSETFRAME (window
, new_f
);
667 window
= selected_window
;
674 tem
= Fcar (position
);
677 window
= Fcar (Fcdr (position
));
679 y
= Fcar (Fcdr (tem
));
684 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
685 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
686 tem
= Fcar (Fcdr (Fcdr (tem
))); /* POSN_WINDOW_POSN (tem) */
695 /* Decode where to put the menu. */
703 else if (WINDOWP (window
))
705 CHECK_LIVE_WINDOW (window
);
706 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
708 xpos
= (FONT_WIDTH (FRAME_FONT (f
))
709 * XFASTINT (XWINDOW (window
)->left
));
710 ypos
= (FRAME_LINE_HEIGHT (f
)
711 * XFASTINT (XWINDOW (window
)->top
));
714 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
715 but I don't want to make one now. */
716 CHECK_WINDOW (window
);
721 XSETFRAME (Vmenu_updating_frame
, f
);
723 Vmenu_updating_frame
= Qnil
;
724 #endif /* HAVE_MENUS */
729 /* Decode the menu items from what was specified. */
731 keymap
= get_keymap (menu
, 0, 0);
734 /* We were given a keymap. Extract menu info from the keymap. */
737 /* Extract the detailed info to make one pane. */
738 keymap_panes (&menu
, 1, NILP (position
));
740 /* Search for a string appearing directly as an element of the keymap.
741 That string is the title of the menu. */
742 prompt
= Fkeymap_prompt (keymap
);
743 if (NILP (title
) && !NILP (prompt
))
746 /* Make that be the pane title of the first pane. */
747 if (!NILP (prompt
) && menu_items_n_panes
>= 0)
748 XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
] = prompt
;
752 else if (CONSP (menu
) && KEYMAPP (XCAR (menu
)))
754 /* We were given a list of keymaps. */
755 int nmaps
= XFASTINT (Flength (menu
));
757 = (Lisp_Object
*) alloca (nmaps
* sizeof (Lisp_Object
));
762 /* The first keymap that has a prompt string
763 supplies the menu title. */
764 for (tem
= menu
, i
= 0; CONSP (tem
); tem
= Fcdr (tem
))
768 maps
[i
++] = keymap
= get_keymap (Fcar (tem
), 1, 0);
770 prompt
= Fkeymap_prompt (keymap
);
771 if (NILP (title
) && !NILP (prompt
))
775 /* Extract the detailed info to make one pane. */
776 keymap_panes (maps
, nmaps
, NILP (position
));
778 /* Make the title be the pane title of the first pane. */
779 if (!NILP (title
) && menu_items_n_panes
>= 0)
780 XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
] = title
;
786 /* We were given an old-fashioned menu. */
788 CHECK_STRING (title
);
790 list_of_panes (Fcdr (menu
));
797 discard_menu_items ();
803 /* Display them in a menu. */
806 selection
= w32_menu_show (f
, xpos
, ypos
, for_click
,
807 keymaps
, title
, &error_name
);
810 discard_menu_items ();
813 #endif /* HAVE_MENUS */
815 if (error_name
) error (error_name
);
821 DEFUN ("x-popup-dialog", Fx_popup_dialog
, Sx_popup_dialog
, 2, 2, 0,
822 doc
: /* Pop up a dialog box and return user's selection.
823 POSITION specifies which frame to use.
824 This is normally a mouse button event or a window or frame.
825 If POSITION is t, it means to use the frame the mouse is on.
826 The dialog box appears in the middle of the specified frame.
828 CONTENTS specifies the alternatives to display in the dialog box.
829 It is a list of the form (TITLE ITEM1 ITEM2...).
830 Each ITEM is a cons cell (STRING . VALUE).
831 The return value is VALUE from the chosen item.
833 An ITEM may also be just a string--that makes a nonselectable item.
834 An ITEM may also be nil--that means to put all preceding items
835 on the left of the dialog box and all following items on the right.
836 \(By default, approximately half appear on each side.) */)
838 Lisp_Object position
, contents
;
845 /* Decode the first argument: find the window or frame to use. */
846 if (EQ (position
, Qt
)
847 || (CONSP (position
) && (EQ (XCAR (position
), Qmenu_bar
)
848 || EQ (XCAR (position
), Qtool_bar
))))
850 #if 0 /* Using the frame the mouse is on may not be right. */
851 /* Use the mouse's current position. */
852 FRAME_PTR new_f
= SELECTED_FRAME ();
853 Lisp_Object bar_window
;
854 enum scroll_bar_part part
;
858 (*mouse_position_hook
) (&new_f
, 1, &bar_window
, &part
, &x
, &y
, &time
);
861 XSETFRAME (window
, new_f
);
863 window
= selected_window
;
865 window
= selected_window
;
867 else if (CONSP (position
))
870 tem
= Fcar (position
);
872 window
= Fcar (Fcdr (position
));
875 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
876 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
879 else if (WINDOWP (position
) || FRAMEP (position
))
884 /* Decode where to put the menu. */
888 else if (WINDOWP (window
))
890 CHECK_LIVE_WINDOW (window
);
891 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
894 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
895 but I don't want to make one now. */
896 CHECK_WINDOW (window
);
899 /* Display a menu with these alternatives
900 in the middle of frame F. */
902 Lisp_Object x
, y
, frame
, newpos
;
903 XSETFRAME (frame
, f
);
904 XSETINT (x
, x_pixel_width (f
) / 2);
905 XSETINT (y
, x_pixel_height (f
) / 2);
906 newpos
= Fcons (Fcons (x
, Fcons (y
, Qnil
)), Fcons (frame
, Qnil
));
908 return Fx_popup_menu (newpos
,
909 Fcons (Fcar (contents
), Fcons (contents
, Qnil
)));
911 #else /* HAVE_DIALOGS */
915 Lisp_Object selection
;
917 /* Decode the dialog items from what was specified. */
918 title
= Fcar (contents
);
919 CHECK_STRING (title
);
921 list_of_panes (Fcons (contents
, Qnil
));
923 /* Display them in a dialog box. */
925 selection
= w32_dialog_show (f
, 0, title
, &error_name
);
928 discard_menu_items ();
930 if (error_name
) error (error_name
);
933 #endif /* HAVE_DIALOGS */
936 /* Activate the menu bar of frame F.
937 This is called from keyboard.c when it gets the
938 menu_bar_activate_event out of the Emacs event queue.
940 To activate the menu bar, we signal to the input thread that it can
941 return from the WM_INITMENU message, allowing the normal Windows
942 processing of the menus.
944 But first we recompute the menu bar contents (the whole tree).
946 This way we can safely execute Lisp code. */
949 x_activate_menubar (f
)
952 set_frame_menubar (f
, 0, 1);
954 /* Lock out further menubar changes while active. */
955 f
->output_data
.w32
->menubar_active
= 1;
957 /* Signal input thread to return from WM_INITMENU. */
958 complete_deferred_msg (FRAME_W32_WINDOW (f
), WM_INITMENU
, 0);
961 /* This callback is called from the menu bar pulldown menu
962 when the user makes a selection.
963 Figure out what the user chose
964 and put the appropriate events into the keyboard buffer. */
967 menubar_selection_callback (FRAME_PTR f
, void * client_data
)
969 Lisp_Object prefix
, entry
;
971 Lisp_Object
*subprefix_stack
;
972 int submenu_depth
= 0;
978 subprefix_stack
= (Lisp_Object
*) alloca (f
->menu_bar_items_used
* sizeof (Lisp_Object
));
979 vector
= f
->menu_bar_vector
;
982 while (i
< f
->menu_bar_items_used
)
984 if (EQ (XVECTOR (vector
)->contents
[i
], Qnil
))
986 subprefix_stack
[submenu_depth
++] = prefix
;
990 else if (EQ (XVECTOR (vector
)->contents
[i
], Qlambda
))
992 prefix
= subprefix_stack
[--submenu_depth
];
995 else if (EQ (XVECTOR (vector
)->contents
[i
], Qt
))
997 prefix
= XVECTOR (vector
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
998 i
+= MENU_ITEMS_PANE_LENGTH
;
1002 entry
= XVECTOR (vector
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
1003 /* The EMACS_INT cast avoids a warning. There's no problem
1004 as long as pointers have enough bits to hold small integers. */
1005 if ((int) (EMACS_INT
) client_data
== i
)
1008 struct input_event buf
;
1011 XSETFRAME (frame
, f
);
1012 buf
.kind
= MENU_BAR_EVENT
;
1013 buf
.frame_or_window
= frame
;
1015 kbd_buffer_store_event (&buf
);
1017 for (j
= 0; j
< submenu_depth
; j
++)
1018 if (!NILP (subprefix_stack
[j
]))
1020 buf
.kind
= MENU_BAR_EVENT
;
1021 buf
.frame_or_window
= frame
;
1022 buf
.arg
= subprefix_stack
[j
];
1023 kbd_buffer_store_event (&buf
);
1028 buf
.kind
= MENU_BAR_EVENT
;
1029 buf
.frame_or_window
= frame
;
1031 kbd_buffer_store_event (&buf
);
1034 buf
.kind
= MENU_BAR_EVENT
;
1035 buf
.frame_or_window
= frame
;
1037 kbd_buffer_store_event (&buf
);
1039 /* Free memory used by owner-drawn and help-echo strings. */
1040 w32_free_menu_strings (FRAME_W32_WINDOW (f
));
1041 f
->output_data
.w32
->menu_command_in_progress
= 0;
1042 f
->output_data
.w32
->menubar_active
= 0;
1045 i
+= MENU_ITEMS_ITEM_LENGTH
;
1048 /* Free memory used by owner-drawn and help-echo strings. */
1049 w32_free_menu_strings (FRAME_W32_WINDOW (f
));
1050 f
->output_data
.w32
->menu_command_in_progress
= 0;
1051 f
->output_data
.w32
->menubar_active
= 0;
1054 /* Allocate a widget_value, blocking input. */
1057 xmalloc_widget_value ()
1059 widget_value
*value
;
1062 value
= malloc_widget_value ();
1068 /* This recursively calls free_widget_value on the tree of widgets.
1069 It must free all data that was malloc'ed for these widget_values.
1070 In Emacs, many slots are pointers into the data of Lisp_Strings, and
1071 must be left alone. */
1074 free_menubar_widget_value_tree (wv
)
1079 wv
->name
= wv
->value
= wv
->key
= (char *) 0xDEADBEEF;
1081 if (wv
->contents
&& (wv
->contents
!= (widget_value
*)1))
1083 free_menubar_widget_value_tree (wv
->contents
);
1084 wv
->contents
= (widget_value
*) 0xDEADBEEF;
1088 free_menubar_widget_value_tree (wv
->next
);
1089 wv
->next
= (widget_value
*) 0xDEADBEEF;
1092 free_widget_value (wv
);
1096 /* Return a tree of widget_value structures for a menu bar item
1097 whose event type is ITEM_KEY (with string ITEM_NAME)
1098 and whose contents come from the list of keymaps MAPS. */
1100 static widget_value
*
1101 single_submenu (item_key
, item_name
, maps
)
1102 Lisp_Object item_key
, item_name
, maps
;
1104 widget_value
*wv
, *prev_wv
, *save_wv
, *first_wv
;
1106 int submenu_depth
= 0;
1109 Lisp_Object
*mapvec
;
1110 widget_value
**submenu_stack
;
1111 int previous_items
= menu_items_used
;
1112 int top_level_items
= 0;
1114 length
= Flength (maps
);
1115 len
= XINT (length
);
1117 /* Convert the list MAPS into a vector MAPVEC. */
1118 mapvec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
1119 for (i
= 0; i
< len
; i
++)
1121 mapvec
[i
] = Fcar (maps
);
1125 menu_items_n_panes
= 0;
1127 /* Loop over the given keymaps, making a pane for each map.
1128 But don't make a pane that is empty--ignore that map instead. */
1129 for (i
= 0; i
< len
; i
++)
1131 if (SYMBOLP (mapvec
[i
])
1132 || (CONSP (mapvec
[i
]) && !KEYMAPP (mapvec
[i
])))
1134 /* Here we have a command at top level in the menu bar
1135 as opposed to a submenu. */
1136 top_level_items
= 1;
1137 push_menu_pane (Qnil
, Qnil
);
1138 push_menu_item (item_name
, Qt
, item_key
, mapvec
[i
],
1139 Qnil
, Qnil
, Qnil
, Qnil
);
1142 single_keymap_panes (mapvec
[i
], item_name
, item_key
, 0, 10);
1145 /* Create a tree of widget_value objects
1146 representing the panes and their items. */
1149 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
1150 wv
= xmalloc_widget_value ();
1154 wv
->button_type
= BUTTON_TYPE_NONE
;
1160 /* Loop over all panes and items made during this call
1161 and construct a tree of widget_value objects.
1162 Ignore the panes and items made by previous calls to
1163 single_submenu, even though those are also in menu_items. */
1165 while (i
< menu_items_used
)
1167 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1169 submenu_stack
[submenu_depth
++] = save_wv
;
1174 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1177 save_wv
= submenu_stack
[--submenu_depth
];
1180 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
1181 && submenu_depth
!= 0)
1182 i
+= MENU_ITEMS_PANE_LENGTH
;
1183 /* Ignore a nil in the item list.
1184 It's meaningful only for dialog boxes. */
1185 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1187 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1189 /* Create a new pane. */
1190 Lisp_Object pane_name
, prefix
;
1193 pane_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_NAME
];
1194 prefix
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
1196 #ifndef HAVE_MULTILINGUAL_MENU
1197 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
1199 pane_name
= ENCODE_SYSTEM (pane_name
);
1200 AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
) = pane_name
;
1203 pane_string
= (NILP (pane_name
)
1204 ? "" : (char *) XSTRING (pane_name
)->data
);
1205 /* If there is just one top-level pane, put all its items directly
1206 under the top-level menu. */
1207 if (menu_items_n_panes
== 1)
1210 /* If the pane has a meaningful name,
1211 make the pane a top-level menu item
1212 with its items as a submenu beneath it. */
1213 if (strcmp (pane_string
, ""))
1215 wv
= xmalloc_widget_value ();
1219 first_wv
->contents
= wv
;
1220 wv
->name
= pane_string
;
1221 /* Ignore the @ that means "separate pane".
1222 This is a kludge, but this isn't worth more time. */
1223 if (!NILP (prefix
) && wv
->name
[0] == '@')
1227 wv
->button_type
= BUTTON_TYPE_NONE
;
1232 i
+= MENU_ITEMS_PANE_LENGTH
;
1236 /* Create a new item within current pane. */
1237 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
;
1240 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
1241 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
1242 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
1243 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
1244 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
1245 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
1246 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
1248 #ifndef HAVE_MULTILINGUAL_MENU
1249 if (STRING_MULTIBYTE (item_name
))
1251 item_name
= ENCODE_SYSTEM (item_name
);
1252 AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
) = item_name
;
1255 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
1257 descrip
= ENCODE_SYSTEM (descrip
);
1258 AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
) = descrip
;
1260 #endif /* not HAVE_MULTILINGUAL_MENU */
1262 wv
= xmalloc_widget_value ();
1266 save_wv
->contents
= wv
;
1268 wv
->name
= (char *) XSTRING (item_name
)->data
;
1269 if (!NILP (descrip
))
1270 wv
->key
= (char *) XSTRING (descrip
)->data
;
1272 /* The EMACS_INT cast avoids a warning. There's no problem
1273 as long as pointers have enough bits to hold small integers. */
1274 wv
->call_data
= (!NILP (def
) ? (void *) (EMACS_INT
) i
: 0);
1275 wv
->enabled
= !NILP (enable
);
1278 wv
->button_type
= BUTTON_TYPE_NONE
;
1279 else if (EQ (type
, QCradio
))
1280 wv
->button_type
= BUTTON_TYPE_RADIO
;
1281 else if (EQ (type
, QCtoggle
))
1282 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
1286 wv
->selected
= !NILP (selected
);
1287 if (!STRINGP (help
))
1294 i
+= MENU_ITEMS_ITEM_LENGTH
;
1298 /* If we have just one "menu item"
1299 that was originally a button, return it by itself. */
1300 if (top_level_items
&& first_wv
->contents
&& first_wv
->contents
->next
== 0)
1302 wv
= first_wv
->contents
;
1303 free_widget_value (first_wv
);
1310 /* Set the contents of the menubar widgets of frame F.
1311 The argument FIRST_TIME is currently ignored;
1312 it is set the first time this is called, from initialize_frame_menubar. */
1315 set_frame_menubar (f
, first_time
, deep_p
)
1320 HMENU menubar_widget
= f
->output_data
.w32
->menubar_widget
;
1322 widget_value
*wv
, *first_wv
, *prev_wv
= 0;
1325 /* We must not change the menubar when actually in use. */
1326 if (f
->output_data
.w32
->menubar_active
)
1329 XSETFRAME (Vmenu_updating_frame
, f
);
1331 if (! menubar_widget
)
1333 else if (pending_menu_activation
&& !deep_p
)
1336 wv
= xmalloc_widget_value ();
1337 wv
->name
= "menubar";
1340 wv
->button_type
= BUTTON_TYPE_NONE
;
1346 /* Make a widget-value tree representing the entire menu trees. */
1348 struct buffer
*prev
= current_buffer
;
1350 int specpdl_count
= specpdl_ptr
- specpdl
;
1351 int previous_menu_items_used
= f
->menu_bar_items_used
;
1352 Lisp_Object
*previous_items
1353 = (Lisp_Object
*) alloca (previous_menu_items_used
1354 * sizeof (Lisp_Object
));
1356 /* If we are making a new widget, its contents are empty,
1357 do always reinitialize them. */
1358 if (! menubar_widget
)
1359 previous_menu_items_used
= 0;
1361 buffer
= XWINDOW (FRAME_SELECTED_WINDOW (f
))->buffer
;
1362 specbind (Qinhibit_quit
, Qt
);
1363 /* Don't let the debugger step into this code
1364 because it is not reentrant. */
1365 specbind (Qdebug_on_next_call
, Qnil
);
1367 record_unwind_protect (Fset_match_data
, Fmatch_data (Qnil
, Qnil
));
1368 if (NILP (Voverriding_local_map_menu_flag
))
1370 specbind (Qoverriding_terminal_local_map
, Qnil
);
1371 specbind (Qoverriding_local_map
, Qnil
);
1374 set_buffer_internal_1 (XBUFFER (buffer
));
1376 /* Run the Lucid hook. */
1377 safe_run_hooks (Qactivate_menubar_hook
);
1378 /* If it has changed current-menubar from previous value,
1379 really recompute the menubar from the value. */
1380 if (! NILP (Vlucid_menu_bar_dirty_flag
))
1381 call0 (Qrecompute_lucid_menubar
);
1382 safe_run_hooks (Qmenu_bar_update_hook
);
1383 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1385 items
= FRAME_MENU_BAR_ITEMS (f
);
1387 inhibit_garbage_collection ();
1389 /* Save the frame's previous menu bar contents data. */
1390 if (previous_menu_items_used
)
1391 bcopy (XVECTOR (f
->menu_bar_vector
)->contents
, previous_items
,
1392 previous_menu_items_used
* sizeof (Lisp_Object
));
1394 /* Fill in the current menu bar contents. */
1395 menu_items
= f
->menu_bar_vector
;
1396 menu_items_allocated
= VECTORP (menu_items
) ? ASIZE (menu_items
) : 0;
1398 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1400 Lisp_Object key
, string
, maps
;
1402 key
= XVECTOR (items
)->contents
[i
];
1403 string
= XVECTOR (items
)->contents
[i
+ 1];
1404 maps
= XVECTOR (items
)->contents
[i
+ 2];
1408 wv
= single_submenu (key
, string
, maps
);
1412 first_wv
->contents
= wv
;
1413 /* Don't set wv->name here; GC during the loop might relocate it. */
1415 wv
->button_type
= BUTTON_TYPE_NONE
;
1419 finish_menu_items ();
1421 set_buffer_internal_1 (prev
);
1422 unbind_to (specpdl_count
, Qnil
);
1424 /* If there has been no change in the Lisp-level contents
1425 of the menu bar, skip redisplaying it. Just exit. */
1427 for (i
= 0; i
< previous_menu_items_used
; i
++)
1428 if (menu_items_used
== i
1429 || (!EQ (previous_items
[i
], XVECTOR (menu_items
)->contents
[i
])))
1431 if (i
== menu_items_used
&& i
== previous_menu_items_used
&& i
!= 0)
1433 free_menubar_widget_value_tree (first_wv
);
1439 /* Now GC cannot happen during the lifetime of the widget_value,
1440 so it's safe to store data from a Lisp_String, as long as
1441 local copies are made when the actual menu is created.
1442 Windows takes care of this for normal string items, but
1443 not for owner-drawn items or additional item-info. */
1444 wv
= first_wv
->contents
;
1445 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1448 string
= XVECTOR (items
)->contents
[i
+ 1];
1451 wv
->name
= (char *) XSTRING (string
)->data
;
1455 f
->menu_bar_vector
= menu_items
;
1456 f
->menu_bar_items_used
= menu_items_used
;
1461 /* Make a widget-value tree containing
1462 just the top level menu bar strings. */
1464 items
= FRAME_MENU_BAR_ITEMS (f
);
1465 for (i
= 0; i
< XVECTOR (items
)->size
; i
+= 4)
1469 string
= XVECTOR (items
)->contents
[i
+ 1];
1473 wv
= xmalloc_widget_value ();
1474 wv
->name
= (char *) XSTRING (string
)->data
;
1477 wv
->button_type
= BUTTON_TYPE_NONE
;
1479 /* This prevents lwlib from assuming this
1480 menu item is really supposed to be empty. */
1481 /* The EMACS_INT cast avoids a warning.
1482 This value just has to be different from small integers. */
1483 wv
->call_data
= (void *) (EMACS_INT
) (-1);
1488 first_wv
->contents
= wv
;
1492 /* Forget what we thought we knew about what is in the
1493 detailed contents of the menu bar menus.
1494 Changing the top level always destroys the contents. */
1495 f
->menu_bar_items_used
= 0;
1498 /* Create or update the menu bar widget. */
1504 /* Empty current menubar, rather than creating a fresh one. */
1505 while (DeleteMenu (menubar_widget
, 0, MF_BYPOSITION
))
1510 menubar_widget
= CreateMenu ();
1512 fill_in_menu (menubar_widget
, first_wv
->contents
);
1514 free_menubar_widget_value_tree (first_wv
);
1517 HMENU old_widget
= f
->output_data
.w32
->menubar_widget
;
1519 f
->output_data
.w32
->menubar_widget
= menubar_widget
;
1520 SetMenu (FRAME_W32_WINDOW (f
), f
->output_data
.w32
->menubar_widget
);
1521 /* Causes flicker when menu bar is updated
1522 DrawMenuBar (FRAME_W32_WINDOW (f)); */
1524 /* Force the window size to be recomputed so that the frame's text
1525 area remains the same, if menubar has just been created. */
1526 if (old_widget
== NULL
)
1527 x_set_window_size (f
, 0, FRAME_WIDTH (f
), FRAME_HEIGHT (f
));
1533 /* Called from Fx_create_frame to create the initial menubar of a frame
1534 before it is mapped, so that the window is mapped with the menubar already
1535 there instead of us tacking it on later and thrashing the window after it
1539 initialize_frame_menubar (f
)
1542 /* This function is called before the first chance to redisplay
1543 the frame. It has to be, so the frame will have the right size. */
1544 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1545 set_frame_menubar (f
, 1, 1);
1548 /* Get rid of the menu bar of frame F, and free its storage.
1549 This is used when deleting a frame, and when turning off the menu bar. */
1552 free_frame_menubar (f
)
1558 HMENU old
= GetMenu (FRAME_W32_WINDOW (f
));
1559 SetMenu (FRAME_W32_WINDOW (f
), NULL
);
1560 f
->output_data
.w32
->menubar_widget
= NULL
;
1568 /* w32_menu_show actually displays a menu using the panes and items in
1569 menu_items and returns the value selected from it; we assume input
1570 is blocked by the caller. */
1572 /* F is the frame the menu is for.
1573 X and Y are the frame-relative specified position,
1574 relative to the inside upper left corner of the frame F.
1575 FOR_CLICK is nonzero if this menu was invoked for a mouse click.
1576 KEYMAPS is 1 if this menu was specified with keymaps;
1577 in that case, we return a list containing the chosen item's value
1578 and perhaps also the pane's prefix.
1579 TITLE is the specified menu title.
1580 ERROR is a place to store an error message string in case of failure.
1581 (We return nil on failure, but the value doesn't actually matter.) */
1584 w32_menu_show (f
, x
, y
, for_click
, keymaps
, title
, error
)
1594 int menu_item_selection
;
1597 widget_value
*wv
, *save_wv
= 0, *first_wv
= 0, *prev_wv
= 0;
1598 widget_value
**submenu_stack
1599 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
1600 Lisp_Object
*subprefix_stack
1601 = (Lisp_Object
*) alloca (menu_items_used
* sizeof (Lisp_Object
));
1602 int submenu_depth
= 0;
1607 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
1609 *error
= "Empty menu";
1613 /* Create a tree of widget_value objects
1614 representing the panes and their items. */
1615 wv
= xmalloc_widget_value ();
1619 wv
->button_type
= BUTTON_TYPE_NONE
;
1624 /* Loop over all panes and items, filling in the tree. */
1626 while (i
< menu_items_used
)
1628 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1630 submenu_stack
[submenu_depth
++] = save_wv
;
1636 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1639 save_wv
= submenu_stack
[--submenu_depth
];
1643 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
)
1644 && submenu_depth
!= 0)
1645 i
+= MENU_ITEMS_PANE_LENGTH
;
1646 /* Ignore a nil in the item list.
1647 It's meaningful only for dialog boxes. */
1648 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1650 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1652 /* Create a new pane. */
1653 Lisp_Object pane_name
, prefix
;
1655 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
1656 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
1657 #ifndef HAVE_MULTILINGUAL_MENU
1658 if (STRINGP (pane_name
) && STRING_MULTIBYTE (pane_name
))
1660 pane_name
= ENCODE_SYSTEM (pane_name
);
1661 AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
) = pane_name
;
1664 pane_string
= (NILP (pane_name
)
1665 ? "" : (char *) XSTRING (pane_name
)->data
);
1666 /* If there is just one top-level pane, put all its items directly
1667 under the top-level menu. */
1668 if (menu_items_n_panes
== 1)
1671 /* If the pane has a meaningful name,
1672 make the pane a top-level menu item
1673 with its items as a submenu beneath it. */
1674 if (!keymaps
&& strcmp (pane_string
, ""))
1676 wv
= xmalloc_widget_value ();
1680 first_wv
->contents
= wv
;
1681 wv
->name
= pane_string
;
1682 if (keymaps
&& !NILP (prefix
))
1686 wv
->button_type
= BUTTON_TYPE_NONE
;
1691 else if (first_pane
)
1697 i
+= MENU_ITEMS_PANE_LENGTH
;
1701 /* Create a new item within current pane. */
1702 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
, help
;
1704 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
1705 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
1706 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
1707 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
1708 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
1709 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
1710 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
1712 #ifndef HAVE_MULTILINGUAL_MENU
1713 if (STRINGP (item_name
) && STRING_MULTIBYTE (item_name
))
1715 item_name
= ENCODE_SYSTEM (item_name
);
1716 AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
) = item_name
;
1718 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
1720 descrip
= ENCODE_SYSTEM (descrip
);
1721 AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
) = descrip
;
1723 #endif /* not HAVE_MULTILINGUAL_MENU */
1725 wv
= xmalloc_widget_value ();
1729 save_wv
->contents
= wv
;
1730 wv
->name
= (char *) XSTRING (item_name
)->data
;
1731 if (!NILP (descrip
))
1732 wv
->key
= (char *) XSTRING (descrip
)->data
;
1734 /* Use the contents index as call_data, since we are
1735 restricted to 16-bits. */
1736 wv
->call_data
= !NILP (def
) ? (void *) (EMACS_INT
) i
: 0;
1737 wv
->enabled
= !NILP (enable
);
1740 wv
->button_type
= BUTTON_TYPE_NONE
;
1741 else if (EQ (type
, QCtoggle
))
1742 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
1743 else if (EQ (type
, QCradio
))
1744 wv
->button_type
= BUTTON_TYPE_RADIO
;
1748 wv
->selected
= !NILP (selected
);
1749 if (!STRINGP (help
))
1756 i
+= MENU_ITEMS_ITEM_LENGTH
;
1760 /* Deal with the title, if it is non-nil. */
1763 widget_value
*wv_title
= xmalloc_widget_value ();
1764 widget_value
*wv_sep
= xmalloc_widget_value ();
1766 /* Maybe replace this separator with a bitmap or owner-draw item
1767 so that it looks better. Having two separators looks odd. */
1768 wv_sep
->name
= "--";
1769 wv_sep
->next
= first_wv
->contents
;
1770 wv_sep
->help
= Qnil
;
1772 #ifndef HAVE_MULTILINGUAL_MENU
1773 if (STRING_MULTIBYTE (title
))
1774 title
= ENCODE_SYSTEM (title
);
1776 wv_title
->name
= (char *) XSTRING (title
)->data
;
1777 wv_title
->enabled
= TRUE
;
1778 wv_title
->title
= TRUE
;
1779 wv_title
->button_type
= BUTTON_TYPE_NONE
;
1780 wv_title
->help
= Qnil
;
1781 wv_title
->next
= wv_sep
;
1782 first_wv
->contents
= wv_title
;
1785 /* Actually create the menu. */
1786 current_popup_menu
= menu
= CreatePopupMenu ();
1787 fill_in_menu (menu
, first_wv
->contents
);
1789 /* Adjust coordinates to be root-window-relative. */
1792 ClientToScreen (FRAME_W32_WINDOW (f
), &pos
);
1794 /* No selection has been chosen yet. */
1795 menu_item_selection
= 0;
1797 /* Display the menu. */
1798 menu_item_selection
= SendMessage (FRAME_W32_WINDOW (f
),
1799 WM_EMACS_TRACKPOPUPMENU
,
1800 (WPARAM
)menu
, (LPARAM
)&pos
);
1802 /* Clean up extraneous mouse events which might have been generated
1804 discard_mouse_events ();
1806 /* Free the widget_value objects we used to specify the contents. */
1807 free_menubar_widget_value_tree (first_wv
);
1811 /* Find the selected item, and its pane, to return
1812 the proper value. */
1813 if (menu_item_selection
!= 0)
1815 Lisp_Object prefix
, entry
;
1817 prefix
= entry
= Qnil
;
1819 while (i
< menu_items_used
)
1821 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qnil
))
1823 subprefix_stack
[submenu_depth
++] = prefix
;
1827 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qlambda
))
1829 prefix
= subprefix_stack
[--submenu_depth
];
1832 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
1835 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
1836 i
+= MENU_ITEMS_PANE_LENGTH
;
1838 /* Ignore a nil in the item list.
1839 It's meaningful only for dialog boxes. */
1840 else if (EQ (XVECTOR (menu_items
)->contents
[i
], Qquote
))
1845 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
1846 if (menu_item_selection
== i
)
1852 entry
= Fcons (entry
, Qnil
);
1854 entry
= Fcons (prefix
, entry
);
1855 for (j
= submenu_depth
- 1; j
>= 0; j
--)
1856 if (!NILP (subprefix_stack
[j
]))
1857 entry
= Fcons (subprefix_stack
[j
], entry
);
1861 i
+= MENU_ITEMS_ITEM_LENGTH
;
1871 static char * button_names
[] = {
1872 "button1", "button2", "button3", "button4", "button5",
1873 "button6", "button7", "button8", "button9", "button10" };
1876 w32_dialog_show (f
, keymaps
, title
, error
)
1882 int i
, nb_buttons
=0;
1883 char dialog_name
[6];
1884 int menu_item_selection
;
1886 widget_value
*wv
, *first_wv
= 0, *prev_wv
= 0;
1888 /* Number of elements seen so far, before boundary. */
1890 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
1891 int boundary_seen
= 0;
1895 if (menu_items_n_panes
> 1)
1897 *error
= "Multiple panes in dialog box";
1901 /* Create a tree of widget_value objects
1902 representing the text label and buttons. */
1904 Lisp_Object pane_name
, prefix
;
1906 pane_name
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_NAME
];
1907 prefix
= XVECTOR (menu_items
)->contents
[MENU_ITEMS_PANE_PREFIX
];
1908 pane_string
= (NILP (pane_name
)
1909 ? "" : (char *) XSTRING (pane_name
)->data
);
1910 prev_wv
= xmalloc_widget_value ();
1911 prev_wv
->value
= pane_string
;
1912 if (keymaps
&& !NILP (prefix
))
1914 prev_wv
->enabled
= 1;
1915 prev_wv
->name
= "message";
1916 prev_wv
->help
= Qnil
;
1919 /* Loop over all panes and items, filling in the tree. */
1920 i
= MENU_ITEMS_PANE_LENGTH
;
1921 while (i
< menu_items_used
)
1924 /* Create a new item within current pane. */
1925 Lisp_Object item_name
, enable
, descrip
, help
;
1927 item_name
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_NAME
];
1928 enable
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_ENABLE
];
1930 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_EQUIV_KEY
];
1931 help
= XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_HELP
];
1933 if (NILP (item_name
))
1935 free_menubar_widget_value_tree (first_wv
);
1936 *error
= "Submenu in dialog items";
1939 if (EQ (item_name
, Qquote
))
1941 /* This is the boundary between left-side elts
1942 and right-side elts. Stop incrementing right_count. */
1947 if (nb_buttons
>= 9)
1949 free_menubar_widget_value_tree (first_wv
);
1950 *error
= "Too many dialog items";
1954 wv
= xmalloc_widget_value ();
1956 wv
->name
= (char *) button_names
[nb_buttons
];
1957 if (!NILP (descrip
))
1958 wv
->key
= (char *) XSTRING (descrip
)->data
;
1959 wv
->value
= (char *) XSTRING (item_name
)->data
;
1960 wv
->call_data
= (void *) &XVECTOR (menu_items
)->contents
[i
];
1961 wv
->enabled
= !NILP (enable
);
1965 if (! boundary_seen
)
1969 i
+= MENU_ITEMS_ITEM_LENGTH
;
1972 /* If the boundary was not specified,
1973 by default put half on the left and half on the right. */
1974 if (! boundary_seen
)
1975 left_count
= nb_buttons
- nb_buttons
/ 2;
1977 wv
= xmalloc_widget_value ();
1978 wv
->name
= dialog_name
;
1981 /* Dialog boxes use a really stupid name encoding
1982 which specifies how many buttons to use
1983 and how many buttons are on the right.
1984 The Q means something also. */
1985 dialog_name
[0] = 'Q';
1986 dialog_name
[1] = '0' + nb_buttons
;
1987 dialog_name
[2] = 'B';
1988 dialog_name
[3] = 'R';
1989 /* Number of buttons to put on the right. */
1990 dialog_name
[4] = '0' + nb_buttons
- left_count
;
1992 wv
->contents
= first_wv
;
1996 /* Actually create the dialog. */
1997 dialog_id
= widget_id_tick
++;
1998 menu
= lw_create_widget (first_wv
->name
, "dialog", dialog_id
, first_wv
,
1999 f
->output_data
.w32
->widget
, 1, 0,
2000 dialog_selection_callback
, 0);
2001 lw_modify_all_widgets (dialog_id
, first_wv
->contents
, TRUE
);
2003 /* Free the widget_value objects we used to specify the contents. */
2004 free_menubar_widget_value_tree (first_wv
);
2006 /* No selection has been chosen yet. */
2007 menu_item_selection
= 0;
2009 /* Display the menu. */
2010 lw_pop_up_all_widgets (dialog_id
);
2011 popup_activated_flag
= 1;
2013 /* Process events that apply to the menu. */
2014 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
), dialog_id
);
2016 lw_destroy_all_widgets (dialog_id
);
2018 /* Find the selected item, and its pane, to return
2019 the proper value. */
2020 if (menu_item_selection
!= 0)
2026 while (i
< menu_items_used
)
2030 if (EQ (XVECTOR (menu_items
)->contents
[i
], Qt
))
2033 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_PANE_PREFIX
];
2034 i
+= MENU_ITEMS_PANE_LENGTH
;
2039 = XVECTOR (menu_items
)->contents
[i
+ MENU_ITEMS_ITEM_VALUE
];
2040 if (menu_item_selection
== i
)
2044 entry
= Fcons (entry
, Qnil
);
2046 entry
= Fcons (prefix
, entry
);
2050 i
+= MENU_ITEMS_ITEM_LENGTH
;
2057 #endif /* HAVE_DIALOGS */
2060 /* Is this item a separator? */
2062 name_is_separator (name
)
2067 /* Check if name string consists of only dashes ('-'). */
2068 while (*name
== '-') name
++;
2069 /* Separators can also be of the form "--:TripleSuperMegaEtched"
2070 or "--deep-shadow". We don't implement them yet, se we just treat
2071 them like normal separators. */
2072 return (*name
== '\0' || start
+ 2 == name
);
2076 /* Indicate boundary between left and right. */
2078 add_left_right_boundary (HMENU menu
)
2080 return AppendMenu (menu
, MF_MENUBARBREAK
, 0, NULL
);
2084 add_menu_item (HMENU menu
, widget_value
*wv
, HMENU item
)
2090 if (name_is_separator (wv
->name
))
2092 fuFlags
= MF_SEPARATOR
;
2098 fuFlags
= MF_STRING
;
2100 fuFlags
= MF_STRING
| MF_GRAYED
;
2102 if (wv
->key
!= NULL
)
2104 out_string
= alloca (strlen (wv
->name
) + strlen (wv
->key
) + 2);
2105 strcpy (out_string
, wv
->name
);
2106 strcat (out_string
, "\t");
2107 strcat (out_string
, wv
->key
);
2110 out_string
= wv
->name
;
2114 else if (wv
->title
|| wv
->call_data
== 0)
2116 /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since
2117 we can't deallocate the memory otherwise. */
2118 if (get_menu_item_info
)
2120 out_string
= (char *) LocalAlloc (LPTR
, strlen (wv
->name
) + 1);
2122 DebPrint ("Menu: allocing %ld for owner-draw", info
.dwItemData
);
2124 strcpy (out_string
, wv
->name
);
2125 fuFlags
= MF_OWNERDRAW
| MF_DISABLED
;
2128 fuFlags
= MF_DISABLED
;
2131 /* Draw radio buttons and tickboxes. */
2132 else if (wv
->selected
&& (wv
->button_type
== BUTTON_TYPE_TOGGLE
||
2133 wv
->button_type
== BUTTON_TYPE_RADIO
))
2134 fuFlags
|= MF_CHECKED
;
2136 fuFlags
|= MF_UNCHECKED
;
2142 item
!= NULL
? (UINT
) item
: (UINT
) wv
->call_data
,
2145 /* This must be done after the menu item is created. */
2146 if (!wv
->title
&& wv
->call_data
!= 0)
2148 if (set_menu_item_info
)
2151 bzero (&info
, sizeof (info
));
2152 info
.cbSize
= sizeof (info
);
2153 info
.fMask
= MIIM_DATA
;
2155 /* Set help string for menu item. Leave it as a Lisp_Object
2156 until it is ready to be displayed, since GC can happen while
2157 menus are active. */
2159 info
.dwItemData
= (DWORD
) wv
->help
;
2161 if (wv
->button_type
== BUTTON_TYPE_RADIO
)
2163 /* CheckMenuRadioItem allows us to differentiate TOGGLE and
2164 RADIO items, but is not available on NT 3.51 and earlier. */
2165 info
.fMask
|= MIIM_TYPE
| MIIM_STATE
;
2166 info
.fType
= MFT_RADIOCHECK
| MFT_STRING
;
2167 info
.dwTypeData
= out_string
;
2168 info
.fState
= wv
->selected
? MFS_CHECKED
: MFS_UNCHECKED
;
2171 set_menu_item_info (menu
,
2172 item
!= NULL
? (UINT
) item
: (UINT
) wv
->call_data
,
2176 return return_value
;
2179 /* Construct native Windows menu(bar) based on widget_value tree. */
2181 fill_in_menu (HMENU menu
, widget_value
*wv
)
2183 int items_added
= 0;
2185 for ( ; wv
!= NULL
; wv
= wv
->next
)
2189 HMENU sub_menu
= CreatePopupMenu ();
2191 if (sub_menu
== NULL
)
2194 if (!fill_in_menu (sub_menu
, wv
->contents
) ||
2195 !add_menu_item (menu
, wv
, sub_menu
))
2197 DestroyMenu (sub_menu
);
2203 if (!add_menu_item (menu
, wv
, NULL
))
2213 /* popup_activated_flag not actually used on W32 */
2217 /* Display help string for currently pointed to menu item. Not
2218 supported on NT 3.51 and earlier, as GetMenuItemInfo is not
2221 w32_menu_display_help (HWND owner
, HMENU menu
, UINT item
, UINT flags
)
2223 if (get_menu_item_info
)
2225 struct frame
*f
= x_window_to_frame (&one_w32_display_info
, owner
);
2226 Lisp_Object frame
, help
;
2228 // No help echo on owner-draw menu items.
2229 if (flags
& MF_OWNERDRAW
|| flags
& MF_POPUP
)
2235 bzero (&info
, sizeof (info
));
2236 info
.cbSize
= sizeof (info
);
2237 info
.fMask
= MIIM_DATA
;
2238 get_menu_item_info (menu
, item
, FALSE
, &info
);
2240 help
= info
.dwItemData
? (Lisp_Object
) info
.dwItemData
: Qnil
;
2243 /* Store the help echo in the keyboard buffer as the X toolkit
2244 version does, rather than directly showing it. This seems to
2245 solve the GC problems that were present when we based the
2246 Windows code on the non-toolkit version. */
2249 XSETFRAME (frame
, f
);
2250 kbd_buffer_store_help_event (frame
, help
);
2253 /* X version has a loop through frames here, which doesn't
2254 appear to do anything, unless it has some side effect. */
2255 show_help_echo (help
, Qnil
, Qnil
, Qnil
, 1);
2259 /* Free memory used by owner-drawn strings. */
2261 w32_free_submenu_strings (menu
)
2264 int i
, num
= GetMenuItemCount (menu
);
2265 for (i
= 0; i
< num
; i
++)
2268 bzero (&info
, sizeof (info
));
2269 info
.cbSize
= sizeof (info
);
2270 info
.fMask
= MIIM_DATA
| MIIM_TYPE
| MIIM_SUBMENU
;
2272 get_menu_item_info (menu
, i
, TRUE
, &info
);
2274 /* Owner-drawn names are held in dwItemData. */
2275 if ((info
.fType
& MF_OWNERDRAW
) && info
.dwItemData
)
2278 DebPrint ("Menu: freeing %ld for owner-draw", info
.dwItemData
);
2280 LocalFree (info
.dwItemData
);
2283 /* Recurse down submenus. */
2285 w32_free_submenu_strings (info
.hSubMenu
);
2290 w32_free_menu_strings (hwnd
)
2293 HMENU menu
= current_popup_menu
;
2295 if (get_menu_item_info
)
2297 /* If there is no popup menu active, free the strings from the frame's
2300 menu
= GetMenu (hwnd
);
2303 w32_free_submenu_strings (menu
);
2306 current_popup_menu
= NULL
;
2309 #endif /* HAVE_MENUS */
2314 /* See if Get/SetMenuItemInfo functions are available. */
2315 HMODULE user32
= GetModuleHandle ("user32.dll");
2316 get_menu_item_info
= GetProcAddress (user32
, "GetMenuItemInfoA");
2317 set_menu_item_info
= GetProcAddress (user32
, "SetMenuItemInfoA");
2319 staticpro (&menu_items
);
2322 current_popup_menu
= NULL
;
2324 Qdebug_on_next_call
= intern ("debug-on-next-call");
2325 staticpro (&Qdebug_on_next_call
);
2327 DEFVAR_LISP ("menu-updating-frame", &Vmenu_updating_frame
,
2328 doc
: /* Frame for which we are updating a menu.
2329 The enable predicate for a menu command should check this variable. */);
2330 Vmenu_updating_frame
= Qnil
;
2332 defsubr (&Sx_popup_menu
);
2334 defsubr (&Sx_popup_dialog
);