1 /* Menu support for GNU Emacs on the Microsoft W32 API.
2 Copyright (C) 1986, 1988, 1993, 1994, 1996, 1998, 1999, 2001, 2002,
3 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
31 #include "termhooks.h"
33 #include "blockinput.h"
36 #include "character.h"
39 /* This may include sys/types.h, and that somehow loses
40 if this is not done before the other system files. */
43 /* Load sys/types.h if not already loaded.
44 In some systems loading it twice is suicidal. */
46 #include <sys/types.h>
49 #include "dispextern.h"
51 #undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
58 HMENU current_popup_menu
;
60 void syms_of_w32menu ();
61 void globals_of_w32menu ();
63 typedef BOOL (WINAPI
* GetMenuItemInfoA_Proc
) (
67 IN OUT LPMENUITEMINFOA
);
68 typedef BOOL (WINAPI
* SetMenuItemInfoA_Proc
) (
74 GetMenuItemInfoA_Proc get_menu_item_info
= NULL
;
75 SetMenuItemInfoA_Proc set_menu_item_info
= NULL
;
76 AppendMenuW_Proc unicode_append_menu
= NULL
;
78 Lisp_Object Qdebug_on_next_call
;
80 extern Lisp_Object Vmenu_updating_frame
;
82 extern Lisp_Object Qmenu_bar
;
84 extern Lisp_Object QCtoggle
, QCradio
;
86 extern Lisp_Object Voverriding_local_map
;
87 extern Lisp_Object Voverriding_local_map_menu_flag
;
89 extern Lisp_Object Qoverriding_local_map
, Qoverriding_terminal_local_map
;
91 extern Lisp_Object Qmenu_bar_update_hook
;
93 void set_frame_menubar
P_ ((FRAME_PTR
, int, int));
95 static void push_menu_item
P_ ((Lisp_Object
, Lisp_Object
, Lisp_Object
,
96 Lisp_Object
, Lisp_Object
, Lisp_Object
,
97 Lisp_Object
, Lisp_Object
));
99 static Lisp_Object w32_dialog_show
P_ ((FRAME_PTR
, int, Lisp_Object
, char**));
101 static int is_simple_dialog
P_ ((Lisp_Object
));
102 static Lisp_Object simple_dialog_show
P_ ((FRAME_PTR
, Lisp_Object
, Lisp_Object
));
104 static Lisp_Object w32_menu_show
P_ ((FRAME_PTR
, int, int, int, int,
105 Lisp_Object
, char **));
107 void w32_free_menu_strings
P_((HWND
));
109 static int next_menubar_widget_id
;
111 extern widget_value
*xmalloc_widget_value
P_ ((void));
113 /* This is set nonzero after the user activates the menu bar, and set
114 to zero again after the menu bars are redisplayed by prepare_menu_bar.
115 While it is nonzero, all calls to set_frame_menubar go deep.
117 I don't understand why this is needed, but it does seem to be
118 needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
120 int pending_menu_activation
;
123 /* Return the frame whose ->output_data.w32->menubar_widget equals
126 static struct frame
*
127 menubar_id_to_frame (id
)
130 Lisp_Object tail
, frame
;
133 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
139 if (!FRAME_WINDOW_P (f
))
141 if (f
->output_data
.w32
->menubar_widget
== id
)
147 DEFUN ("x-popup-menu", Fx_popup_menu
, Sx_popup_menu
, 2, 2, 0,
148 doc
: /* Pop up a deck-of-cards menu and return user's selection.
149 POSITION is a position specification. This is either a mouse button
150 event or a list ((XOFFSET YOFFSET) WINDOW) where XOFFSET and YOFFSET
151 are positions in pixels from the top left corner of WINDOW's frame
152 \(WINDOW may be a frame object instead of a window). This controls the
153 position of the center of the first line in the first pane of the
154 menu, not the top left of the menu as a whole. If POSITION is t, it
155 means to use the current mouse position.
157 MENU is a specifier for a menu. For the simplest case, MENU is a keymap.
158 The menu items come from key bindings that have a menu string as well as
159 a definition; actually, the \"definition\" in such a key binding looks like
160 \(STRING . REAL-DEFINITION). To give the menu a title, put a string into
161 the keymap as a top-level element.
163 If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.
164 Otherwise, REAL-DEFINITION should be a valid key binding definition.
166 You can also use a list of keymaps as MENU. Then each keymap makes a
167 separate pane. When MENU is a keymap or a list of keymaps, the return
168 value is a list of events.
170 Alternatively, you can specify a menu of multiple panes with a list of
171 the form (TITLE PANE1 PANE2...), where each pane is a list of
172 form (TITLE ITEM1 ITEM2...).
173 Each ITEM is normally a cons cell (STRING . VALUE); but a string can
174 appear as an item--that makes a nonselectable line in the menu.
175 With this form of menu, the return value is VALUE from the chosen item.
177 If POSITION is nil, don't display the menu at all, just precalculate the
178 cached information about equivalent key sequences. */)
180 Lisp_Object position
, menu
;
182 Lisp_Object keymap
, tem
;
183 int xpos
= 0, ypos
= 0;
186 Lisp_Object selection
;
188 Lisp_Object x
, y
, window
;
194 if (! NILP (position
))
198 /* Decode the first argument: find the window and the coordinates. */
199 if (EQ (position
, Qt
)
200 || (CONSP (position
) && (EQ (XCAR (position
), Qmenu_bar
)
201 || EQ (XCAR (position
), Qtool_bar
))))
203 /* Use the mouse's current position. */
204 FRAME_PTR new_f
= SELECTED_FRAME ();
205 Lisp_Object bar_window
;
206 enum scroll_bar_part part
;
209 if (FRAME_TERMINAL (new_f
)->mouse_position_hook
)
210 (*FRAME_TERMINAL (new_f
)->mouse_position_hook
) (&new_f
, 1, &bar_window
,
211 &part
, &x
, &y
, &time
);
213 XSETFRAME (window
, new_f
);
216 window
= selected_window
;
223 tem
= Fcar (position
);
226 window
= Fcar (Fcdr (position
));
228 y
= Fcar (Fcdr (tem
));
233 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
234 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
235 tem
= Fcar (Fcdr (Fcdr (tem
))); /* POSN_WINDOW_POSN (tem) */
244 /* Decode where to put the menu. */
252 else if (WINDOWP (window
))
254 CHECK_LIVE_WINDOW (window
);
255 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
257 xpos
= WINDOW_LEFT_EDGE_X (XWINDOW (window
));
258 ypos
= WINDOW_TOP_EDGE_Y (XWINDOW (window
));
261 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
262 but I don't want to make one now. */
263 CHECK_WINDOW (window
);
268 XSETFRAME (Vmenu_updating_frame
, f
);
271 Vmenu_updating_frame
= Qnil
;
272 #endif /* HAVE_MENUS */
277 /* Decode the menu items from what was specified. */
279 keymap
= get_keymap (menu
, 0, 0);
282 /* We were given a keymap. Extract menu info from the keymap. */
285 /* Extract the detailed info to make one pane. */
286 keymap_panes (&menu
, 1, NILP (position
));
288 /* Search for a string appearing directly as an element of the keymap.
289 That string is the title of the menu. */
290 prompt
= Fkeymap_prompt (keymap
);
291 if (NILP (title
) && !NILP (prompt
))
294 /* Make that be the pane title of the first pane. */
295 if (!NILP (prompt
) && menu_items_n_panes
>= 0)
296 ASET (menu_items
, MENU_ITEMS_PANE_NAME
, prompt
);
300 else if (CONSP (menu
) && KEYMAPP (XCAR (menu
)))
302 /* We were given a list of keymaps. */
303 int nmaps
= XFASTINT (Flength (menu
));
305 = (Lisp_Object
*) alloca (nmaps
* sizeof (Lisp_Object
));
310 /* The first keymap that has a prompt string
311 supplies the menu title. */
312 for (tem
= menu
, i
= 0; CONSP (tem
); tem
= Fcdr (tem
))
316 maps
[i
++] = keymap
= get_keymap (Fcar (tem
), 1, 0);
318 prompt
= Fkeymap_prompt (keymap
);
319 if (NILP (title
) && !NILP (prompt
))
323 /* Extract the detailed info to make one pane. */
324 keymap_panes (maps
, nmaps
, NILP (position
));
326 /* Make the title be the pane title of the first pane. */
327 if (!NILP (title
) && menu_items_n_panes
>= 0)
328 ASET (menu_items
, MENU_ITEMS_PANE_NAME
, title
);
334 /* We were given an old-fashioned menu. */
336 CHECK_STRING (title
);
338 list_of_panes (Fcdr (menu
));
345 discard_menu_items ();
351 /* If resources from a previous popup menu still exist, does nothing
352 until the `menu_free_timer' has freed them (see w32fns.c). This
353 can occur if you press ESC or click outside a menu without selecting
356 if (current_popup_menu
)
358 discard_menu_items ();
363 /* Display them in a menu. */
366 selection
= w32_menu_show (f
, xpos
, ypos
, for_click
,
367 keymaps
, title
, &error_name
);
370 discard_menu_items ();
372 #endif /* HAVE_MENUS */
376 if (error_name
) error (error_name
);
382 DEFUN ("x-popup-dialog", Fx_popup_dialog
, Sx_popup_dialog
, 2, 3, 0,
383 doc
: /* Pop up a dialog box and return user's selection.
384 POSITION specifies which frame to use.
385 This is normally a mouse button event or a window or frame.
386 If POSITION is t, it means to use the frame the mouse is on.
387 The dialog box appears in the middle of the specified frame.
389 CONTENTS specifies the alternatives to display in the dialog box.
390 It is a list of the form (TITLE ITEM1 ITEM2...).
391 Each ITEM is a cons cell (STRING . VALUE).
392 The return value is VALUE from the chosen item.
394 An ITEM may also be just a string--that makes a nonselectable item.
395 An ITEM may also be nil--that means to put all preceding items
396 on the left of the dialog box and all following items on the right.
397 \(By default, approximately half appear on each side.)
399 If HEADER is non-nil, the frame title for the box is "Information",
400 otherwise it is "Question". */)
401 (position
, contents
, header
)
402 Lisp_Object position
, contents
, header
;
409 /* Decode the first argument: find the window or frame to use. */
410 if (EQ (position
, Qt
)
411 || (CONSP (position
) && (EQ (XCAR (position
), Qmenu_bar
)
412 || EQ (XCAR (position
), Qtool_bar
))))
414 #if 0 /* Using the frame the mouse is on may not be right. */
415 /* Use the mouse's current position. */
416 FRAME_PTR new_f
= SELECTED_FRAME ();
417 Lisp_Object bar_window
;
418 enum scroll_bar_part part
;
422 (*mouse_position_hook
) (&new_f
, 1, &bar_window
, &part
, &x
, &y
, &time
);
425 XSETFRAME (window
, new_f
);
427 window
= selected_window
;
429 window
= selected_window
;
431 else if (CONSP (position
))
434 tem
= Fcar (position
);
436 window
= Fcar (Fcdr (position
));
439 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
440 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
443 else if (WINDOWP (position
) || FRAMEP (position
))
448 /* Decode where to put the menu. */
452 else if (WINDOWP (window
))
454 CHECK_LIVE_WINDOW (window
);
455 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
458 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
459 but I don't want to make one now. */
460 CHECK_WINDOW (window
);
465 /* Handle simple Yes/No choices as MessageBox popups. */
466 if (is_simple_dialog (contents
))
467 return simple_dialog_show (f
, contents
, header
);
470 /* Display a menu with these alternatives
471 in the middle of frame F. */
472 Lisp_Object x
, y
, frame
, newpos
;
473 XSETFRAME (frame
, f
);
474 XSETINT (x
, x_pixel_width (f
) / 2);
475 XSETINT (y
, x_pixel_height (f
) / 2);
476 newpos
= Fcons (Fcons (x
, Fcons (y
, Qnil
)), Fcons (frame
, Qnil
));
477 return Fx_popup_menu (newpos
,
478 Fcons (Fcar (contents
), Fcons (contents
, Qnil
)));
481 #else /* HAVE_DIALOGS */
485 Lisp_Object selection
;
487 /* Decode the dialog items from what was specified. */
488 title
= Fcar (contents
);
489 CHECK_STRING (title
);
491 list_of_panes (Fcons (contents
, Qnil
));
493 /* Display them in a dialog box. */
495 selection
= w32_dialog_show (f
, 0, title
, header
, &error_name
);
498 discard_menu_items ();
500 if (error_name
) error (error_name
);
503 #endif /* HAVE_DIALOGS */
506 /* Activate the menu bar of frame F.
507 This is called from keyboard.c when it gets the
508 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
510 To activate the menu bar, we signal to the input thread that it can
511 return from the WM_INITMENU message, allowing the normal Windows
512 processing of the menus.
514 But first we recompute the menu bar contents (the whole tree).
516 This way we can safely execute Lisp code. */
519 x_activate_menubar (f
)
522 set_frame_menubar (f
, 0, 1);
524 /* Lock out further menubar changes while active. */
525 f
->output_data
.w32
->menubar_active
= 1;
527 /* Signal input thread to return from WM_INITMENU. */
528 complete_deferred_msg (FRAME_W32_WINDOW (f
), WM_INITMENU
, 0);
531 /* This callback is called from the menu bar pulldown menu
532 when the user makes a selection.
533 Figure out what the user chose
534 and put the appropriate events into the keyboard buffer. */
537 menubar_selection_callback (FRAME_PTR f
, void * client_data
)
539 Lisp_Object prefix
, entry
;
541 Lisp_Object
*subprefix_stack
;
542 int submenu_depth
= 0;
548 subprefix_stack
= (Lisp_Object
*) alloca (f
->menu_bar_items_used
* sizeof (Lisp_Object
));
549 vector
= f
->menu_bar_vector
;
552 while (i
< f
->menu_bar_items_used
)
554 if (EQ (AREF (vector
, i
), Qnil
))
556 subprefix_stack
[submenu_depth
++] = prefix
;
560 else if (EQ (AREF (vector
, i
), Qlambda
))
562 prefix
= subprefix_stack
[--submenu_depth
];
565 else if (EQ (AREF (vector
, i
), Qt
))
567 prefix
= AREF (vector
, i
+ MENU_ITEMS_PANE_PREFIX
);
568 i
+= MENU_ITEMS_PANE_LENGTH
;
572 entry
= AREF (vector
, i
+ MENU_ITEMS_ITEM_VALUE
);
573 /* The EMACS_INT cast avoids a warning. There's no problem
574 as long as pointers have enough bits to hold small integers. */
575 if ((int) (EMACS_INT
) client_data
== i
)
578 struct input_event buf
;
582 XSETFRAME (frame
, f
);
583 buf
.kind
= MENU_BAR_EVENT
;
584 buf
.frame_or_window
= frame
;
586 kbd_buffer_store_event (&buf
);
588 for (j
= 0; j
< submenu_depth
; j
++)
589 if (!NILP (subprefix_stack
[j
]))
591 buf
.kind
= MENU_BAR_EVENT
;
592 buf
.frame_or_window
= frame
;
593 buf
.arg
= subprefix_stack
[j
];
594 kbd_buffer_store_event (&buf
);
599 buf
.kind
= MENU_BAR_EVENT
;
600 buf
.frame_or_window
= frame
;
602 kbd_buffer_store_event (&buf
);
605 buf
.kind
= MENU_BAR_EVENT
;
606 buf
.frame_or_window
= frame
;
608 /* Free memory used by owner-drawn and help-echo strings. */
609 w32_free_menu_strings (FRAME_W32_WINDOW (f
));
610 kbd_buffer_store_event (&buf
);
612 f
->output_data
.w32
->menubar_active
= 0;
615 i
+= MENU_ITEMS_ITEM_LENGTH
;
618 /* Free memory used by owner-drawn and help-echo strings. */
619 w32_free_menu_strings (FRAME_W32_WINDOW (f
));
620 f
->output_data
.w32
->menubar_active
= 0;
624 /* Set up data i menu_items for a menu bar item
625 whose event type is ITEM_KEY (with string ITEM_NAME)
626 and whose contents come from the list of keymaps MAPS. */
629 parse_single_submenu (item_key
, item_name
, maps
)
630 Lisp_Object item_key
, item_name
, maps
;
636 int top_level_items
= 0;
638 length
= Flength (maps
);
641 /* Convert the list MAPS into a vector MAPVEC. */
642 mapvec
= (Lisp_Object
*) alloca (len
* sizeof (Lisp_Object
));
643 for (i
= 0; i
< len
; i
++)
645 mapvec
[i
] = Fcar (maps
);
649 /* Loop over the given keymaps, making a pane for each map.
650 But don't make a pane that is empty--ignore that map instead. */
651 for (i
= 0; i
< len
; i
++)
653 if (SYMBOLP (mapvec
[i
])
654 || (CONSP (mapvec
[i
]) && !KEYMAPP (mapvec
[i
])))
656 /* Here we have a command at top level in the menu bar
657 as opposed to a submenu. */
659 push_menu_pane (Qnil
, Qnil
);
660 push_menu_item (item_name
, Qt
, item_key
, mapvec
[i
],
661 Qnil
, Qnil
, Qnil
, Qnil
);
666 prompt
= Fkeymap_prompt (mapvec
[i
]);
667 single_keymap_panes (mapvec
[i
],
668 !NILP (prompt
) ? prompt
: item_name
,
673 return top_level_items
;
677 /* Create a tree of widget_value objects
678 representing the panes and items
679 in menu_items starting at index START, up to index END. */
681 static widget_value
*
682 digest_single_submenu (start
, end
, top_level_items
)
683 int start
, end
, top_level_items
;
685 widget_value
*wv
, *prev_wv
, *save_wv
, *first_wv
;
687 int submenu_depth
= 0;
688 widget_value
**submenu_stack
;
691 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
692 wv
= xmalloc_widget_value ();
696 wv
->button_type
= BUTTON_TYPE_NONE
;
702 /* Loop over all panes and items made by the preceding call
703 to parse_single_submenu and construct a tree of widget_value objects.
704 Ignore the panes and items used by previous calls to
705 digest_single_submenu, even though those are also in menu_items. */
709 if (EQ (AREF (menu_items
, i
), Qnil
))
711 submenu_stack
[submenu_depth
++] = save_wv
;
716 else if (EQ (AREF (menu_items
, i
), Qlambda
))
719 save_wv
= submenu_stack
[--submenu_depth
];
722 else if (EQ (AREF (menu_items
, i
), Qt
)
723 && submenu_depth
!= 0)
724 i
+= MENU_ITEMS_PANE_LENGTH
;
725 /* Ignore a nil in the item list.
726 It's meaningful only for dialog boxes. */
727 else if (EQ (AREF (menu_items
, i
), Qquote
))
729 else if (EQ (AREF (menu_items
, i
), Qt
))
731 /* Create a new pane. */
732 Lisp_Object pane_name
, prefix
;
735 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
736 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
738 if (STRINGP (pane_name
))
740 if (unicode_append_menu
)
741 /* Encode as UTF-8 for now. */
742 pane_name
= ENCODE_UTF_8 (pane_name
);
743 else if (STRING_MULTIBYTE (pane_name
))
744 pane_name
= ENCODE_SYSTEM (pane_name
);
746 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
749 pane_string
= (NILP (pane_name
)
750 ? "" : (char *) SDATA (pane_name
));
751 /* If there is just one top-level pane, put all its items directly
752 under the top-level menu. */
753 if (menu_items_n_panes
== 1)
756 /* If the pane has a meaningful name,
757 make the pane a top-level menu item
758 with its items as a submenu beneath it. */
759 if (strcmp (pane_string
, ""))
761 wv
= xmalloc_widget_value ();
765 first_wv
->contents
= wv
;
766 wv
->lname
= pane_name
;
767 /* Set value to 1 so update_submenu_strings can handle '@' */
768 wv
->value
= (char *) 1;
770 wv
->button_type
= BUTTON_TYPE_NONE
;
775 i
+= MENU_ITEMS_PANE_LENGTH
;
779 /* Create a new item within current pane. */
780 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
;
783 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
784 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
785 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
786 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
787 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
788 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
789 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
791 if (STRINGP (item_name
))
793 if (unicode_append_menu
)
794 item_name
= ENCODE_UTF_8 (item_name
);
795 else if (STRING_MULTIBYTE (item_name
))
796 item_name
= ENCODE_SYSTEM (item_name
);
798 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
801 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
803 descrip
= ENCODE_SYSTEM (descrip
);
804 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
807 wv
= xmalloc_widget_value ();
811 save_wv
->contents
= wv
;
813 wv
->lname
= item_name
;
817 /* The EMACS_INT cast avoids a warning. There's no problem
818 as long as pointers have enough bits to hold small integers. */
819 wv
->call_data
= (!NILP (def
) ? (void *) (EMACS_INT
) i
: 0);
820 wv
->enabled
= !NILP (enable
);
823 wv
->button_type
= BUTTON_TYPE_NONE
;
824 else if (EQ (type
, QCradio
))
825 wv
->button_type
= BUTTON_TYPE_RADIO
;
826 else if (EQ (type
, QCtoggle
))
827 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
831 wv
->selected
= !NILP (selected
);
839 i
+= MENU_ITEMS_ITEM_LENGTH
;
843 /* If we have just one "menu item"
844 that was originally a button, return it by itself. */
845 if (top_level_items
&& first_wv
->contents
&& first_wv
->contents
->next
== 0)
847 wv
= first_wv
->contents
;
848 free_widget_value (first_wv
);
857 /* Set the contents of the menubar widgets of frame F.
858 The argument FIRST_TIME is currently ignored;
859 it is set the first time this is called, from initialize_frame_menubar. */
862 set_frame_menubar (f
, first_time
, deep_p
)
867 HMENU menubar_widget
= f
->output_data
.w32
->menubar_widget
;
869 widget_value
*wv
, *first_wv
, *prev_wv
= 0;
871 int *submenu_start
, *submenu_end
;
872 int *submenu_top_level_items
, *submenu_n_panes
;
874 /* We must not change the menubar when actually in use. */
875 if (f
->output_data
.w32
->menubar_active
)
878 XSETFRAME (Vmenu_updating_frame
, f
);
880 if (! menubar_widget
)
882 else if (pending_menu_activation
&& !deep_p
)
887 /* Make a widget-value tree representing the entire menu trees. */
889 struct buffer
*prev
= current_buffer
;
891 int specpdl_count
= SPECPDL_INDEX ();
892 int previous_menu_items_used
= f
->menu_bar_items_used
;
893 Lisp_Object
*previous_items
894 = (Lisp_Object
*) alloca (previous_menu_items_used
895 * sizeof (Lisp_Object
));
897 /* If we are making a new widget, its contents are empty,
898 do always reinitialize them. */
899 if (! menubar_widget
)
900 previous_menu_items_used
= 0;
902 buffer
= XWINDOW (FRAME_SELECTED_WINDOW (f
))->buffer
;
903 specbind (Qinhibit_quit
, Qt
);
904 /* Don't let the debugger step into this code
905 because it is not reentrant. */
906 specbind (Qdebug_on_next_call
, Qnil
);
908 record_unwind_save_match_data ();
910 if (NILP (Voverriding_local_map_menu_flag
))
912 specbind (Qoverriding_terminal_local_map
, Qnil
);
913 specbind (Qoverriding_local_map
, Qnil
);
916 set_buffer_internal_1 (XBUFFER (buffer
));
918 /* Run the Lucid hook. */
919 safe_run_hooks (Qactivate_menubar_hook
);
920 /* If it has changed current-menubar from previous value,
921 really recompute the menubar from the value. */
922 if (! NILP (Vlucid_menu_bar_dirty_flag
))
923 call0 (Qrecompute_lucid_menubar
);
924 safe_run_hooks (Qmenu_bar_update_hook
);
925 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
927 items
= FRAME_MENU_BAR_ITEMS (f
);
929 /* Save the frame's previous menu bar contents data. */
930 if (previous_menu_items_used
)
931 bcopy (XVECTOR (f
->menu_bar_vector
)->contents
, previous_items
,
932 previous_menu_items_used
* sizeof (Lisp_Object
));
934 /* Fill in menu_items with the current menu bar contents.
935 This can evaluate Lisp code. */
936 menu_items
= f
->menu_bar_vector
;
937 menu_items_allocated
= VECTORP (menu_items
) ? ASIZE (menu_items
) : 0;
938 submenu_start
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
939 submenu_end
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
940 submenu_n_panes
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int));
941 submenu_top_level_items
942 = (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
944 for (i
= 0; i
< ASIZE (items
); i
+= 4)
946 Lisp_Object key
, string
, maps
;
950 key
= AREF (items
, i
);
951 string
= AREF (items
, i
+ 1);
952 maps
= AREF (items
, i
+ 2);
956 submenu_start
[i
] = menu_items_used
;
958 menu_items_n_panes
= 0;
959 submenu_top_level_items
[i
]
960 = parse_single_submenu (key
, string
, maps
);
961 submenu_n_panes
[i
] = menu_items_n_panes
;
963 submenu_end
[i
] = menu_items_used
;
966 finish_menu_items ();
968 /* Convert menu_items into widget_value trees
969 to display the menu. This cannot evaluate Lisp code. */
971 wv
= xmalloc_widget_value ();
972 wv
->name
= "menubar";
975 wv
->button_type
= BUTTON_TYPE_NONE
;
979 for (i
= 0; i
< last_i
; i
+= 4)
981 menu_items_n_panes
= submenu_n_panes
[i
];
982 wv
= digest_single_submenu (submenu_start
[i
], submenu_end
[i
],
983 submenu_top_level_items
[i
]);
987 first_wv
->contents
= wv
;
988 /* Don't set wv->name here; GC during the loop might relocate it. */
990 wv
->button_type
= BUTTON_TYPE_NONE
;
994 set_buffer_internal_1 (prev
);
995 unbind_to (specpdl_count
, Qnil
);
997 /* If there has been no change in the Lisp-level contents
998 of the menu bar, skip redisplaying it. Just exit. */
1000 for (i
= 0; i
< previous_menu_items_used
; i
++)
1001 if (menu_items_used
== i
1002 || (!EQ (previous_items
[i
], AREF (menu_items
, i
))))
1004 if (i
== menu_items_used
&& i
== previous_menu_items_used
&& i
!= 0)
1006 free_menubar_widget_value_tree (first_wv
);
1012 /* Now GC cannot happen during the lifetime of the widget_value,
1013 so it's safe to store data from a Lisp_String, as long as
1014 local copies are made when the actual menu is created.
1015 Windows takes care of this for normal string items, but
1016 not for owner-drawn items or additional item-info. */
1017 wv
= first_wv
->contents
;
1018 for (i
= 0; i
< ASIZE (items
); i
+= 4)
1021 string
= AREF (items
, i
+ 1);
1024 wv
->name
= (char *) SDATA (string
);
1025 update_submenu_strings (wv
->contents
);
1029 f
->menu_bar_vector
= menu_items
;
1030 f
->menu_bar_items_used
= menu_items_used
;
1035 /* Make a widget-value tree containing
1036 just the top level menu bar strings. */
1038 wv
= xmalloc_widget_value ();
1039 wv
->name
= "menubar";
1042 wv
->button_type
= BUTTON_TYPE_NONE
;
1046 items
= FRAME_MENU_BAR_ITEMS (f
);
1047 for (i
= 0; i
< ASIZE (items
); i
+= 4)
1051 string
= AREF (items
, i
+ 1);
1055 wv
= xmalloc_widget_value ();
1056 wv
->name
= (char *) SDATA (string
);
1059 wv
->button_type
= BUTTON_TYPE_NONE
;
1061 /* This prevents lwlib from assuming this
1062 menu item is really supposed to be empty. */
1063 /* The EMACS_INT cast avoids a warning.
1064 This value just has to be different from small integers. */
1065 wv
->call_data
= (void *) (EMACS_INT
) (-1);
1070 first_wv
->contents
= wv
;
1074 /* Forget what we thought we knew about what is in the
1075 detailed contents of the menu bar menus.
1076 Changing the top level always destroys the contents. */
1077 f
->menu_bar_items_used
= 0;
1080 /* Create or update the menu bar widget. */
1086 /* Empty current menubar, rather than creating a fresh one. */
1087 while (DeleteMenu (menubar_widget
, 0, MF_BYPOSITION
))
1092 menubar_widget
= CreateMenu ();
1094 fill_in_menu (menubar_widget
, first_wv
->contents
);
1096 free_menubar_widget_value_tree (first_wv
);
1099 HMENU old_widget
= f
->output_data
.w32
->menubar_widget
;
1101 f
->output_data
.w32
->menubar_widget
= menubar_widget
;
1102 SetMenu (FRAME_W32_WINDOW (f
), f
->output_data
.w32
->menubar_widget
);
1103 /* Causes flicker when menu bar is updated
1104 DrawMenuBar (FRAME_W32_WINDOW (f)); */
1106 /* Force the window size to be recomputed so that the frame's text
1107 area remains the same, if menubar has just been created. */
1108 if (old_widget
== NULL
)
1109 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
1115 /* Called from Fx_create_frame to create the initial menubar of a frame
1116 before it is mapped, so that the window is mapped with the menubar already
1117 there instead of us tacking it on later and thrashing the window after it
1121 initialize_frame_menubar (f
)
1124 /* This function is called before the first chance to redisplay
1125 the frame. It has to be, so the frame will have the right size. */
1126 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
1127 set_frame_menubar (f
, 1, 1);
1130 /* Get rid of the menu bar of frame F, and free its storage.
1131 This is used when deleting a frame, and when turning off the menu bar. */
1134 free_frame_menubar (f
)
1140 HMENU old
= GetMenu (FRAME_W32_WINDOW (f
));
1141 SetMenu (FRAME_W32_WINDOW (f
), NULL
);
1142 f
->output_data
.w32
->menubar_widget
= NULL
;
1150 /* w32_menu_show actually displays a menu using the panes and items in
1151 menu_items and returns the value selected from it; we assume input
1152 is blocked by the caller. */
1154 /* F is the frame the menu is for.
1155 X and Y are the frame-relative specified position,
1156 relative to the inside upper left corner of the frame F.
1157 FOR_CLICK is nonzero if this menu was invoked for a mouse click.
1158 KEYMAPS is 1 if this menu was specified with keymaps;
1159 in that case, we return a list containing the chosen item's value
1160 and perhaps also the pane's prefix.
1161 TITLE is the specified menu title.
1162 ERROR is a place to store an error message string in case of failure.
1163 (We return nil on failure, but the value doesn't actually matter.) */
1166 w32_menu_show (f
, x
, y
, for_click
, keymaps
, title
, error
)
1176 int menu_item_selection
;
1179 widget_value
*wv
, *save_wv
= 0, *first_wv
= 0, *prev_wv
= 0;
1180 widget_value
**submenu_stack
1181 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
1182 Lisp_Object
*subprefix_stack
1183 = (Lisp_Object
*) alloca (menu_items_used
* sizeof (Lisp_Object
));
1184 int submenu_depth
= 0;
1189 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
1191 *error
= "Empty menu";
1195 /* Create a tree of widget_value objects
1196 representing the panes and their items. */
1197 wv
= xmalloc_widget_value ();
1201 wv
->button_type
= BUTTON_TYPE_NONE
;
1206 /* Loop over all panes and items, filling in the tree. */
1208 while (i
< menu_items_used
)
1210 if (EQ (AREF (menu_items
, i
), Qnil
))
1212 submenu_stack
[submenu_depth
++] = save_wv
;
1218 else if (EQ (AREF (menu_items
, i
), Qlambda
))
1221 save_wv
= submenu_stack
[--submenu_depth
];
1225 else if (EQ (AREF (menu_items
, i
), Qt
)
1226 && submenu_depth
!= 0)
1227 i
+= MENU_ITEMS_PANE_LENGTH
;
1228 /* Ignore a nil in the item list.
1229 It's meaningful only for dialog boxes. */
1230 else if (EQ (AREF (menu_items
, i
), Qquote
))
1232 else if (EQ (AREF (menu_items
, i
), Qt
))
1234 /* Create a new pane. */
1235 Lisp_Object pane_name
, prefix
;
1237 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
1238 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
1240 if (STRINGP (pane_name
))
1242 if (unicode_append_menu
)
1243 pane_name
= ENCODE_UTF_8 (pane_name
);
1244 else if (STRING_MULTIBYTE (pane_name
))
1245 pane_name
= ENCODE_SYSTEM (pane_name
);
1247 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
1250 pane_string
= (NILP (pane_name
)
1251 ? "" : (char *) SDATA (pane_name
));
1252 /* If there is just one top-level pane, put all its items directly
1253 under the top-level menu. */
1254 if (menu_items_n_panes
== 1)
1257 /* If the pane has a meaningful name,
1258 make the pane a top-level menu item
1259 with its items as a submenu beneath it. */
1260 if (!keymaps
&& strcmp (pane_string
, ""))
1262 wv
= xmalloc_widget_value ();
1266 first_wv
->contents
= wv
;
1267 wv
->name
= pane_string
;
1268 if (keymaps
&& !NILP (prefix
))
1272 wv
->button_type
= BUTTON_TYPE_NONE
;
1277 else if (first_pane
)
1283 i
+= MENU_ITEMS_PANE_LENGTH
;
1287 /* Create a new item within current pane. */
1288 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
, help
;
1290 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
1291 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
1292 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
1293 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
1294 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
1295 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
1296 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
1298 if (STRINGP (item_name
))
1300 if (unicode_append_menu
)
1301 item_name
= ENCODE_UTF_8 (item_name
);
1302 else if (STRING_MULTIBYTE (item_name
))
1303 item_name
= ENCODE_SYSTEM (item_name
);
1305 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
1308 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
1310 descrip
= ENCODE_SYSTEM (descrip
);
1311 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
1314 wv
= xmalloc_widget_value ();
1318 save_wv
->contents
= wv
;
1319 wv
->name
= (char *) SDATA (item_name
);
1320 if (!NILP (descrip
))
1321 wv
->key
= (char *) SDATA (descrip
);
1323 /* Use the contents index as call_data, since we are
1324 restricted to 16-bits. */
1325 wv
->call_data
= !NILP (def
) ? (void *) (EMACS_INT
) i
: 0;
1326 wv
->enabled
= !NILP (enable
);
1329 wv
->button_type
= BUTTON_TYPE_NONE
;
1330 else if (EQ (type
, QCtoggle
))
1331 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
1332 else if (EQ (type
, QCradio
))
1333 wv
->button_type
= BUTTON_TYPE_RADIO
;
1337 wv
->selected
= !NILP (selected
);
1338 if (!STRINGP (help
))
1345 i
+= MENU_ITEMS_ITEM_LENGTH
;
1349 /* Deal with the title, if it is non-nil. */
1352 widget_value
*wv_title
= xmalloc_widget_value ();
1353 widget_value
*wv_sep
= xmalloc_widget_value ();
1355 /* Maybe replace this separator with a bitmap or owner-draw item
1356 so that it looks better. Having two separators looks odd. */
1357 wv_sep
->name
= "--";
1358 wv_sep
->next
= first_wv
->contents
;
1359 wv_sep
->help
= Qnil
;
1361 if (unicode_append_menu
)
1362 title
= ENCODE_UTF_8 (title
);
1363 else if (STRING_MULTIBYTE (title
))
1364 title
= ENCODE_SYSTEM (title
);
1366 wv_title
->name
= (char *) SDATA (title
);
1367 wv_title
->enabled
= TRUE
;
1368 wv_title
->title
= TRUE
;
1369 wv_title
->button_type
= BUTTON_TYPE_NONE
;
1370 wv_title
->help
= Qnil
;
1371 wv_title
->next
= wv_sep
;
1372 first_wv
->contents
= wv_title
;
1375 /* Actually create the menu. */
1376 current_popup_menu
= menu
= CreatePopupMenu ();
1377 fill_in_menu (menu
, first_wv
->contents
);
1379 /* Adjust coordinates to be root-window-relative. */
1382 ClientToScreen (FRAME_W32_WINDOW (f
), &pos
);
1384 /* No selection has been chosen yet. */
1385 menu_item_selection
= 0;
1387 /* Display the menu. */
1388 menu_item_selection
= SendMessage (FRAME_W32_WINDOW (f
),
1389 WM_EMACS_TRACKPOPUPMENU
,
1390 (WPARAM
)menu
, (LPARAM
)&pos
);
1392 /* Clean up extraneous mouse events which might have been generated
1394 discard_mouse_events ();
1396 /* Free the widget_value objects we used to specify the contents. */
1397 free_menubar_widget_value_tree (first_wv
);
1401 /* Free the owner-drawn and help-echo menu strings. */
1402 w32_free_menu_strings (FRAME_W32_WINDOW (f
));
1403 f
->output_data
.w32
->menubar_active
= 0;
1405 /* Find the selected item, and its pane, to return
1406 the proper value. */
1407 if (menu_item_selection
!= 0)
1409 Lisp_Object prefix
, entry
;
1411 prefix
= entry
= Qnil
;
1413 while (i
< menu_items_used
)
1415 if (EQ (AREF (menu_items
, i
), Qnil
))
1417 subprefix_stack
[submenu_depth
++] = prefix
;
1421 else if (EQ (AREF (menu_items
, i
), Qlambda
))
1423 prefix
= subprefix_stack
[--submenu_depth
];
1426 else if (EQ (AREF (menu_items
, i
), Qt
))
1428 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
1429 i
+= MENU_ITEMS_PANE_LENGTH
;
1431 /* Ignore a nil in the item list.
1432 It's meaningful only for dialog boxes. */
1433 else if (EQ (AREF (menu_items
, i
), Qquote
))
1437 entry
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_VALUE
);
1438 if (menu_item_selection
== i
)
1444 entry
= Fcons (entry
, Qnil
);
1446 entry
= Fcons (prefix
, entry
);
1447 for (j
= submenu_depth
- 1; j
>= 0; j
--)
1448 if (!NILP (subprefix_stack
[j
]))
1449 entry
= Fcons (subprefix_stack
[j
], entry
);
1453 i
+= MENU_ITEMS_ITEM_LENGTH
;
1457 else if (!for_click
)
1458 /* Make "Cancel" equivalent to C-g. */
1459 Fsignal (Qquit
, Qnil
);
1466 /* TODO: On Windows, there are two ways of defining a dialog.
1468 1. Create a predefined dialog resource and include it in nt/emacs.rc.
1469 Using this method, we could then set the titles and make unneeded
1470 buttons invisible before displaying the dialog. Everything would
1471 be a fixed size though, so there is a risk that text does not
1473 2. Create the dialog template in memory on the fly. This allows us
1474 to size the dialog and buttons dynamically, probably giving more
1475 natural looking results for dialogs with few buttons, and eliminating
1476 the problem of text overflowing the buttons. But the API for this is
1477 quite complex - structures have to be allocated in particular ways,
1478 text content is tacked onto the end of structures in variable length
1479 arrays with further structures tacked on after these, there are
1480 certain alignment requirements for all this, and we have to
1481 measure all the text and convert to "dialog coordinates" to figure
1482 out how big to make everything.
1484 For now, we'll just stick with menus for dialogs that are more
1485 complicated than simple yes/no type questions for which we can use
1486 the MessageBox function.
1489 static char * button_names
[] = {
1490 "button1", "button2", "button3", "button4", "button5",
1491 "button6", "button7", "button8", "button9", "button10" };
1494 w32_dialog_show (f
, keymaps
, title
, header
, error
)
1497 Lisp_Object title
, header
;
1500 int i
, nb_buttons
=0;
1501 char dialog_name
[6];
1502 int menu_item_selection
;
1504 widget_value
*wv
, *first_wv
= 0, *prev_wv
= 0;
1506 /* Number of elements seen so far, before boundary. */
1508 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
1509 int boundary_seen
= 0;
1513 if (menu_items_n_panes
> 1)
1515 *error
= "Multiple panes in dialog box";
1519 /* Create a tree of widget_value objects
1520 representing the text label and buttons. */
1522 Lisp_Object pane_name
, prefix
;
1524 pane_name
= AREF (menu_items
, MENU_ITEMS_PANE_NAME
);
1525 prefix
= AREF (menu_items
, MENU_ITEMS_PANE_PREFIX
);
1526 pane_string
= (NILP (pane_name
)
1527 ? "" : (char *) SDATA (pane_name
));
1528 prev_wv
= xmalloc_widget_value ();
1529 prev_wv
->value
= pane_string
;
1530 if (keymaps
&& !NILP (prefix
))
1532 prev_wv
->enabled
= 1;
1533 prev_wv
->name
= "message";
1534 prev_wv
->help
= Qnil
;
1537 /* Loop over all panes and items, filling in the tree. */
1538 i
= MENU_ITEMS_PANE_LENGTH
;
1539 while (i
< menu_items_used
)
1542 /* Create a new item within current pane. */
1543 Lisp_Object item_name
, enable
, descrip
, help
;
1545 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
1546 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
1547 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
1548 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
1550 if (NILP (item_name
))
1552 free_menubar_widget_value_tree (first_wv
);
1553 *error
= "Submenu in dialog items";
1556 if (EQ (item_name
, Qquote
))
1558 /* This is the boundary between left-side elts
1559 and right-side elts. Stop incrementing right_count. */
1564 if (nb_buttons
>= 9)
1566 free_menubar_widget_value_tree (first_wv
);
1567 *error
= "Too many dialog items";
1571 wv
= xmalloc_widget_value ();
1573 wv
->name
= (char *) button_names
[nb_buttons
];
1574 if (!NILP (descrip
))
1575 wv
->key
= (char *) SDATA (descrip
);
1576 wv
->value
= (char *) SDATA (item_name
);
1577 wv
->call_data
= (void *) &AREF (menu_items
, i
);
1578 wv
->enabled
= !NILP (enable
);
1582 if (! boundary_seen
)
1586 i
+= MENU_ITEMS_ITEM_LENGTH
;
1589 /* If the boundary was not specified,
1590 by default put half on the left and half on the right. */
1591 if (! boundary_seen
)
1592 left_count
= nb_buttons
- nb_buttons
/ 2;
1594 wv
= xmalloc_widget_value ();
1595 wv
->name
= dialog_name
;
1598 /* Frame title: 'Q' = Question, 'I' = Information.
1599 Can also have 'E' = Error if, one day, we want
1600 a popup for errors. */
1602 dialog_name
[0] = 'Q';
1604 dialog_name
[0] = 'I';
1606 /* Dialog boxes use a really stupid name encoding
1607 which specifies how many buttons to use
1608 and how many buttons are on the right. */
1609 dialog_name
[1] = '0' + nb_buttons
;
1610 dialog_name
[2] = 'B';
1611 dialog_name
[3] = 'R';
1612 /* Number of buttons to put on the right. */
1613 dialog_name
[4] = '0' + nb_buttons
- left_count
;
1615 wv
->contents
= first_wv
;
1619 /* Actually create the dialog. */
1620 dialog_id
= widget_id_tick
++;
1621 menu
= lw_create_widget (first_wv
->name
, "dialog", dialog_id
, first_wv
,
1622 f
->output_data
.w32
->widget
, 1, 0,
1623 dialog_selection_callback
, 0);
1624 lw_modify_all_widgets (dialog_id
, first_wv
->contents
, TRUE
);
1626 /* Free the widget_value objects we used to specify the contents. */
1627 free_menubar_widget_value_tree (first_wv
);
1629 /* No selection has been chosen yet. */
1630 menu_item_selection
= 0;
1632 /* Display the menu. */
1633 lw_pop_up_all_widgets (dialog_id
);
1635 /* Process events that apply to the menu. */
1636 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
), dialog_id
);
1638 lw_destroy_all_widgets (dialog_id
);
1640 /* Find the selected item, and its pane, to return
1641 the proper value. */
1642 if (menu_item_selection
!= 0)
1648 while (i
< menu_items_used
)
1652 if (EQ (AREF (menu_items
, i
), Qt
))
1654 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
1655 i
+= MENU_ITEMS_PANE_LENGTH
;
1659 entry
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_VALUE
);
1660 if (menu_item_selection
== i
)
1664 entry
= Fcons (entry
, Qnil
);
1666 entry
= Fcons (prefix
, entry
);
1670 i
+= MENU_ITEMS_ITEM_LENGTH
;
1675 /* Make "Cancel" equivalent to C-g. */
1676 Fsignal (Qquit
, Qnil
);
1680 #else /* !HAVE_DIALOGS */
1682 /* Currently we only handle Yes No dialogs (y-or-n-p and yes-or-no-p) as
1683 simple dialogs. We could handle a few more, but I'm not aware of
1684 anywhere in Emacs that uses the other specific dialog choices that
1685 MessageBox provides. */
1687 static int is_simple_dialog (contents
)
1688 Lisp_Object contents
;
1690 Lisp_Object options
= XCDR (contents
);
1691 Lisp_Object name
, yes
, no
, other
;
1693 yes
= build_string ("Yes");
1694 no
= build_string ("No");
1696 if (!CONSP (options
))
1699 name
= XCAR (XCAR (options
));
1700 if (!CONSP (options
))
1703 if (!NILP (Fstring_equal (name
, yes
)))
1705 else if (!NILP (Fstring_equal (name
, no
)))
1710 options
= XCDR (options
);
1711 if (!CONSP (options
))
1714 name
= XCAR (XCAR (options
));
1715 if (NILP (Fstring_equal (name
, other
)))
1718 /* Check there are no more options. */
1719 options
= XCDR (options
);
1720 return !(CONSP (options
));
1723 static Lisp_Object
simple_dialog_show (f
, contents
, header
)
1725 Lisp_Object contents
, header
;
1730 Lisp_Object lispy_answer
= Qnil
, temp
= XCAR (contents
);
1733 text
= SDATA (temp
);
1740 type
= MB_ICONQUESTION
;
1744 title
= "Information";
1745 type
= MB_ICONINFORMATION
;
1749 /* Since we only handle Yes/No dialogs, and we already checked
1750 is_simple_dialog, we don't need to worry about checking contents
1751 to see what type of dialog to use. */
1752 answer
= MessageBox (FRAME_W32_WINDOW (f
), text
, title
, type
);
1754 if (answer
== IDYES
)
1755 lispy_answer
= build_string ("Yes");
1756 else if (answer
== IDNO
)
1757 lispy_answer
= build_string ("No");
1759 Fsignal (Qquit
, Qnil
);
1761 for (temp
= XCDR (contents
); CONSP (temp
); temp
= XCDR (temp
))
1763 Lisp_Object item
, name
, value
;
1768 value
= XCDR (item
);
1776 if (!NILP (Fstring_equal (name
, lispy_answer
)))
1781 Fsignal (Qquit
, Qnil
);
1784 #endif /* !HAVE_DIALOGS */
1787 /* Is this item a separator? */
1789 name_is_separator (name
)
1794 /* Check if name string consists of only dashes ('-'). */
1795 while (*name
== '-') name
++;
1796 /* Separators can also be of the form "--:TripleSuperMegaEtched"
1797 or "--deep-shadow". We don't implement them yet, se we just treat
1798 them like normal separators. */
1799 return (*name
== '\0' || start
+ 2 == name
);
1803 /* Indicate boundary between left and right. */
1805 add_left_right_boundary (HMENU menu
)
1807 return AppendMenu (menu
, MF_MENUBARBREAK
, 0, NULL
);
1810 /* UTF8: 0xxxxxxx, 110xxxxx 10xxxxxx, 1110xxxx, 10xxxxxx, 10xxxxxx */
1812 utf8to16 (unsigned char * src
, int len
, WCHAR
* dest
)
1819 *dest
= (WCHAR
) *src
;
1820 dest
++; src
++; len
--;
1822 /* Since we might get >3 byte sequences which we don't handle, ignore the extra parts. */
1823 else if (*src
< 0xC0)
1827 /* 2 char UTF-8 sequence. */
1828 else if (*src
< 0xE0)
1830 *dest
= (WCHAR
) (((*src
& 0x1f) << 6)
1831 | (*(src
+ 1) & 0x3f));
1832 src
+= 2; len
-= 2; dest
++;
1834 else if (*src
< 0xF0)
1836 *dest
= (WCHAR
) (((*src
& 0x0f) << 12)
1837 | ((*(src
+ 1) & 0x3f) << 6)
1838 | (*(src
+ 2) & 0x3f));
1839 src
+= 3; len
-= 3; dest
++;
1841 else /* Not encodable. Insert Unicode Substitution char. */
1843 *dest
= (WCHAR
) 0xfffd;
1844 src
++; len
--; dest
++;
1851 add_menu_item (HMENU menu
, widget_value
*wv
, HMENU item
)
1854 char *out_string
, *p
, *q
;
1856 size_t nlen
, orig_len
;
1858 if (name_is_separator (wv
->name
))
1860 fuFlags
= MF_SEPARATOR
;
1866 fuFlags
= MF_STRING
;
1868 fuFlags
= MF_STRING
| MF_GRAYED
;
1870 if (wv
->key
!= NULL
)
1872 out_string
= alloca (strlen (wv
->name
) + strlen (wv
->key
) + 2);
1873 strcpy (out_string
, wv
->name
);
1874 strcat (out_string
, "\t");
1875 strcat (out_string
, wv
->key
);
1878 out_string
= wv
->name
;
1880 /* Quote any special characters within the menu item's text and
1882 nlen
= orig_len
= strlen (out_string
);
1883 if (unicode_append_menu
)
1885 /* With UTF-8, & cannot be part of a multibyte character. */
1886 for (p
= out_string
; *p
; p
++)
1894 /* If encoded with the system codepage, use multibyte string
1895 functions in case of multibyte characters that contain '&'. */
1896 for (p
= out_string
; *p
; p
= _mbsinc (p
))
1898 if (_mbsnextc (p
) == '&')
1903 if (nlen
> orig_len
)
1906 out_string
= alloca (nlen
+ 1);
1910 if (unicode_append_menu
)
1918 if (_mbsnextc (p
) == '&')
1933 else if (wv
->title
|| wv
->call_data
== 0)
1935 /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since
1936 we can't deallocate the memory otherwise. */
1937 if (get_menu_item_info
)
1939 out_string
= (char *) local_alloc (strlen (wv
->name
) + 1);
1940 strcpy (out_string
, wv
->name
);
1942 DebPrint ("Menu: allocing %ld for owner-draw", out_string
);
1944 fuFlags
= MF_OWNERDRAW
| MF_DISABLED
;
1947 fuFlags
= MF_DISABLED
;
1950 /* Draw radio buttons and tickboxes. */
1951 else if (wv
->selected
&& (wv
->button_type
== BUTTON_TYPE_TOGGLE
||
1952 wv
->button_type
== BUTTON_TYPE_RADIO
))
1953 fuFlags
|= MF_CHECKED
;
1955 fuFlags
|= MF_UNCHECKED
;
1958 if (unicode_append_menu
&& out_string
)
1960 /* Convert out_string from UTF-8 to UTF-16-LE. */
1961 int utf8_len
= strlen (out_string
);
1962 WCHAR
* utf16_string
;
1963 if (fuFlags
& MF_OWNERDRAW
)
1964 utf16_string
= local_alloc ((utf8_len
+ 1) * sizeof (WCHAR
));
1966 utf16_string
= alloca ((utf8_len
+ 1) * sizeof (WCHAR
));
1968 utf8to16 (out_string
, utf8_len
, utf16_string
);
1969 return_value
= unicode_append_menu (menu
, fuFlags
,
1970 item
!= NULL
? (UINT
) item
1971 : (UINT
) wv
->call_data
,
1975 /* On W9x/ME, unicode menus are not supported, though AppendMenuW
1976 apparently does exist at least in some cases and appears to be
1977 stubbed out to do nothing. out_string is UTF-8, but since
1978 our standard menus are in English and this is only going to
1979 happen the first time a menu is used, the encoding is
1980 of minor importance compared with menus not working at all. */
1982 AppendMenu (menu
, fuFlags
,
1983 item
!= NULL
? (UINT
) item
: (UINT
) wv
->call_data
,
1985 /* Don't use unicode menus in future. */
1986 unicode_append_menu
= NULL
;
1989 if (unicode_append_menu
&& (fuFlags
& MF_OWNERDRAW
))
1990 local_free (out_string
);
1997 item
!= NULL
? (UINT
) item
: (UINT
) wv
->call_data
,
2001 /* This must be done after the menu item is created. */
2002 if (!wv
->title
&& wv
->call_data
!= 0)
2004 if (set_menu_item_info
)
2007 bzero (&info
, sizeof (info
));
2008 info
.cbSize
= sizeof (info
);
2009 info
.fMask
= MIIM_DATA
;
2011 /* Set help string for menu item. Leave it as a Lisp_Object
2012 until it is ready to be displayed, since GC can happen while
2013 menus are active. */
2014 if (!NILP (wv
->help
))
2015 #ifdef USE_LISP_UNION_TYPE
2016 info
.dwItemData
= (DWORD
) (wv
->help
).i
;
2018 info
.dwItemData
= (DWORD
) (wv
->help
);
2020 if (wv
->button_type
== BUTTON_TYPE_RADIO
)
2022 /* CheckMenuRadioItem allows us to differentiate TOGGLE and
2023 RADIO items, but is not available on NT 3.51 and earlier. */
2024 info
.fMask
|= MIIM_TYPE
| MIIM_STATE
;
2025 info
.fType
= MFT_RADIOCHECK
| MFT_STRING
;
2026 info
.dwTypeData
= out_string
;
2027 info
.fState
= wv
->selected
? MFS_CHECKED
: MFS_UNCHECKED
;
2030 set_menu_item_info (menu
,
2031 item
!= NULL
? (UINT
) item
: (UINT
) wv
->call_data
,
2035 return return_value
;
2038 /* Construct native Windows menu(bar) based on widget_value tree. */
2040 fill_in_menu (HMENU menu
, widget_value
*wv
)
2042 int items_added
= 0;
2044 for ( ; wv
!= NULL
; wv
= wv
->next
)
2048 HMENU sub_menu
= CreatePopupMenu ();
2050 if (sub_menu
== NULL
)
2053 if (!fill_in_menu (sub_menu
, wv
->contents
) ||
2054 !add_menu_item (menu
, wv
, sub_menu
))
2056 DestroyMenu (sub_menu
);
2062 if (!add_menu_item (menu
, wv
, NULL
))
2069 /* Display help string for currently pointed to menu item. Not
2070 supported on NT 3.51 and earlier, as GetMenuItemInfo is not
2073 w32_menu_display_help (HWND owner
, HMENU menu
, UINT item
, UINT flags
)
2075 if (get_menu_item_info
)
2077 struct frame
*f
= x_window_to_frame (&one_w32_display_info
, owner
);
2078 Lisp_Object frame
, help
;
2080 /* No help echo on owner-draw menu items, or when the keyboard is used
2081 to navigate the menus, since tooltips are distracting if they pop
2083 if (flags
& MF_OWNERDRAW
|| flags
& MF_POPUP
2084 || !(flags
& MF_MOUSESELECT
))
2090 bzero (&info
, sizeof (info
));
2091 info
.cbSize
= sizeof (info
);
2092 info
.fMask
= MIIM_DATA
;
2093 get_menu_item_info (menu
, item
, FALSE
, &info
);
2095 #ifdef USE_LISP_UNION_TYPE
2096 help
= info
.dwItemData
? (Lisp_Object
) ((EMACS_INT
) info
.dwItemData
)
2099 help
= info
.dwItemData
? (Lisp_Object
) info
.dwItemData
: Qnil
;
2103 /* Store the help echo in the keyboard buffer as the X toolkit
2104 version does, rather than directly showing it. This seems to
2105 solve the GC problems that were present when we based the
2106 Windows code on the non-toolkit version. */
2109 XSETFRAME (frame
, f
);
2110 kbd_buffer_store_help_event (frame
, help
);
2113 /* X version has a loop through frames here, which doesn't
2114 appear to do anything, unless it has some side effect. */
2115 show_help_echo (help
, Qnil
, Qnil
, Qnil
, 1);
2119 /* Free memory used by owner-drawn strings. */
2121 w32_free_submenu_strings (menu
)
2124 int i
, num
= GetMenuItemCount (menu
);
2125 for (i
= 0; i
< num
; i
++)
2128 bzero (&info
, sizeof (info
));
2129 info
.cbSize
= sizeof (info
);
2130 info
.fMask
= MIIM_DATA
| MIIM_TYPE
| MIIM_SUBMENU
;
2132 get_menu_item_info (menu
, i
, TRUE
, &info
);
2134 /* Owner-drawn names are held in dwItemData. */
2135 if ((info
.fType
& MF_OWNERDRAW
) && info
.dwItemData
)
2138 DebPrint ("Menu: freeing %ld for owner-draw", info
.dwItemData
);
2140 local_free (info
.dwItemData
);
2143 /* Recurse down submenus. */
2145 w32_free_submenu_strings (info
.hSubMenu
);
2150 w32_free_menu_strings (hwnd
)
2153 HMENU menu
= current_popup_menu
;
2155 if (get_menu_item_info
)
2157 /* If there is no popup menu active, free the strings from the frame's
2160 menu
= GetMenu (hwnd
);
2163 w32_free_submenu_strings (menu
);
2166 current_popup_menu
= NULL
;
2169 #endif /* HAVE_MENUS */
2171 /* The following is used by delayed window autoselection. */
2173 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p
, Smenu_or_popup_active_p
, 0, 0, 0,
2174 doc
: /* Return t if a menu or popup dialog is active on selected frame. */)
2179 f
= SELECTED_FRAME ();
2180 return (f
->output_data
.w32
->menubar_active
> 0) ? Qt
: Qnil
;
2183 #endif /* HAVE_MENUS */
2186 void syms_of_w32menu ()
2188 globals_of_w32menu ();
2189 staticpro (&menu_items
);
2192 current_popup_menu
= NULL
;
2194 DEFSYM (Qdebug_on_next_call
, "debug-on-next-call");
2196 defsubr (&Sx_popup_menu
);
2197 defsubr (&Smenu_or_popup_active_p
);
2199 defsubr (&Sx_popup_dialog
);
2204 globals_of_w32menu is used to initialize those global variables that
2205 must always be initialized on startup even when the global variable
2206 initialized is non zero (see the function main in emacs.c).
2207 globals_of_w32menu is called from syms_of_w32menu when the global
2208 variable initialized is 0 and directly from main when initialized
2211 void globals_of_w32menu ()
2213 /* See if Get/SetMenuItemInfo functions are available. */
2214 HMODULE user32
= GetModuleHandle ("user32.dll");
2215 get_menu_item_info
= (GetMenuItemInfoA_Proc
) GetProcAddress (user32
, "GetMenuItemInfoA");
2216 set_menu_item_info
= (SetMenuItemInfoA_Proc
) GetProcAddress (user32
, "SetMenuItemInfoA");
2217 unicode_append_menu
= (AppendMenuW_Proc
) GetProcAddress (user32
, "AppendMenuW");
2220 /* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0
2221 (do not change this comment) */