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, 2009
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/>. */
32 #include "termhooks.h"
34 #include "blockinput.h"
37 #include "character.h"
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
44 /* Load sys/types.h if not already loaded.
45 In some systems loading it twice is suicidal. */
47 #include <sys/types.h>
50 #include "dispextern.h"
52 #undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
59 HMENU current_popup_menu
;
61 void syms_of_w32menu ();
62 void globals_of_w32menu ();
64 typedef BOOL (WINAPI
* GetMenuItemInfoA_Proc
) (
68 IN OUT LPMENUITEMINFOA
);
69 typedef BOOL (WINAPI
* SetMenuItemInfoA_Proc
) (
75 GetMenuItemInfoA_Proc get_menu_item_info
= NULL
;
76 SetMenuItemInfoA_Proc set_menu_item_info
= NULL
;
77 AppendMenuW_Proc unicode_append_menu
= NULL
;
79 Lisp_Object Qdebug_on_next_call
;
81 extern Lisp_Object Vmenu_updating_frame
;
83 extern Lisp_Object Qmenu_bar
;
85 extern Lisp_Object QCtoggle
, QCradio
;
87 extern Lisp_Object Voverriding_local_map
;
88 extern Lisp_Object Voverriding_local_map_menu_flag
;
90 extern Lisp_Object Qoverriding_local_map
, Qoverriding_terminal_local_map
;
92 extern Lisp_Object Qmenu_bar_update_hook
;
94 void set_frame_menubar
P_ ((FRAME_PTR
, int, int));
97 static Lisp_Object w32_dialog_show
P_ ((FRAME_PTR
, int, Lisp_Object
, char**));
99 static int is_simple_dialog
P_ ((Lisp_Object
));
100 static Lisp_Object simple_dialog_show
P_ ((FRAME_PTR
, Lisp_Object
, Lisp_Object
));
102 static Lisp_Object w32_menu_show
P_ ((FRAME_PTR
, int, int, int, int,
103 Lisp_Object
, char **));
105 void w32_free_menu_strings
P_((HWND
));
108 /* This is set nonzero after the user activates the menu bar, and set
109 to zero again after the menu bars are redisplayed by prepare_menu_bar.
110 While it is nonzero, all calls to set_frame_menubar go deep.
112 I don't understand why this is needed, but it does seem to be
113 needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
115 int pending_menu_activation
;
118 /* Return the frame whose ->output_data.w32->menubar_widget equals
121 static struct frame
*
122 menubar_id_to_frame (id
)
125 Lisp_Object tail
, frame
;
128 for (tail
= Vframe_list
; CONSP (tail
); tail
= XCDR (tail
))
134 if (!FRAME_WINDOW_P (f
))
136 if (f
->output_data
.w32
->menubar_widget
== id
)
142 DEFUN ("x-popup-menu", Fx_popup_menu
, Sx_popup_menu
, 2, 2, 0,
143 doc
: /* Pop up a deck-of-cards menu and return user's selection.
144 POSITION is a position specification. This is either a mouse button
145 event or a list ((XOFFSET YOFFSET) WINDOW) where XOFFSET and YOFFSET
146 are positions in pixels from the top left corner of WINDOW's frame
147 \(WINDOW may be a frame object instead of a window). This controls the
148 position of the center of the first line in the first pane of the
149 menu, not the top left of the menu as a whole. If POSITION is t, it
150 means to use the current mouse position.
152 MENU is a specifier for a menu. For the simplest case, MENU is a keymap.
153 The menu items come from key bindings that have a menu string as well as
154 a definition; actually, the \"definition\" in such a key binding looks like
155 \(STRING . REAL-DEFINITION). To give the menu a title, put a string into
156 the keymap as a top-level element.
158 If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.
159 Otherwise, REAL-DEFINITION should be a valid key binding definition.
161 You can also use a list of keymaps as MENU. Then each keymap makes a
162 separate pane. When MENU is a keymap or a list of keymaps, the return
163 value is a list of events.
165 Alternatively, you can specify a menu of multiple panes with a list of
166 the form (TITLE PANE1 PANE2...), where each pane is a list of
167 form (TITLE ITEM1 ITEM2...).
168 Each ITEM is normally a cons cell (STRING . VALUE); but a string can
169 appear as an item--that makes a nonselectable line in the menu.
170 With this form of menu, the return value is VALUE from the chosen item.
172 If POSITION is nil, don't display the menu at all, just precalculate the
173 cached information about equivalent key sequences. */)
175 Lisp_Object position
, menu
;
177 Lisp_Object keymap
, tem
;
178 int xpos
= 0, ypos
= 0;
181 Lisp_Object selection
;
183 Lisp_Object x
, y
, window
;
186 int specpdl_count
= SPECPDL_INDEX ();
190 if (! NILP (position
))
194 /* Decode the first argument: find the window and the coordinates. */
195 if (EQ (position
, Qt
)
196 || (CONSP (position
) && (EQ (XCAR (position
), Qmenu_bar
)
197 || EQ (XCAR (position
), Qtool_bar
))))
199 /* Use the mouse's current position. */
200 FRAME_PTR new_f
= SELECTED_FRAME ();
201 Lisp_Object bar_window
;
202 enum scroll_bar_part part
;
205 if (FRAME_TERMINAL (new_f
)->mouse_position_hook
)
206 (*FRAME_TERMINAL (new_f
)->mouse_position_hook
) (&new_f
, 1, &bar_window
,
207 &part
, &x
, &y
, &time
);
209 XSETFRAME (window
, new_f
);
212 window
= selected_window
;
219 tem
= Fcar (position
);
222 window
= Fcar (Fcdr (position
));
224 y
= Fcar (Fcdr (tem
));
229 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
230 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
231 tem
= Fcar (Fcdr (Fcdr (tem
))); /* POSN_WINDOW_POSN (tem) */
240 /* Decode where to put the menu. */
248 else if (WINDOWP (window
))
250 CHECK_LIVE_WINDOW (window
);
251 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
253 xpos
= WINDOW_LEFT_EDGE_X (XWINDOW (window
));
254 ypos
= WINDOW_TOP_EDGE_Y (XWINDOW (window
));
257 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
258 but I don't want to make one now. */
259 CHECK_WINDOW (window
);
264 XSETFRAME (Vmenu_updating_frame
, f
);
267 Vmenu_updating_frame
= Qnil
;
268 #endif /* HAVE_MENUS */
270 record_unwind_protect (unuse_menu_items
, Qnil
);
275 /* Decode the menu items from what was specified. */
277 keymap
= get_keymap (menu
, 0, 0);
280 /* We were given a keymap. Extract menu info from the keymap. */
283 /* Extract the detailed info to make one pane. */
284 keymap_panes (&menu
, 1, NILP (position
));
286 /* Search for a string appearing directly as an element of the keymap.
287 That string is the title of the menu. */
288 prompt
= Fkeymap_prompt (keymap
);
289 if (NILP (title
) && !NILP (prompt
))
292 /* Make that be the pane title of the first pane. */
293 if (!NILP (prompt
) && menu_items_n_panes
>= 0)
294 ASET (menu_items
, MENU_ITEMS_PANE_NAME
, prompt
);
298 else if (CONSP (menu
) && KEYMAPP (XCAR (menu
)))
300 /* We were given a list of keymaps. */
301 int nmaps
= XFASTINT (Flength (menu
));
303 = (Lisp_Object
*) alloca (nmaps
* sizeof (Lisp_Object
));
308 /* The first keymap that has a prompt string
309 supplies the menu title. */
310 for (tem
= menu
, i
= 0; CONSP (tem
); tem
= Fcdr (tem
))
314 maps
[i
++] = keymap
= get_keymap (Fcar (tem
), 1, 0);
316 prompt
= Fkeymap_prompt (keymap
);
317 if (NILP (title
) && !NILP (prompt
))
321 /* Extract the detailed info to make one pane. */
322 keymap_panes (maps
, nmaps
, NILP (position
));
324 /* Make the title be the pane title of the first pane. */
325 if (!NILP (title
) && menu_items_n_panes
>= 0)
326 ASET (menu_items
, MENU_ITEMS_PANE_NAME
, title
);
332 /* We were given an old-fashioned menu. */
334 CHECK_STRING (title
);
336 list_of_panes (Fcdr (menu
));
341 unbind_to (specpdl_count
, Qnil
);
345 discard_menu_items ();
346 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
352 /* If resources from a previous popup menu still exist, does nothing
353 until the `menu_free_timer' has freed them (see w32fns.c). This
354 can occur if you press ESC or click outside a menu without selecting
357 if (current_popup_menu
)
359 discard_menu_items ();
360 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
365 /* Display them in a menu. */
368 selection
= w32_menu_show (f
, xpos
, ypos
, for_click
,
369 keymaps
, title
, &error_name
);
372 discard_menu_items ();
373 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
375 #endif /* HAVE_MENUS */
379 if (error_name
) error (error_name
);
385 DEFUN ("x-popup-dialog", Fx_popup_dialog
, Sx_popup_dialog
, 2, 3, 0,
386 doc
: /* Pop up a dialog box and return user's selection.
387 POSITION specifies which frame to use.
388 This is normally a mouse button event or a window or frame.
389 If POSITION is t, it means to use the frame the mouse is on.
390 The dialog box appears in the middle of the specified frame.
392 CONTENTS specifies the alternatives to display in the dialog box.
393 It is a list of the form (TITLE ITEM1 ITEM2...).
394 Each ITEM is a cons cell (STRING . VALUE).
395 The return value is VALUE from the chosen item.
397 An ITEM may also be just a string--that makes a nonselectable item.
398 An ITEM may also be nil--that means to put all preceding items
399 on the left of the dialog box and all following items on the right.
400 \(By default, approximately half appear on each side.)
402 If HEADER is non-nil, the frame title for the box is "Information",
403 otherwise it is "Question". */)
404 (position
, contents
, header
)
405 Lisp_Object position
, contents
, header
;
412 /* Decode the first argument: find the window or frame to use. */
413 if (EQ (position
, Qt
)
414 || (CONSP (position
) && (EQ (XCAR (position
), Qmenu_bar
)
415 || EQ (XCAR (position
), Qtool_bar
))))
417 #if 0 /* Using the frame the mouse is on may not be right. */
418 /* Use the mouse's current position. */
419 FRAME_PTR new_f
= SELECTED_FRAME ();
420 Lisp_Object bar_window
;
421 enum scroll_bar_part part
;
425 (*mouse_position_hook
) (&new_f
, 1, &bar_window
, &part
, &x
, &y
, &time
);
428 XSETFRAME (window
, new_f
);
430 window
= selected_window
;
432 window
= selected_window
;
434 else if (CONSP (position
))
437 tem
= Fcar (position
);
439 window
= Fcar (Fcdr (position
));
442 tem
= Fcar (Fcdr (position
)); /* EVENT_START (position) */
443 window
= Fcar (tem
); /* POSN_WINDOW (tem) */
446 else if (WINDOWP (position
) || FRAMEP (position
))
451 /* Decode where to put the menu. */
455 else if (WINDOWP (window
))
457 CHECK_LIVE_WINDOW (window
);
458 f
= XFRAME (WINDOW_FRAME (XWINDOW (window
)));
461 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
462 but I don't want to make one now. */
463 CHECK_WINDOW (window
);
468 /* Handle simple Yes/No choices as MessageBox popups. */
469 if (is_simple_dialog (contents
))
470 return simple_dialog_show (f
, contents
, header
);
473 /* Display a menu with these alternatives
474 in the middle of frame F. */
475 Lisp_Object x
, y
, frame
, newpos
;
476 XSETFRAME (frame
, f
);
477 XSETINT (x
, x_pixel_width (f
) / 2);
478 XSETINT (y
, x_pixel_height (f
) / 2);
479 newpos
= Fcons (Fcons (x
, Fcons (y
, Qnil
)), Fcons (frame
, Qnil
));
480 return Fx_popup_menu (newpos
,
481 Fcons (Fcar (contents
), Fcons (contents
, Qnil
)));
484 #else /* HAVE_DIALOGS */
488 Lisp_Object selection
;
490 /* Decode the dialog items from what was specified. */
491 title
= Fcar (contents
);
492 CHECK_STRING (title
);
494 list_of_panes (Fcons (contents
, Qnil
));
496 /* Display them in a dialog box. */
498 selection
= w32_dialog_show (f
, 0, title
, header
, &error_name
);
501 discard_menu_items ();
502 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
504 if (error_name
) error (error_name
);
507 #endif /* HAVE_DIALOGS */
510 /* Activate the menu bar of frame F.
511 This is called from keyboard.c when it gets the
512 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
514 To activate the menu bar, we signal to the input thread that it can
515 return from the WM_INITMENU message, allowing the normal Windows
516 processing of the menus.
518 But first we recompute the menu bar contents (the whole tree).
520 This way we can safely execute Lisp code. */
523 x_activate_menubar (f
)
526 set_frame_menubar (f
, 0, 1);
528 /* Lock out further menubar changes while active. */
529 f
->output_data
.w32
->menubar_active
= 1;
531 /* Signal input thread to return from WM_INITMENU. */
532 complete_deferred_msg (FRAME_W32_WINDOW (f
), WM_INITMENU
, 0);
535 /* This callback is called from the menu bar pulldown menu
536 when the user makes a selection.
537 Figure out what the user chose
538 and put the appropriate events into the keyboard buffer. */
541 menubar_selection_callback (FRAME_PTR f
, void * client_data
)
543 Lisp_Object prefix
, entry
;
545 Lisp_Object
*subprefix_stack
;
546 int submenu_depth
= 0;
552 subprefix_stack
= (Lisp_Object
*) alloca (f
->menu_bar_items_used
* sizeof (Lisp_Object
));
553 vector
= f
->menu_bar_vector
;
556 while (i
< f
->menu_bar_items_used
)
558 if (EQ (AREF (vector
, i
), Qnil
))
560 subprefix_stack
[submenu_depth
++] = prefix
;
564 else if (EQ (AREF (vector
, i
), Qlambda
))
566 prefix
= subprefix_stack
[--submenu_depth
];
569 else if (EQ (AREF (vector
, i
), Qt
))
571 prefix
= AREF (vector
, i
+ MENU_ITEMS_PANE_PREFIX
);
572 i
+= MENU_ITEMS_PANE_LENGTH
;
576 entry
= AREF (vector
, i
+ MENU_ITEMS_ITEM_VALUE
);
577 /* The EMACS_INT cast avoids a warning. There's no problem
578 as long as pointers have enough bits to hold small integers. */
579 if ((int) (EMACS_INT
) client_data
== i
)
582 struct input_event buf
;
586 XSETFRAME (frame
, f
);
587 buf
.kind
= MENU_BAR_EVENT
;
588 buf
.frame_or_window
= frame
;
590 kbd_buffer_store_event (&buf
);
592 for (j
= 0; j
< submenu_depth
; j
++)
593 if (!NILP (subprefix_stack
[j
]))
595 buf
.kind
= MENU_BAR_EVENT
;
596 buf
.frame_or_window
= frame
;
597 buf
.arg
= subprefix_stack
[j
];
598 kbd_buffer_store_event (&buf
);
603 buf
.kind
= MENU_BAR_EVENT
;
604 buf
.frame_or_window
= frame
;
606 kbd_buffer_store_event (&buf
);
609 buf
.kind
= MENU_BAR_EVENT
;
610 buf
.frame_or_window
= frame
;
612 /* Free memory used by owner-drawn and help-echo strings. */
613 w32_free_menu_strings (FRAME_W32_WINDOW (f
));
614 kbd_buffer_store_event (&buf
);
616 f
->output_data
.w32
->menubar_active
= 0;
619 i
+= MENU_ITEMS_ITEM_LENGTH
;
622 /* Free memory used by owner-drawn and help-echo strings. */
623 w32_free_menu_strings (FRAME_W32_WINDOW (f
));
624 f
->output_data
.w32
->menubar_active
= 0;
628 /* Set the contents of the menubar widgets of frame F.
629 The argument FIRST_TIME is currently ignored;
630 it is set the first time this is called, from initialize_frame_menubar. */
633 set_frame_menubar (f
, first_time
, deep_p
)
638 HMENU menubar_widget
= f
->output_data
.w32
->menubar_widget
;
640 widget_value
*wv
, *first_wv
, *prev_wv
= 0;
642 int *submenu_start
, *submenu_end
;
643 int *submenu_top_level_items
, *submenu_n_panes
;
645 /* We must not change the menubar when actually in use. */
646 if (f
->output_data
.w32
->menubar_active
)
649 XSETFRAME (Vmenu_updating_frame
, f
);
651 if (! menubar_widget
)
653 else if (pending_menu_activation
&& !deep_p
)
658 /* Make a widget-value tree representing the entire menu trees. */
660 struct buffer
*prev
= current_buffer
;
662 int specpdl_count
= SPECPDL_INDEX ();
663 int previous_menu_items_used
= f
->menu_bar_items_used
;
664 Lisp_Object
*previous_items
665 = (Lisp_Object
*) alloca (previous_menu_items_used
666 * sizeof (Lisp_Object
));
668 /* If we are making a new widget, its contents are empty,
669 do always reinitialize them. */
670 if (! menubar_widget
)
671 previous_menu_items_used
= 0;
673 buffer
= XWINDOW (FRAME_SELECTED_WINDOW (f
))->buffer
;
674 specbind (Qinhibit_quit
, Qt
);
675 /* Don't let the debugger step into this code
676 because it is not reentrant. */
677 specbind (Qdebug_on_next_call
, Qnil
);
679 record_unwind_save_match_data ();
681 if (NILP (Voverriding_local_map_menu_flag
))
683 specbind (Qoverriding_terminal_local_map
, Qnil
);
684 specbind (Qoverriding_local_map
, Qnil
);
687 set_buffer_internal_1 (XBUFFER (buffer
));
689 /* Run the Lucid hook. */
690 safe_run_hooks (Qactivate_menubar_hook
);
691 /* If it has changed current-menubar from previous value,
692 really recompute the menubar from the value. */
693 if (! NILP (Vlucid_menu_bar_dirty_flag
))
694 call0 (Qrecompute_lucid_menubar
);
695 safe_run_hooks (Qmenu_bar_update_hook
);
696 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
698 items
= FRAME_MENU_BAR_ITEMS (f
);
700 /* Save the frame's previous menu bar contents data. */
701 if (previous_menu_items_used
)
702 bcopy (XVECTOR (f
->menu_bar_vector
)->contents
, previous_items
,
703 previous_menu_items_used
* sizeof (Lisp_Object
));
705 /* Fill in menu_items with the current menu bar contents.
706 This can evaluate Lisp code. */
709 menu_items
= f
->menu_bar_vector
;
710 menu_items_allocated
= VECTORP (menu_items
) ? ASIZE (menu_items
) : 0;
711 submenu_start
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
712 submenu_end
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
713 submenu_n_panes
= (int *) alloca (XVECTOR (items
)->size
* sizeof (int));
714 submenu_top_level_items
715 = (int *) alloca (XVECTOR (items
)->size
* sizeof (int *));
717 for (i
= 0; i
< ASIZE (items
); i
+= 4)
719 Lisp_Object key
, string
, maps
;
723 key
= AREF (items
, i
);
724 string
= AREF (items
, i
+ 1);
725 maps
= AREF (items
, i
+ 2);
729 submenu_start
[i
] = menu_items_used
;
731 menu_items_n_panes
= 0;
732 submenu_top_level_items
[i
]
733 = parse_single_submenu (key
, string
, maps
);
734 submenu_n_panes
[i
] = menu_items_n_panes
;
736 submenu_end
[i
] = menu_items_used
;
739 finish_menu_items ();
741 /* Convert menu_items into widget_value trees
742 to display the menu. This cannot evaluate Lisp code. */
744 wv
= xmalloc_widget_value ();
745 wv
->name
= "menubar";
748 wv
->button_type
= BUTTON_TYPE_NONE
;
752 for (i
= 0; i
< last_i
; i
+= 4)
754 menu_items_n_panes
= submenu_n_panes
[i
];
755 wv
= digest_single_submenu (submenu_start
[i
], submenu_end
[i
],
756 submenu_top_level_items
[i
]);
760 first_wv
->contents
= wv
;
761 /* Don't set wv->name here; GC during the loop might relocate it. */
763 wv
->button_type
= BUTTON_TYPE_NONE
;
767 set_buffer_internal_1 (prev
);
769 /* If there has been no change in the Lisp-level contents
770 of the menu bar, skip redisplaying it. Just exit. */
772 for (i
= 0; i
< previous_menu_items_used
; i
++)
773 if (menu_items_used
== i
774 || (!EQ (previous_items
[i
], AREF (menu_items
, i
))))
776 if (i
== menu_items_used
&& i
== previous_menu_items_used
&& i
!= 0)
778 free_menubar_widget_value_tree (first_wv
);
779 discard_menu_items ();
780 unbind_to (specpdl_count
, Qnil
);
784 f
->menu_bar_vector
= menu_items
;
785 f
->menu_bar_items_used
= menu_items_used
;
787 /* This undoes save_menu_items. */
788 unbind_to (specpdl_count
, Qnil
);
790 /* Now GC cannot happen during the lifetime of the widget_value,
791 so it's safe to store data from a Lisp_String, as long as
792 local copies are made when the actual menu is created.
793 Windows takes care of this for normal string items, but
794 not for owner-drawn items or additional item-info. */
795 wv
= first_wv
->contents
;
796 for (i
= 0; i
< ASIZE (items
); i
+= 4)
799 string
= AREF (items
, i
+ 1);
802 wv
->name
= (char *) SDATA (string
);
803 update_submenu_strings (wv
->contents
);
809 /* Make a widget-value tree containing
810 just the top level menu bar strings. */
812 wv
= xmalloc_widget_value ();
813 wv
->name
= "menubar";
816 wv
->button_type
= BUTTON_TYPE_NONE
;
820 items
= FRAME_MENU_BAR_ITEMS (f
);
821 for (i
= 0; i
< ASIZE (items
); i
+= 4)
825 string
= AREF (items
, i
+ 1);
829 wv
= xmalloc_widget_value ();
830 wv
->name
= (char *) SDATA (string
);
833 wv
->button_type
= BUTTON_TYPE_NONE
;
835 /* This prevents lwlib from assuming this
836 menu item is really supposed to be empty. */
837 /* The EMACS_INT cast avoids a warning.
838 This value just has to be different from small integers. */
839 wv
->call_data
= (void *) (EMACS_INT
) (-1);
844 first_wv
->contents
= wv
;
848 /* Forget what we thought we knew about what is in the
849 detailed contents of the menu bar menus.
850 Changing the top level always destroys the contents. */
851 f
->menu_bar_items_used
= 0;
854 /* Create or update the menu bar widget. */
860 /* Empty current menubar, rather than creating a fresh one. */
861 while (DeleteMenu (menubar_widget
, 0, MF_BYPOSITION
))
866 menubar_widget
= CreateMenu ();
868 fill_in_menu (menubar_widget
, first_wv
->contents
);
870 free_menubar_widget_value_tree (first_wv
);
873 HMENU old_widget
= f
->output_data
.w32
->menubar_widget
;
875 f
->output_data
.w32
->menubar_widget
= menubar_widget
;
876 SetMenu (FRAME_W32_WINDOW (f
), f
->output_data
.w32
->menubar_widget
);
877 /* Causes flicker when menu bar is updated
878 DrawMenuBar (FRAME_W32_WINDOW (f)); */
880 /* Force the window size to be recomputed so that the frame's text
881 area remains the same, if menubar has just been created. */
882 if (old_widget
== NULL
)
883 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
889 /* Called from Fx_create_frame to create the initial menubar of a frame
890 before it is mapped, so that the window is mapped with the menubar already
891 there instead of us tacking it on later and thrashing the window after it
895 initialize_frame_menubar (f
)
898 /* This function is called before the first chance to redisplay
899 the frame. It has to be, so the frame will have the right size. */
900 FRAME_MENU_BAR_ITEMS (f
) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f
));
901 set_frame_menubar (f
, 1, 1);
904 /* Get rid of the menu bar of frame F, and free its storage.
905 This is used when deleting a frame, and when turning off the menu bar. */
908 free_frame_menubar (f
)
914 HMENU old
= GetMenu (FRAME_W32_WINDOW (f
));
915 SetMenu (FRAME_W32_WINDOW (f
), NULL
);
916 f
->output_data
.w32
->menubar_widget
= NULL
;
924 /* w32_menu_show actually displays a menu using the panes and items in
925 menu_items and returns the value selected from it; we assume input
926 is blocked by the caller. */
928 /* F is the frame the menu is for.
929 X and Y are the frame-relative specified position,
930 relative to the inside upper left corner of the frame F.
931 FOR_CLICK is nonzero if this menu was invoked for a mouse click.
932 KEYMAPS is 1 if this menu was specified with keymaps;
933 in that case, we return a list containing the chosen item's value
934 and perhaps also the pane's prefix.
935 TITLE is the specified menu title.
936 ERROR is a place to store an error message string in case of failure.
937 (We return nil on failure, but the value doesn't actually matter.) */
940 w32_menu_show (f
, x
, y
, for_click
, keymaps
, title
, error
)
950 int menu_item_selection
;
953 widget_value
*wv
, *save_wv
= 0, *first_wv
= 0, *prev_wv
= 0;
954 widget_value
**submenu_stack
955 = (widget_value
**) alloca (menu_items_used
* sizeof (widget_value
*));
956 Lisp_Object
*subprefix_stack
957 = (Lisp_Object
*) alloca (menu_items_used
* sizeof (Lisp_Object
));
958 int submenu_depth
= 0;
963 if (menu_items_n_panes
== 0)
966 if (menu_items_used
<= MENU_ITEMS_PANE_LENGTH
)
968 *error
= "Empty menu";
972 /* Create a tree of widget_value objects
973 representing the panes and their items. */
974 wv
= xmalloc_widget_value ();
978 wv
->button_type
= BUTTON_TYPE_NONE
;
983 /* Loop over all panes and items, filling in the tree. */
985 while (i
< menu_items_used
)
987 if (EQ (AREF (menu_items
, i
), Qnil
))
989 submenu_stack
[submenu_depth
++] = save_wv
;
995 else if (EQ (AREF (menu_items
, i
), Qlambda
))
998 save_wv
= submenu_stack
[--submenu_depth
];
1002 else if (EQ (AREF (menu_items
, i
), Qt
)
1003 && submenu_depth
!= 0)
1004 i
+= MENU_ITEMS_PANE_LENGTH
;
1005 /* Ignore a nil in the item list.
1006 It's meaningful only for dialog boxes. */
1007 else if (EQ (AREF (menu_items
, i
), Qquote
))
1009 else if (EQ (AREF (menu_items
, i
), Qt
))
1011 /* Create a new pane. */
1012 Lisp_Object pane_name
, prefix
;
1014 pane_name
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_NAME
);
1015 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
1017 if (STRINGP (pane_name
))
1019 if (unicode_append_menu
)
1020 pane_name
= ENCODE_UTF_8 (pane_name
);
1021 else if (STRING_MULTIBYTE (pane_name
))
1022 pane_name
= ENCODE_SYSTEM (pane_name
);
1024 ASET (menu_items
, i
+ MENU_ITEMS_PANE_NAME
, pane_name
);
1027 pane_string
= (NILP (pane_name
)
1028 ? "" : (char *) SDATA (pane_name
));
1029 /* If there is just one top-level pane, put all its items directly
1030 under the top-level menu. */
1031 if (menu_items_n_panes
== 1)
1034 /* If the pane has a meaningful name,
1035 make the pane a top-level menu item
1036 with its items as a submenu beneath it. */
1037 if (!keymaps
&& strcmp (pane_string
, ""))
1039 wv
= xmalloc_widget_value ();
1043 first_wv
->contents
= wv
;
1044 wv
->name
= pane_string
;
1045 if (keymaps
&& !NILP (prefix
))
1049 wv
->button_type
= BUTTON_TYPE_NONE
;
1054 else if (first_pane
)
1060 i
+= MENU_ITEMS_PANE_LENGTH
;
1064 /* Create a new item within current pane. */
1065 Lisp_Object item_name
, enable
, descrip
, def
, type
, selected
, help
;
1067 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
1068 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
1069 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
1070 def
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_DEFINITION
);
1071 type
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_TYPE
);
1072 selected
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_SELECTED
);
1073 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
1075 if (STRINGP (item_name
))
1077 if (unicode_append_menu
)
1078 item_name
= ENCODE_UTF_8 (item_name
);
1079 else if (STRING_MULTIBYTE (item_name
))
1080 item_name
= ENCODE_SYSTEM (item_name
);
1082 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
, item_name
);
1085 if (STRINGP (descrip
) && STRING_MULTIBYTE (descrip
))
1087 descrip
= ENCODE_SYSTEM (descrip
);
1088 ASET (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
, descrip
);
1091 wv
= xmalloc_widget_value ();
1095 save_wv
->contents
= wv
;
1096 wv
->name
= (char *) SDATA (item_name
);
1097 if (!NILP (descrip
))
1098 wv
->key
= (char *) SDATA (descrip
);
1100 /* Use the contents index as call_data, since we are
1101 restricted to 16-bits. */
1102 wv
->call_data
= !NILP (def
) ? (void *) (EMACS_INT
) i
: 0;
1103 wv
->enabled
= !NILP (enable
);
1106 wv
->button_type
= BUTTON_TYPE_NONE
;
1107 else if (EQ (type
, QCtoggle
))
1108 wv
->button_type
= BUTTON_TYPE_TOGGLE
;
1109 else if (EQ (type
, QCradio
))
1110 wv
->button_type
= BUTTON_TYPE_RADIO
;
1114 wv
->selected
= !NILP (selected
);
1116 if (!STRINGP (help
))
1123 i
+= MENU_ITEMS_ITEM_LENGTH
;
1127 /* Deal with the title, if it is non-nil. */
1130 widget_value
*wv_title
= xmalloc_widget_value ();
1131 widget_value
*wv_sep
= xmalloc_widget_value ();
1133 /* Maybe replace this separator with a bitmap or owner-draw item
1134 so that it looks better. Having two separators looks odd. */
1135 wv_sep
->name
= "--";
1136 wv_sep
->next
= first_wv
->contents
;
1137 wv_sep
->help
= Qnil
;
1139 if (unicode_append_menu
)
1140 title
= ENCODE_UTF_8 (title
);
1141 else if (STRING_MULTIBYTE (title
))
1142 title
= ENCODE_SYSTEM (title
);
1144 wv_title
->name
= (char *) SDATA (title
);
1145 wv_title
->enabled
= TRUE
;
1146 wv_title
->title
= TRUE
;
1147 wv_title
->button_type
= BUTTON_TYPE_NONE
;
1148 wv_title
->help
= Qnil
;
1149 wv_title
->next
= wv_sep
;
1150 first_wv
->contents
= wv_title
;
1153 /* No selection has been chosen yet. */
1154 menu_item_selection
= 0;
1156 /* Actually create the menu. */
1157 current_popup_menu
= menu
= CreatePopupMenu ();
1158 fill_in_menu (menu
, first_wv
->contents
);
1160 /* Adjust coordinates to be root-window-relative. */
1163 ClientToScreen (FRAME_W32_WINDOW (f
), &pos
);
1165 /* Display the menu. */
1166 menu_item_selection
= SendMessage (FRAME_W32_WINDOW (f
),
1167 WM_EMACS_TRACKPOPUPMENU
,
1168 (WPARAM
)menu
, (LPARAM
)&pos
);
1170 /* Clean up extraneous mouse events which might have been generated
1172 discard_mouse_events ();
1173 FRAME_X_DISPLAY_INFO (f
)->grabbed
= 0;
1175 /* Free the widget_value objects we used to specify the contents. */
1176 free_menubar_widget_value_tree (first_wv
);
1180 /* Free the owner-drawn and help-echo menu strings. */
1181 w32_free_menu_strings (FRAME_W32_WINDOW (f
));
1182 f
->output_data
.w32
->menubar_active
= 0;
1184 /* Find the selected item, and its pane, to return
1185 the proper value. */
1186 if (menu_item_selection
!= 0)
1188 Lisp_Object prefix
, entry
;
1190 prefix
= entry
= Qnil
;
1192 while (i
< menu_items_used
)
1194 if (EQ (AREF (menu_items
, i
), Qnil
))
1196 subprefix_stack
[submenu_depth
++] = prefix
;
1200 else if (EQ (AREF (menu_items
, i
), Qlambda
))
1202 prefix
= subprefix_stack
[--submenu_depth
];
1205 else if (EQ (AREF (menu_items
, i
), Qt
))
1207 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
1208 i
+= MENU_ITEMS_PANE_LENGTH
;
1210 /* Ignore a nil in the item list.
1211 It's meaningful only for dialog boxes. */
1212 else if (EQ (AREF (menu_items
, i
), Qquote
))
1216 entry
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_VALUE
);
1217 if (menu_item_selection
== i
)
1223 entry
= Fcons (entry
, Qnil
);
1225 entry
= Fcons (prefix
, entry
);
1226 for (j
= submenu_depth
- 1; j
>= 0; j
--)
1227 if (!NILP (subprefix_stack
[j
]))
1228 entry
= Fcons (subprefix_stack
[j
], entry
);
1232 i
+= MENU_ITEMS_ITEM_LENGTH
;
1236 else if (!for_click
)
1237 /* Make "Cancel" equivalent to C-g. */
1238 Fsignal (Qquit
, Qnil
);
1245 /* TODO: On Windows, there are two ways of defining a dialog.
1247 1. Create a predefined dialog resource and include it in nt/emacs.rc.
1248 Using this method, we could then set the titles and make unneeded
1249 buttons invisible before displaying the dialog. Everything would
1250 be a fixed size though, so there is a risk that text does not
1252 2. Create the dialog template in memory on the fly. This allows us
1253 to size the dialog and buttons dynamically, probably giving more
1254 natural looking results for dialogs with few buttons, and eliminating
1255 the problem of text overflowing the buttons. But the API for this is
1256 quite complex - structures have to be allocated in particular ways,
1257 text content is tacked onto the end of structures in variable length
1258 arrays with further structures tacked on after these, there are
1259 certain alignment requirements for all this, and we have to
1260 measure all the text and convert to "dialog coordinates" to figure
1261 out how big to make everything.
1263 For now, we'll just stick with menus for dialogs that are more
1264 complicated than simple yes/no type questions for which we can use
1265 the MessageBox function.
1268 static char * button_names
[] = {
1269 "button1", "button2", "button3", "button4", "button5",
1270 "button6", "button7", "button8", "button9", "button10" };
1273 w32_dialog_show (f
, keymaps
, title
, header
, error
)
1276 Lisp_Object title
, header
;
1279 int i
, nb_buttons
=0;
1280 char dialog_name
[6];
1281 int menu_item_selection
;
1283 widget_value
*wv
, *first_wv
= 0, *prev_wv
= 0;
1285 /* Number of elements seen so far, before boundary. */
1287 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
1288 int boundary_seen
= 0;
1292 if (menu_items_n_panes
> 1)
1294 *error
= "Multiple panes in dialog box";
1298 /* Create a tree of widget_value objects
1299 representing the text label and buttons. */
1301 Lisp_Object pane_name
, prefix
;
1303 pane_name
= AREF (menu_items
, MENU_ITEMS_PANE_NAME
);
1304 prefix
= AREF (menu_items
, MENU_ITEMS_PANE_PREFIX
);
1305 pane_string
= (NILP (pane_name
)
1306 ? "" : (char *) SDATA (pane_name
));
1307 prev_wv
= xmalloc_widget_value ();
1308 prev_wv
->value
= pane_string
;
1309 if (keymaps
&& !NILP (prefix
))
1311 prev_wv
->enabled
= 1;
1312 prev_wv
->name
= "message";
1313 prev_wv
->help
= Qnil
;
1316 /* Loop over all panes and items, filling in the tree. */
1317 i
= MENU_ITEMS_PANE_LENGTH
;
1318 while (i
< menu_items_used
)
1321 /* Create a new item within current pane. */
1322 Lisp_Object item_name
, enable
, descrip
, help
;
1324 item_name
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_NAME
);
1325 enable
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_ENABLE
);
1326 descrip
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_EQUIV_KEY
);
1327 help
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_HELP
);
1329 if (NILP (item_name
))
1331 free_menubar_widget_value_tree (first_wv
);
1332 *error
= "Submenu in dialog items";
1335 if (EQ (item_name
, Qquote
))
1337 /* This is the boundary between left-side elts
1338 and right-side elts. Stop incrementing right_count. */
1343 if (nb_buttons
>= 9)
1345 free_menubar_widget_value_tree (first_wv
);
1346 *error
= "Too many dialog items";
1350 wv
= xmalloc_widget_value ();
1352 wv
->name
= (char *) button_names
[nb_buttons
];
1353 if (!NILP (descrip
))
1354 wv
->key
= (char *) SDATA (descrip
);
1355 wv
->value
= (char *) SDATA (item_name
);
1356 wv
->call_data
= (void *) &AREF (menu_items
, i
);
1357 wv
->enabled
= !NILP (enable
);
1361 if (! boundary_seen
)
1365 i
+= MENU_ITEMS_ITEM_LENGTH
;
1368 /* If the boundary was not specified,
1369 by default put half on the left and half on the right. */
1370 if (! boundary_seen
)
1371 left_count
= nb_buttons
- nb_buttons
/ 2;
1373 wv
= xmalloc_widget_value ();
1374 wv
->name
= dialog_name
;
1377 /* Frame title: 'Q' = Question, 'I' = Information.
1378 Can also have 'E' = Error if, one day, we want
1379 a popup for errors. */
1381 dialog_name
[0] = 'Q';
1383 dialog_name
[0] = 'I';
1385 /* Dialog boxes use a really stupid name encoding
1386 which specifies how many buttons to use
1387 and how many buttons are on the right. */
1388 dialog_name
[1] = '0' + nb_buttons
;
1389 dialog_name
[2] = 'B';
1390 dialog_name
[3] = 'R';
1391 /* Number of buttons to put on the right. */
1392 dialog_name
[4] = '0' + nb_buttons
- left_count
;
1394 wv
->contents
= first_wv
;
1398 /* Actually create the dialog. */
1399 dialog_id
= widget_id_tick
++;
1400 menu
= lw_create_widget (first_wv
->name
, "dialog", dialog_id
, first_wv
,
1401 f
->output_data
.w32
->widget
, 1, 0,
1402 dialog_selection_callback
, 0);
1403 lw_modify_all_widgets (dialog_id
, first_wv
->contents
, TRUE
);
1405 /* Free the widget_value objects we used to specify the contents. */
1406 free_menubar_widget_value_tree (first_wv
);
1408 /* No selection has been chosen yet. */
1409 menu_item_selection
= 0;
1411 /* Display the menu. */
1412 lw_pop_up_all_widgets (dialog_id
);
1414 /* Process events that apply to the menu. */
1415 popup_get_selection ((XEvent
*) 0, FRAME_X_DISPLAY_INFO (f
), dialog_id
);
1417 lw_destroy_all_widgets (dialog_id
);
1419 /* Find the selected item, and its pane, to return
1420 the proper value. */
1421 if (menu_item_selection
!= 0)
1427 while (i
< menu_items_used
)
1431 if (EQ (AREF (menu_items
, i
), Qt
))
1433 prefix
= AREF (menu_items
, i
+ MENU_ITEMS_PANE_PREFIX
);
1434 i
+= MENU_ITEMS_PANE_LENGTH
;
1438 entry
= AREF (menu_items
, i
+ MENU_ITEMS_ITEM_VALUE
);
1439 if (menu_item_selection
== i
)
1443 entry
= Fcons (entry
, Qnil
);
1445 entry
= Fcons (prefix
, entry
);
1449 i
+= MENU_ITEMS_ITEM_LENGTH
;
1454 /* Make "Cancel" equivalent to C-g. */
1455 Fsignal (Qquit
, Qnil
);
1459 #else /* !HAVE_DIALOGS */
1461 /* Currently we only handle Yes No dialogs (y-or-n-p and yes-or-no-p) as
1462 simple dialogs. We could handle a few more, but I'm not aware of
1463 anywhere in Emacs that uses the other specific dialog choices that
1464 MessageBox provides. */
1466 static int is_simple_dialog (contents
)
1467 Lisp_Object contents
;
1469 Lisp_Object options
= XCDR (contents
);
1470 Lisp_Object name
, yes
, no
, other
;
1472 yes
= build_string ("Yes");
1473 no
= build_string ("No");
1475 if (!CONSP (options
))
1478 name
= XCAR (XCAR (options
));
1479 if (!CONSP (options
))
1482 if (!NILP (Fstring_equal (name
, yes
)))
1484 else if (!NILP (Fstring_equal (name
, no
)))
1489 options
= XCDR (options
);
1490 if (!CONSP (options
))
1493 name
= XCAR (XCAR (options
));
1494 if (NILP (Fstring_equal (name
, other
)))
1497 /* Check there are no more options. */
1498 options
= XCDR (options
);
1499 return !(CONSP (options
));
1502 static Lisp_Object
simple_dialog_show (f
, contents
, header
)
1504 Lisp_Object contents
, header
;
1509 Lisp_Object lispy_answer
= Qnil
, temp
= XCAR (contents
);
1512 text
= SDATA (temp
);
1519 type
= MB_ICONQUESTION
;
1523 title
= "Information";
1524 type
= MB_ICONINFORMATION
;
1528 /* Since we only handle Yes/No dialogs, and we already checked
1529 is_simple_dialog, we don't need to worry about checking contents
1530 to see what type of dialog to use. */
1531 answer
= MessageBox (FRAME_W32_WINDOW (f
), text
, title
, type
);
1533 if (answer
== IDYES
)
1534 lispy_answer
= build_string ("Yes");
1535 else if (answer
== IDNO
)
1536 lispy_answer
= build_string ("No");
1538 Fsignal (Qquit
, Qnil
);
1540 for (temp
= XCDR (contents
); CONSP (temp
); temp
= XCDR (temp
))
1542 Lisp_Object item
, name
, value
;
1547 value
= XCDR (item
);
1555 if (!NILP (Fstring_equal (name
, lispy_answer
)))
1560 Fsignal (Qquit
, Qnil
);
1563 #endif /* !HAVE_DIALOGS */
1566 /* Is this item a separator? */
1568 name_is_separator (name
)
1573 /* Check if name string consists of only dashes ('-'). */
1574 while (*name
== '-') name
++;
1575 /* Separators can also be of the form "--:TripleSuperMegaEtched"
1576 or "--deep-shadow". We don't implement them yet, se we just treat
1577 them like normal separators. */
1578 return (*name
== '\0' || start
+ 2 == name
);
1582 /* Indicate boundary between left and right. */
1584 add_left_right_boundary (HMENU menu
)
1586 return AppendMenu (menu
, MF_MENUBARBREAK
, 0, NULL
);
1589 /* UTF8: 0xxxxxxx, 110xxxxx 10xxxxxx, 1110xxxx, 10xxxxxx, 10xxxxxx */
1591 utf8to16 (unsigned char * src
, int len
, WCHAR
* dest
)
1598 *dest
= (WCHAR
) *src
;
1599 dest
++; src
++; len
--;
1601 /* Since we might get >3 byte sequences which we don't handle, ignore the extra parts. */
1602 else if (*src
< 0xC0)
1606 /* 2 char UTF-8 sequence. */
1607 else if (*src
< 0xE0)
1609 *dest
= (WCHAR
) (((*src
& 0x1f) << 6)
1610 | (*(src
+ 1) & 0x3f));
1611 src
+= 2; len
-= 2; dest
++;
1613 else if (*src
< 0xF0)
1615 *dest
= (WCHAR
) (((*src
& 0x0f) << 12)
1616 | ((*(src
+ 1) & 0x3f) << 6)
1617 | (*(src
+ 2) & 0x3f));
1618 src
+= 3; len
-= 3; dest
++;
1620 else /* Not encodable. Insert Unicode Substitution char. */
1622 *dest
= (WCHAR
) 0xfffd;
1623 src
++; len
--; dest
++;
1630 add_menu_item (HMENU menu
, widget_value
*wv
, HMENU item
)
1633 char *out_string
, *p
, *q
;
1635 size_t nlen
, orig_len
;
1637 if (name_is_separator (wv
->name
))
1639 fuFlags
= MF_SEPARATOR
;
1645 fuFlags
= MF_STRING
;
1647 fuFlags
= MF_STRING
| MF_GRAYED
;
1649 if (wv
->key
!= NULL
)
1651 out_string
= alloca (strlen (wv
->name
) + strlen (wv
->key
) + 2);
1652 strcpy (out_string
, wv
->name
);
1653 strcat (out_string
, "\t");
1654 strcat (out_string
, wv
->key
);
1657 out_string
= wv
->name
;
1659 /* Quote any special characters within the menu item's text and
1661 nlen
= orig_len
= strlen (out_string
);
1662 if (unicode_append_menu
)
1664 /* With UTF-8, & cannot be part of a multibyte character. */
1665 for (p
= out_string
; *p
; p
++)
1673 /* If encoded with the system codepage, use multibyte string
1674 functions in case of multibyte characters that contain '&'. */
1675 for (p
= out_string
; *p
; p
= _mbsinc (p
))
1677 if (_mbsnextc (p
) == '&')
1682 if (nlen
> orig_len
)
1685 out_string
= alloca (nlen
+ 1);
1689 if (unicode_append_menu
)
1697 if (_mbsnextc (p
) == '&')
1712 else if (wv
->title
|| wv
->call_data
== 0)
1714 /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since
1715 we can't deallocate the memory otherwise. */
1716 if (get_menu_item_info
)
1718 out_string
= (char *) local_alloc (strlen (wv
->name
) + 1);
1719 strcpy (out_string
, wv
->name
);
1721 DebPrint ("Menu: allocing %ld for owner-draw", out_string
);
1723 fuFlags
= MF_OWNERDRAW
| MF_DISABLED
;
1726 fuFlags
= MF_DISABLED
;
1729 /* Draw radio buttons and tickboxes. */
1730 else if (wv
->selected
&& (wv
->button_type
== BUTTON_TYPE_TOGGLE
||
1731 wv
->button_type
== BUTTON_TYPE_RADIO
))
1732 fuFlags
|= MF_CHECKED
;
1734 fuFlags
|= MF_UNCHECKED
;
1737 if (unicode_append_menu
&& out_string
)
1739 /* Convert out_string from UTF-8 to UTF-16-LE. */
1740 int utf8_len
= strlen (out_string
);
1741 WCHAR
* utf16_string
;
1742 if (fuFlags
& MF_OWNERDRAW
)
1743 utf16_string
= local_alloc ((utf8_len
+ 1) * sizeof (WCHAR
));
1745 utf16_string
= alloca ((utf8_len
+ 1) * sizeof (WCHAR
));
1747 utf8to16 (out_string
, utf8_len
, utf16_string
);
1748 return_value
= unicode_append_menu (menu
, fuFlags
,
1749 item
!= NULL
? (UINT
) item
1750 : (UINT
) wv
->call_data
,
1754 /* On W9x/ME, unicode menus are not supported, though AppendMenuW
1755 apparently does exist at least in some cases and appears to be
1756 stubbed out to do nothing. out_string is UTF-8, but since
1757 our standard menus are in English and this is only going to
1758 happen the first time a menu is used, the encoding is
1759 of minor importance compared with menus not working at all. */
1761 AppendMenu (menu
, fuFlags
,
1762 item
!= NULL
? (UINT
) item
: (UINT
) wv
->call_data
,
1764 /* Don't use unicode menus in future. */
1765 unicode_append_menu
= NULL
;
1768 if (unicode_append_menu
&& (fuFlags
& MF_OWNERDRAW
))
1769 local_free (out_string
);
1776 item
!= NULL
? (UINT
) item
: (UINT
) wv
->call_data
,
1780 /* This must be done after the menu item is created. */
1781 if (!wv
->title
&& wv
->call_data
!= 0)
1783 if (set_menu_item_info
)
1786 bzero (&info
, sizeof (info
));
1787 info
.cbSize
= sizeof (info
);
1788 info
.fMask
= MIIM_DATA
;
1790 /* Set help string for menu item. Leave it as a Lisp_Object
1791 until it is ready to be displayed, since GC can happen while
1792 menus are active. */
1793 if (!NILP (wv
->help
))
1794 #ifdef USE_LISP_UNION_TYPE
1795 info
.dwItemData
= (DWORD
) (wv
->help
).i
;
1797 info
.dwItemData
= (DWORD
) (wv
->help
);
1799 if (wv
->button_type
== BUTTON_TYPE_RADIO
)
1801 /* CheckMenuRadioItem allows us to differentiate TOGGLE and
1802 RADIO items, but is not available on NT 3.51 and earlier. */
1803 info
.fMask
|= MIIM_TYPE
| MIIM_STATE
;
1804 info
.fType
= MFT_RADIOCHECK
| MFT_STRING
;
1805 info
.dwTypeData
= out_string
;
1806 info
.fState
= wv
->selected
? MFS_CHECKED
: MFS_UNCHECKED
;
1809 set_menu_item_info (menu
,
1810 item
!= NULL
? (UINT
) item
: (UINT
) wv
->call_data
,
1814 return return_value
;
1817 /* Construct native Windows menu(bar) based on widget_value tree. */
1819 fill_in_menu (HMENU menu
, widget_value
*wv
)
1821 int items_added
= 0;
1823 for ( ; wv
!= NULL
; wv
= wv
->next
)
1827 HMENU sub_menu
= CreatePopupMenu ();
1829 if (sub_menu
== NULL
)
1832 if (!fill_in_menu (sub_menu
, wv
->contents
) ||
1833 !add_menu_item (menu
, wv
, sub_menu
))
1835 DestroyMenu (sub_menu
);
1841 if (!add_menu_item (menu
, wv
, NULL
))
1848 /* Display help string for currently pointed to menu item. Not
1849 supported on NT 3.51 and earlier, as GetMenuItemInfo is not
1852 w32_menu_display_help (HWND owner
, HMENU menu
, UINT item
, UINT flags
)
1854 if (get_menu_item_info
)
1856 struct frame
*f
= x_window_to_frame (&one_w32_display_info
, owner
);
1857 Lisp_Object frame
, help
;
1859 /* No help echo on owner-draw menu items, or when the keyboard is used
1860 to navigate the menus, since tooltips are distracting if they pop
1862 if (flags
& MF_OWNERDRAW
|| flags
& MF_POPUP
1863 || !(flags
& MF_MOUSESELECT
))
1869 bzero (&info
, sizeof (info
));
1870 info
.cbSize
= sizeof (info
);
1871 info
.fMask
= MIIM_DATA
;
1872 get_menu_item_info (menu
, item
, FALSE
, &info
);
1874 #ifdef USE_LISP_UNION_TYPE
1875 help
= info
.dwItemData
? (Lisp_Object
) ((EMACS_INT
) info
.dwItemData
)
1878 help
= info
.dwItemData
? (Lisp_Object
) info
.dwItemData
: Qnil
;
1882 /* Store the help echo in the keyboard buffer as the X toolkit
1883 version does, rather than directly showing it. This seems to
1884 solve the GC problems that were present when we based the
1885 Windows code on the non-toolkit version. */
1888 XSETFRAME (frame
, f
);
1889 kbd_buffer_store_help_event (frame
, help
);
1892 /* X version has a loop through frames here, which doesn't
1893 appear to do anything, unless it has some side effect. */
1894 show_help_echo (help
, Qnil
, Qnil
, Qnil
, 1);
1898 /* Free memory used by owner-drawn strings. */
1900 w32_free_submenu_strings (menu
)
1903 int i
, num
= GetMenuItemCount (menu
);
1904 for (i
= 0; i
< num
; i
++)
1907 bzero (&info
, sizeof (info
));
1908 info
.cbSize
= sizeof (info
);
1909 info
.fMask
= MIIM_DATA
| MIIM_TYPE
| MIIM_SUBMENU
;
1911 get_menu_item_info (menu
, i
, TRUE
, &info
);
1913 /* Owner-drawn names are held in dwItemData. */
1914 if ((info
.fType
& MF_OWNERDRAW
) && info
.dwItemData
)
1917 DebPrint ("Menu: freeing %ld for owner-draw", info
.dwItemData
);
1919 local_free (info
.dwItemData
);
1922 /* Recurse down submenus. */
1924 w32_free_submenu_strings (info
.hSubMenu
);
1929 w32_free_menu_strings (hwnd
)
1932 HMENU menu
= current_popup_menu
;
1934 if (get_menu_item_info
)
1936 /* If there is no popup menu active, free the strings from the frame's
1939 menu
= GetMenu (hwnd
);
1942 w32_free_submenu_strings (menu
);
1945 current_popup_menu
= NULL
;
1948 #endif /* HAVE_MENUS */
1950 /* The following is used by delayed window autoselection. */
1952 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p
, Smenu_or_popup_active_p
, 0, 0, 0,
1953 doc
: /* Return t if a menu or popup dialog is active on selected frame. */)
1958 f
= SELECTED_FRAME ();
1959 return (f
->output_data
.w32
->menubar_active
> 0) ? Qt
: Qnil
;
1962 #endif /* HAVE_MENUS */
1965 void syms_of_w32menu ()
1967 globals_of_w32menu ();
1969 current_popup_menu
= NULL
;
1971 DEFSYM (Qdebug_on_next_call
, "debug-on-next-call");
1973 defsubr (&Sx_popup_menu
);
1974 defsubr (&Smenu_or_popup_active_p
);
1976 defsubr (&Sx_popup_dialog
);
1981 globals_of_w32menu is used to initialize those global variables that
1982 must always be initialized on startup even when the global variable
1983 initialized is non zero (see the function main in emacs.c).
1984 globals_of_w32menu is called from syms_of_w32menu when the global
1985 variable initialized is 0 and directly from main when initialized
1988 void globals_of_w32menu ()
1990 /* See if Get/SetMenuItemInfo functions are available. */
1991 HMODULE user32
= GetModuleHandle ("user32.dll");
1992 get_menu_item_info
= (GetMenuItemInfoA_Proc
) GetProcAddress (user32
, "GetMenuItemInfoA");
1993 set_menu_item_info
= (SetMenuItemInfoA_Proc
) GetProcAddress (user32
, "SetMenuItemInfoA");
1994 unicode_append_menu
= (AppendMenuW_Proc
) GetProcAddress (user32
, "AppendMenuW");
1997 /* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0
1998 (do not change this comment) */