Merge from emacs-24; up to 2013-01-03T02:37:57Z!rgm@gnu.org
[emacs.git] / src / w32menu.c
blobb25652017cdff0c7ba25253c333a1bdf53017ed8
1 /* Menu support for GNU Emacs on the Microsoft Windows API.
2 Copyright (C) 1986, 1988, 1993-1994, 1996, 1998-1999, 2001-2013 Free
3 Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 #include <config.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #include <setjmp.h>
26 #include "lisp.h"
27 #include "keyboard.h"
28 #include "keymap.h"
29 #include "frame.h"
30 #include "termhooks.h"
31 #include "window.h"
32 #include "blockinput.h"
33 #include "character.h"
34 #include "buffer.h"
35 #include "charset.h"
36 #include "coding.h"
37 #include "menu.h"
39 /* This may include sys/types.h, and that somehow loses
40 if this is not done before the other system files. */
41 #include "w32term.h"
43 /* Cygwin does not support the multibyte string functions declared in
44 * mbstring.h below --- but that's okay: because Cygwin is
45 * UNICODE-only, we don't need to use these functions anyway. */
47 #ifndef NTGUI_UNICODE
48 #include <mbstring.h>
49 #endif /* !NTGUI_UNICODE */
51 /* Load sys/types.h if not already loaded.
52 In some systems loading it twice is suicidal. */
53 #ifndef makedev
54 #include <sys/types.h>
55 #endif
57 #include "dispextern.h"
59 #include "w32common.h" /* for osinfo_cache */
61 #undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
63 #ifndef TRUE
64 #define TRUE 1
65 #define FALSE 0
66 #endif /* no TRUE */
68 HMENU current_popup_menu;
70 void syms_of_w32menu (void);
71 void globals_of_w32menu (void);
73 typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (
74 IN HMENU,
75 IN UINT,
76 IN BOOL,
77 IN OUT LPMENUITEMINFOA);
78 typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) (
79 IN HMENU,
80 IN UINT,
81 IN BOOL,
82 IN LPCMENUITEMINFOA);
83 typedef int (WINAPI * MessageBoxW_Proc) (
84 IN HWND window,
85 IN WCHAR *text,
86 IN WCHAR *caption,
87 IN UINT type);
89 #ifdef NTGUI_UNICODE
90 #define get_menu_item_info GetMenuItemInfoA
91 #define set_menu_item_info SetMenuItemInfoA
92 #define unicode_append_menu AppendMenuW
93 #define unicode_message_box MessageBoxW
94 #else /* !NTGUI_UNICODE */
95 GetMenuItemInfoA_Proc get_menu_item_info = NULL;
96 SetMenuItemInfoA_Proc set_menu_item_info = NULL;
97 AppendMenuW_Proc unicode_append_menu = NULL;
98 MessageBoxW_Proc unicode_message_box = NULL;
99 #endif /* NTGUI_UNICODE */
101 Lisp_Object Qdebug_on_next_call;
103 void set_frame_menubar (struct frame *, bool, bool);
105 #ifdef HAVE_DIALOGS
106 static Lisp_Object w32_dialog_show (struct frame *, int, Lisp_Object, char**);
107 #else
108 static int is_simple_dialog (Lisp_Object);
109 static Lisp_Object simple_dialog_show (struct frame *, Lisp_Object, Lisp_Object);
110 #endif
112 static void utf8to16 (unsigned char *, int, WCHAR *);
113 static int fill_in_menu (HMENU, widget_value *);
115 void w32_free_menu_strings (HWND);
117 #ifdef HAVE_MENUS
118 #ifdef HAVE_DIALOGS
119 Lisp_Object
120 w32_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
122 Lisp_Object title;
123 char *error_name;
124 Lisp_Object selection;
126 check_window_system (f);
128 /* Decode the dialog items from what was specified. */
129 title = Fcar (contents);
130 CHECK_STRING (title);
132 list_of_panes (Fcons (contents, Qnil));
134 /* Display them in a dialog box. */
135 block_input ();
136 selection = w32_dialog_show (f, 0, title, header, &error_name);
137 unblock_input ();
139 discard_menu_items ();
140 FRAME_DISPLAY_INFO (f)->grabbed = 0;
142 if (error_name) error (error_name);
143 return selection;
145 #endif /* HAVE_DIALOGS */
147 /* Activate the menu bar of frame F.
148 This is called from keyboard.c when it gets the
149 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
151 To activate the menu bar, we signal to the input thread that it can
152 return from the WM_INITMENU message, allowing the normal Windows
153 processing of the menus.
155 But first we recompute the menu bar contents (the whole tree).
157 This way we can safely execute Lisp code. */
159 void
160 x_activate_menubar (struct frame *f)
162 set_frame_menubar (f, 0, 1);
164 /* Lock out further menubar changes while active. */
165 f->output_data.w32->menubar_active = 1;
167 /* Signal input thread to return from WM_INITMENU. */
168 complete_deferred_msg (FRAME_W32_WINDOW (f), WM_INITMENU, 0);
171 /* This callback is called from the menu bar pulldown menu
172 when the user makes a selection.
173 Figure out what the user chose
174 and put the appropriate events into the keyboard buffer. */
176 void
177 menubar_selection_callback (struct frame *f, void * client_data)
179 Lisp_Object prefix, entry;
180 Lisp_Object vector;
181 Lisp_Object *subprefix_stack;
182 int submenu_depth = 0;
183 int i;
185 if (!f)
186 return;
187 entry = Qnil;
188 subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * word_size);
189 vector = f->menu_bar_vector;
190 prefix = Qnil;
191 i = 0;
192 while (i < f->menu_bar_items_used)
194 if (EQ (AREF (vector, i), Qnil))
196 subprefix_stack[submenu_depth++] = prefix;
197 prefix = entry;
198 i++;
200 else if (EQ (AREF (vector, i), Qlambda))
202 prefix = subprefix_stack[--submenu_depth];
203 i++;
205 else if (EQ (AREF (vector, i), Qt))
207 prefix = AREF (vector, i + MENU_ITEMS_PANE_PREFIX);
208 i += MENU_ITEMS_PANE_LENGTH;
210 else
212 entry = AREF (vector, i + MENU_ITEMS_ITEM_VALUE);
213 /* The EMACS_INT cast avoids a warning. There's no problem
214 as long as pointers have enough bits to hold small integers. */
215 if ((int) (EMACS_INT) client_data == i)
217 int j;
218 struct input_event buf;
219 Lisp_Object frame;
220 EVENT_INIT (buf);
222 XSETFRAME (frame, f);
223 buf.kind = MENU_BAR_EVENT;
224 buf.frame_or_window = frame;
225 buf.arg = frame;
226 kbd_buffer_store_event (&buf);
228 for (j = 0; j < submenu_depth; j++)
229 if (!NILP (subprefix_stack[j]))
231 buf.kind = MENU_BAR_EVENT;
232 buf.frame_or_window = frame;
233 buf.arg = subprefix_stack[j];
234 kbd_buffer_store_event (&buf);
237 if (!NILP (prefix))
239 buf.kind = MENU_BAR_EVENT;
240 buf.frame_or_window = frame;
241 buf.arg = prefix;
242 kbd_buffer_store_event (&buf);
245 buf.kind = MENU_BAR_EVENT;
246 buf.frame_or_window = frame;
247 buf.arg = entry;
248 /* Free memory used by owner-drawn and help-echo strings. */
249 w32_free_menu_strings (FRAME_W32_WINDOW (f));
250 kbd_buffer_store_event (&buf);
252 f->output_data.w32->menubar_active = 0;
253 return;
255 i += MENU_ITEMS_ITEM_LENGTH;
258 /* Free memory used by owner-drawn and help-echo strings. */
259 w32_free_menu_strings (FRAME_W32_WINDOW (f));
260 f->output_data.w32->menubar_active = 0;
264 /* Set the contents of the menubar widgets of frame F.
265 The argument FIRST_TIME is currently ignored;
266 it is set the first time this is called, from initialize_frame_menubar. */
268 void
269 set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
271 HMENU menubar_widget = f->output_data.w32->menubar_widget;
272 Lisp_Object items;
273 widget_value *wv, *first_wv, *prev_wv = 0;
274 int i, last_i;
275 int *submenu_start, *submenu_end;
276 int *submenu_top_level_items, *submenu_n_panes;
278 /* We must not change the menubar when actually in use. */
279 if (f->output_data.w32->menubar_active)
280 return;
282 XSETFRAME (Vmenu_updating_frame, f);
284 if (! menubar_widget)
285 deep_p = 1;
287 if (deep_p)
289 /* Make a widget-value tree representing the entire menu trees. */
291 struct buffer *prev = current_buffer;
292 Lisp_Object buffer;
293 ptrdiff_t specpdl_count = SPECPDL_INDEX ();
294 int previous_menu_items_used = f->menu_bar_items_used;
295 Lisp_Object *previous_items
296 = (Lisp_Object *) alloca (previous_menu_items_used
297 * word_size);
299 /* If we are making a new widget, its contents are empty,
300 do always reinitialize them. */
301 if (! menubar_widget)
302 previous_menu_items_used = 0;
304 buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents;
305 specbind (Qinhibit_quit, Qt);
306 /* Don't let the debugger step into this code
307 because it is not reentrant. */
308 specbind (Qdebug_on_next_call, Qnil);
310 record_unwind_save_match_data ();
312 if (NILP (Voverriding_local_map_menu_flag))
314 specbind (Qoverriding_terminal_local_map, Qnil);
315 specbind (Qoverriding_local_map, Qnil);
318 set_buffer_internal_1 (XBUFFER (buffer));
320 /* Run the hooks. */
321 safe_run_hooks (Qactivate_menubar_hook);
322 safe_run_hooks (Qmenu_bar_update_hook);
323 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
325 items = FRAME_MENU_BAR_ITEMS (f);
327 /* Save the frame's previous menu bar contents data. */
328 if (previous_menu_items_used)
329 memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
330 previous_menu_items_used * word_size);
332 /* Fill in menu_items with the current menu bar contents.
333 This can evaluate Lisp code. */
334 save_menu_items ();
336 menu_items = f->menu_bar_vector;
337 menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
338 submenu_start = (int *) alloca (ASIZE (items) * sizeof (int));
339 submenu_end = (int *) alloca (ASIZE (items) * sizeof (int));
340 submenu_n_panes = (int *) alloca (ASIZE (items) * sizeof (int));
341 submenu_top_level_items = (int *) alloca (ASIZE (items) * sizeof (int));
342 init_menu_items ();
343 for (i = 0; i < ASIZE (items); i += 4)
345 Lisp_Object key, string, maps;
347 last_i = i;
349 key = AREF (items, i);
350 string = AREF (items, i + 1);
351 maps = AREF (items, i + 2);
352 if (NILP (string))
353 break;
355 submenu_start[i] = menu_items_used;
357 menu_items_n_panes = 0;
358 submenu_top_level_items[i]
359 = parse_single_submenu (key, string, maps);
360 submenu_n_panes[i] = menu_items_n_panes;
362 submenu_end[i] = menu_items_used;
365 finish_menu_items ();
367 /* Convert menu_items into widget_value trees
368 to display the menu. This cannot evaluate Lisp code. */
370 wv = xmalloc_widget_value ();
371 wv->name = "menubar";
372 wv->value = 0;
373 wv->enabled = 1;
374 wv->button_type = BUTTON_TYPE_NONE;
375 wv->help = Qnil;
376 first_wv = wv;
378 for (i = 0; i < last_i; i += 4)
380 menu_items_n_panes = submenu_n_panes[i];
381 wv = digest_single_submenu (submenu_start[i], submenu_end[i],
382 submenu_top_level_items[i]);
383 if (prev_wv)
384 prev_wv->next = wv;
385 else
386 first_wv->contents = wv;
387 /* Don't set wv->name here; GC during the loop might relocate it. */
388 wv->enabled = 1;
389 wv->button_type = BUTTON_TYPE_NONE;
390 prev_wv = wv;
393 set_buffer_internal_1 (prev);
395 /* If there has been no change in the Lisp-level contents
396 of the menu bar, skip redisplaying it. Just exit. */
398 for (i = 0; i < previous_menu_items_used; i++)
399 if (menu_items_used == i
400 || (!EQ (previous_items[i], AREF (menu_items, i))))
401 break;
402 if (i == menu_items_used && i == previous_menu_items_used && i != 0)
404 free_menubar_widget_value_tree (first_wv);
405 discard_menu_items ();
406 unbind_to (specpdl_count, Qnil);
407 return;
410 fset_menu_bar_vector (f, menu_items);
411 f->menu_bar_items_used = menu_items_used;
413 /* This undoes save_menu_items. */
414 unbind_to (specpdl_count, Qnil);
416 /* Now GC cannot happen during the lifetime of the widget_value,
417 so it's safe to store data from a Lisp_String, as long as
418 local copies are made when the actual menu is created.
419 Windows takes care of this for normal string items, but
420 not for owner-drawn items or additional item-info. */
421 wv = first_wv->contents;
422 for (i = 0; i < ASIZE (items); i += 4)
424 Lisp_Object string;
425 string = AREF (items, i + 1);
426 if (NILP (string))
427 break;
428 wv->name = SSDATA (string);
429 update_submenu_strings (wv->contents);
430 wv = wv->next;
433 else
435 /* Make a widget-value tree containing
436 just the top level menu bar strings. */
438 wv = xmalloc_widget_value ();
439 wv->name = "menubar";
440 wv->value = 0;
441 wv->enabled = 1;
442 wv->button_type = BUTTON_TYPE_NONE;
443 wv->help = Qnil;
444 first_wv = wv;
446 items = FRAME_MENU_BAR_ITEMS (f);
447 for (i = 0; i < ASIZE (items); i += 4)
449 Lisp_Object string;
451 string = AREF (items, i + 1);
452 if (NILP (string))
453 break;
455 wv = xmalloc_widget_value ();
456 wv->name = SSDATA (string);
457 wv->value = 0;
458 wv->enabled = 1;
459 wv->button_type = BUTTON_TYPE_NONE;
460 wv->help = Qnil;
461 /* This prevents lwlib from assuming this
462 menu item is really supposed to be empty. */
463 /* The EMACS_INT cast avoids a warning.
464 This value just has to be different from small integers. */
465 wv->call_data = (void *) (EMACS_INT) (-1);
467 if (prev_wv)
468 prev_wv->next = wv;
469 else
470 first_wv->contents = wv;
471 prev_wv = wv;
474 /* Forget what we thought we knew about what is in the
475 detailed contents of the menu bar menus.
476 Changing the top level always destroys the contents. */
477 f->menu_bar_items_used = 0;
480 /* Create or update the menu bar widget. */
482 block_input ();
484 if (menubar_widget)
486 /* Empty current menubar, rather than creating a fresh one. */
487 while (DeleteMenu (menubar_widget, 0, MF_BYPOSITION))
490 else
492 menubar_widget = CreateMenu ();
494 fill_in_menu (menubar_widget, first_wv->contents);
496 free_menubar_widget_value_tree (first_wv);
499 HMENU old_widget = f->output_data.w32->menubar_widget;
501 f->output_data.w32->menubar_widget = menubar_widget;
502 SetMenu (FRAME_W32_WINDOW (f), f->output_data.w32->menubar_widget);
503 /* Causes flicker when menu bar is updated
504 DrawMenuBar (FRAME_W32_WINDOW (f)); */
506 /* Force the window size to be recomputed so that the frame's text
507 area remains the same, if menubar has just been created. */
508 if (old_widget == NULL)
509 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
512 unblock_input ();
515 /* Called from Fx_create_frame to create the initial menubar of a frame
516 before it is mapped, so that the window is mapped with the menubar already
517 there instead of us tacking it on later and thrashing the window after it
518 is visible. */
520 void
521 initialize_frame_menubar (struct frame *f)
523 /* This function is called before the first chance to redisplay
524 the frame. It has to be, so the frame will have the right size. */
525 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
526 set_frame_menubar (f, 1, 1);
529 /* Get rid of the menu bar of frame F, and free its storage.
530 This is used when deleting a frame, and when turning off the menu bar. */
532 void
533 free_frame_menubar (struct frame *f)
535 block_input ();
538 HMENU old = GetMenu (FRAME_W32_WINDOW (f));
539 SetMenu (FRAME_W32_WINDOW (f), NULL);
540 f->output_data.w32->menubar_widget = NULL;
541 DestroyMenu (old);
544 unblock_input ();
548 /* w32_menu_show actually displays a menu using the panes and items in
549 menu_items and returns the value selected from it; we assume input
550 is blocked by the caller. */
552 /* F is the frame the menu is for.
553 X and Y are the frame-relative specified position,
554 relative to the inside upper left corner of the frame F.
555 FOR_CLICK is nonzero if this menu was invoked for a mouse click.
556 KEYMAPS is 1 if this menu was specified with keymaps;
557 in that case, we return a list containing the chosen item's value
558 and perhaps also the pane's prefix.
559 TITLE is the specified menu title.
560 ERROR is a place to store an error message string in case of failure.
561 (We return nil on failure, but the value doesn't actually matter.) */
563 Lisp_Object
564 w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
565 Lisp_Object title, const char **error)
567 int i;
568 int menu_item_selection;
569 HMENU menu;
570 POINT pos;
571 widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
572 widget_value **submenu_stack
573 = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
574 Lisp_Object *subprefix_stack
575 = (Lisp_Object *) alloca (menu_items_used * word_size);
576 int submenu_depth = 0;
577 int first_pane;
579 *error = NULL;
581 if (menu_items_n_panes == 0)
582 return Qnil;
584 if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
586 *error = "Empty menu";
587 return Qnil;
590 block_input ();
592 /* Create a tree of widget_value objects
593 representing the panes and their items. */
594 wv = xmalloc_widget_value ();
595 wv->name = "menu";
596 wv->value = 0;
597 wv->enabled = 1;
598 wv->button_type = BUTTON_TYPE_NONE;
599 wv->help = Qnil;
600 first_wv = wv;
601 first_pane = 1;
603 /* Loop over all panes and items, filling in the tree. */
604 i = 0;
605 while (i < menu_items_used)
607 if (EQ (AREF (menu_items, i), Qnil))
609 submenu_stack[submenu_depth++] = save_wv;
610 save_wv = prev_wv;
611 prev_wv = 0;
612 first_pane = 1;
613 i++;
615 else if (EQ (AREF (menu_items, i), Qlambda))
617 prev_wv = save_wv;
618 save_wv = submenu_stack[--submenu_depth];
619 first_pane = 0;
620 i++;
622 else if (EQ (AREF (menu_items, i), Qt)
623 && submenu_depth != 0)
624 i += MENU_ITEMS_PANE_LENGTH;
625 /* Ignore a nil in the item list.
626 It's meaningful only for dialog boxes. */
627 else if (EQ (AREF (menu_items, i), Qquote))
628 i += 1;
629 else if (EQ (AREF (menu_items, i), Qt))
631 /* Create a new pane. */
632 Lisp_Object pane_name, prefix;
633 char *pane_string;
634 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
635 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
637 if (STRINGP (pane_name))
639 if (unicode_append_menu)
640 pane_name = ENCODE_UTF_8 (pane_name);
641 else if (STRING_MULTIBYTE (pane_name))
642 pane_name = ENCODE_SYSTEM (pane_name);
644 ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
647 pane_string = (NILP (pane_name)
648 ? "" : SSDATA (pane_name));
649 /* If there is just one top-level pane, put all its items directly
650 under the top-level menu. */
651 if (menu_items_n_panes == 1)
652 pane_string = "";
654 /* If the pane has a meaningful name,
655 make the pane a top-level menu item
656 with its items as a submenu beneath it. */
657 if (!keymaps && strcmp (pane_string, ""))
659 wv = xmalloc_widget_value ();
660 if (save_wv)
661 save_wv->next = wv;
662 else
663 first_wv->contents = wv;
664 wv->name = pane_string;
665 if (keymaps && !NILP (prefix))
666 wv->name++;
667 wv->value = 0;
668 wv->enabled = 1;
669 wv->button_type = BUTTON_TYPE_NONE;
670 wv->help = Qnil;
671 save_wv = wv;
672 prev_wv = 0;
674 else if (first_pane)
676 save_wv = wv;
677 prev_wv = 0;
679 first_pane = 0;
680 i += MENU_ITEMS_PANE_LENGTH;
682 else
684 /* Create a new item within current pane. */
685 Lisp_Object item_name, enable, descrip, def, type, selected, help;
687 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
688 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
689 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
690 def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
691 type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
692 selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
693 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
695 if (STRINGP (item_name))
697 if (unicode_append_menu)
698 item_name = ENCODE_UTF_8 (item_name);
699 else if (STRING_MULTIBYTE (item_name))
700 item_name = ENCODE_SYSTEM (item_name);
702 ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
705 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
707 descrip = ENCODE_SYSTEM (descrip);
708 ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
711 wv = xmalloc_widget_value ();
712 if (prev_wv)
713 prev_wv->next = wv;
714 else
715 save_wv->contents = wv;
716 wv->name = SSDATA (item_name);
717 if (!NILP (descrip))
718 wv->key = SSDATA (descrip);
719 wv->value = 0;
720 /* Use the contents index as call_data, since we are
721 restricted to 16-bits. */
722 wv->call_data = !NILP (def) ? (void *) (EMACS_INT) i : 0;
723 wv->enabled = !NILP (enable);
725 if (NILP (type))
726 wv->button_type = BUTTON_TYPE_NONE;
727 else if (EQ (type, QCtoggle))
728 wv->button_type = BUTTON_TYPE_TOGGLE;
729 else if (EQ (type, QCradio))
730 wv->button_type = BUTTON_TYPE_RADIO;
731 else
732 emacs_abort ();
734 wv->selected = !NILP (selected);
736 if (!STRINGP (help))
737 help = Qnil;
739 wv->help = help;
741 prev_wv = wv;
743 i += MENU_ITEMS_ITEM_LENGTH;
747 /* Deal with the title, if it is non-nil. */
748 if (!NILP (title))
750 widget_value *wv_title = xmalloc_widget_value ();
751 widget_value *wv_sep = xmalloc_widget_value ();
753 /* Maybe replace this separator with a bitmap or owner-draw item
754 so that it looks better. Having two separators looks odd. */
755 wv_sep->name = "--";
756 wv_sep->next = first_wv->contents;
757 wv_sep->help = Qnil;
759 if (unicode_append_menu)
760 title = ENCODE_UTF_8 (title);
761 else if (STRING_MULTIBYTE (title))
762 title = ENCODE_SYSTEM (title);
764 wv_title->name = SSDATA (title);
765 wv_title->enabled = TRUE;
766 wv_title->title = TRUE;
767 wv_title->button_type = BUTTON_TYPE_NONE;
768 wv_title->help = Qnil;
769 wv_title->next = wv_sep;
770 first_wv->contents = wv_title;
773 /* No selection has been chosen yet. */
774 menu_item_selection = 0;
776 /* Actually create the menu. */
777 current_popup_menu = menu = CreatePopupMenu ();
778 fill_in_menu (menu, first_wv->contents);
780 /* Adjust coordinates to be root-window-relative. */
781 pos.x = x;
782 pos.y = y;
783 ClientToScreen (FRAME_W32_WINDOW (f), &pos);
785 /* Display the menu. */
786 menu_item_selection = SendMessage (FRAME_W32_WINDOW (f),
787 WM_EMACS_TRACKPOPUPMENU,
788 (WPARAM)menu, (LPARAM)&pos);
790 /* Clean up extraneous mouse events which might have been generated
791 during the call. */
792 discard_mouse_events ();
793 FRAME_DISPLAY_INFO (f)->grabbed = 0;
795 /* Free the widget_value objects we used to specify the contents. */
796 free_menubar_widget_value_tree (first_wv);
798 DestroyMenu (menu);
800 /* Free the owner-drawn and help-echo menu strings. */
801 w32_free_menu_strings (FRAME_W32_WINDOW (f));
802 f->output_data.w32->menubar_active = 0;
804 /* Find the selected item, and its pane, to return
805 the proper value. */
806 if (menu_item_selection != 0)
808 Lisp_Object prefix, entry;
810 prefix = entry = Qnil;
811 i = 0;
812 while (i < menu_items_used)
814 if (EQ (AREF (menu_items, i), Qnil))
816 subprefix_stack[submenu_depth++] = prefix;
817 prefix = entry;
818 i++;
820 else if (EQ (AREF (menu_items, i), Qlambda))
822 prefix = subprefix_stack[--submenu_depth];
823 i++;
825 else if (EQ (AREF (menu_items, i), Qt))
827 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
828 i += MENU_ITEMS_PANE_LENGTH;
830 /* Ignore a nil in the item list.
831 It's meaningful only for dialog boxes. */
832 else if (EQ (AREF (menu_items, i), Qquote))
833 i += 1;
834 else
836 entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
837 if (menu_item_selection == i)
839 if (keymaps != 0)
841 int j;
843 entry = Fcons (entry, Qnil);
844 if (!NILP (prefix))
845 entry = Fcons (prefix, entry);
846 for (j = submenu_depth - 1; j >= 0; j--)
847 if (!NILP (subprefix_stack[j]))
848 entry = Fcons (subprefix_stack[j], entry);
850 unblock_input ();
851 return entry;
853 i += MENU_ITEMS_ITEM_LENGTH;
857 else if (!for_click)
859 unblock_input ();
860 /* Make "Cancel" equivalent to C-g. */
861 Fsignal (Qquit, Qnil);
864 unblock_input ();
865 return Qnil;
869 #ifdef HAVE_DIALOGS
870 /* TODO: On Windows, there are two ways of defining a dialog.
872 1. Create a predefined dialog resource and include it in nt/emacs.rc.
873 Using this method, we could then set the titles and make unneeded
874 buttons invisible before displaying the dialog. Everything would
875 be a fixed size though, so there is a risk that text does not
876 fit on a button.
877 2. Create the dialog template in memory on the fly. This allows us
878 to size the dialog and buttons dynamically, probably giving more
879 natural looking results for dialogs with few buttons, and eliminating
880 the problem of text overflowing the buttons. But the API for this is
881 quite complex - structures have to be allocated in particular ways,
882 text content is tacked onto the end of structures in variable length
883 arrays with further structures tacked on after these, there are
884 certain alignment requirements for all this, and we have to
885 measure all the text and convert to "dialog coordinates" to figure
886 out how big to make everything.
888 For now, we'll just stick with menus for dialogs that are more
889 complicated than simple yes/no type questions for which we can use
890 the MessageBox function.
893 static char * button_names [] = {
894 "button1", "button2", "button3", "button4", "button5",
895 "button6", "button7", "button8", "button9", "button10" };
897 static Lisp_Object
898 w32_dialog_show (struct frame *f, int keymaps,
899 Lisp_Object title, Lisp_Object header,
900 char **error)
902 int i, nb_buttons = 0;
903 char dialog_name[6];
904 int menu_item_selection;
906 widget_value *wv, *first_wv = 0, *prev_wv = 0;
908 /* Number of elements seen so far, before boundary. */
909 int left_count = 0;
910 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
911 int boundary_seen = 0;
913 *error = NULL;
915 if (menu_items_n_panes > 1)
917 *error = "Multiple panes in dialog box";
918 return Qnil;
921 /* Create a tree of widget_value objects
922 representing the text label and buttons. */
924 Lisp_Object pane_name, prefix;
925 char *pane_string;
926 pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
927 prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX);
928 pane_string = (NILP (pane_name)
929 ? "" : SSDATA (pane_name));
930 prev_wv = xmalloc_widget_value ();
931 prev_wv->value = pane_string;
932 if (keymaps && !NILP (prefix))
933 prev_wv->name++;
934 prev_wv->enabled = 1;
935 prev_wv->name = "message";
936 prev_wv->help = Qnil;
937 first_wv = prev_wv;
939 /* Loop over all panes and items, filling in the tree. */
940 i = MENU_ITEMS_PANE_LENGTH;
941 while (i < menu_items_used)
944 /* Create a new item within current pane. */
945 Lisp_Object item_name, enable, descrip, help;
947 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
948 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
949 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
950 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
952 if (NILP (item_name))
954 free_menubar_widget_value_tree (first_wv);
955 *error = "Submenu in dialog items";
956 return Qnil;
958 if (EQ (item_name, Qquote))
960 /* This is the boundary between left-side elts
961 and right-side elts. Stop incrementing right_count. */
962 boundary_seen = 1;
963 i++;
964 continue;
966 if (nb_buttons >= 9)
968 free_menubar_widget_value_tree (first_wv);
969 *error = "Too many dialog items";
970 return Qnil;
973 wv = xmalloc_widget_value ();
974 prev_wv->next = wv;
975 wv->name = (char *) button_names[nb_buttons];
976 if (!NILP (descrip))
977 wv->key = SSDATA (descrip);
978 wv->value = SSDATA (item_name);
979 wv->call_data = aref_addr (menu_items, i);
980 wv->enabled = !NILP (enable);
981 wv->help = Qnil;
982 prev_wv = wv;
984 if (! boundary_seen)
985 left_count++;
987 nb_buttons++;
988 i += MENU_ITEMS_ITEM_LENGTH;
991 /* If the boundary was not specified,
992 by default put half on the left and half on the right. */
993 if (! boundary_seen)
994 left_count = nb_buttons - nb_buttons / 2;
996 wv = xmalloc_widget_value ();
997 wv->name = dialog_name;
998 wv->help = Qnil;
1000 /* Frame title: 'Q' = Question, 'I' = Information.
1001 Can also have 'E' = Error if, one day, we want
1002 a popup for errors. */
1003 if (NILP (header))
1004 dialog_name[0] = 'Q';
1005 else
1006 dialog_name[0] = 'I';
1008 /* Dialog boxes use a really stupid name encoding
1009 which specifies how many buttons to use
1010 and how many buttons are on the right. */
1011 dialog_name[1] = '0' + nb_buttons;
1012 dialog_name[2] = 'B';
1013 dialog_name[3] = 'R';
1014 /* Number of buttons to put on the right. */
1015 dialog_name[4] = '0' + nb_buttons - left_count;
1016 dialog_name[5] = 0;
1017 wv->contents = first_wv;
1018 first_wv = wv;
1021 /* Actually create the dialog. */
1022 dialog_id = widget_id_tick++;
1023 menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
1024 f->output_data.w32->widget, 1, 0,
1025 dialog_selection_callback, 0);
1026 lw_modify_all_widgets (dialog_id, first_wv->contents, TRUE);
1028 /* Free the widget_value objects we used to specify the contents. */
1029 free_menubar_widget_value_tree (first_wv);
1031 /* No selection has been chosen yet. */
1032 menu_item_selection = 0;
1034 /* Display the menu. */
1035 lw_pop_up_all_widgets (dialog_id);
1037 /* Process events that apply to the menu. */
1038 popup_get_selection ((XEvent *) 0, FRAME_DISPLAY_INFO (f), dialog_id);
1040 lw_destroy_all_widgets (dialog_id);
1042 /* Find the selected item, and its pane, to return
1043 the proper value. */
1044 if (menu_item_selection != 0)
1046 Lisp_Object prefix;
1048 prefix = Qnil;
1049 i = 0;
1050 while (i < menu_items_used)
1052 Lisp_Object entry;
1054 if (EQ (AREF (menu_items, i), Qt))
1056 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
1057 i += MENU_ITEMS_PANE_LENGTH;
1059 else
1061 entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
1062 if (menu_item_selection == i)
1064 if (keymaps != 0)
1066 entry = Fcons (entry, Qnil);
1067 if (!NILP (prefix))
1068 entry = Fcons (prefix, entry);
1070 return entry;
1072 i += MENU_ITEMS_ITEM_LENGTH;
1076 else
1077 /* Make "Cancel" equivalent to C-g. */
1078 Fsignal (Qquit, Qnil);
1080 return Qnil;
1082 #else /* !HAVE_DIALOGS */
1084 /* Currently we only handle Yes No dialogs (y-or-n-p and yes-or-no-p) as
1085 simple dialogs. We could handle a few more, but I'm not aware of
1086 anywhere in Emacs that uses the other specific dialog choices that
1087 MessageBox provides. */
1089 static int
1090 is_simple_dialog (Lisp_Object contents)
1092 Lisp_Object options;
1093 Lisp_Object name, yes, no, other;
1095 if (!CONSP (contents))
1096 return 0;
1097 options = XCDR (contents);
1099 yes = build_string ("Yes");
1100 no = build_string ("No");
1102 if (!CONSP (options))
1103 return 0;
1105 name = XCAR (options);
1106 if (!CONSP (name))
1107 return 0;
1108 name = XCAR (name);
1110 if (!NILP (Fstring_equal (name, yes)))
1111 other = no;
1112 else if (!NILP (Fstring_equal (name, no)))
1113 other = yes;
1114 else
1115 return 0;
1117 options = XCDR (options);
1118 if (!CONSP (options))
1119 return 0;
1121 name = XCAR (options);
1122 if (!CONSP (name))
1123 return 0;
1124 name = XCAR (name);
1125 if (NILP (Fstring_equal (name, other)))
1126 return 0;
1128 /* Check there are no more options. */
1129 options = XCDR (options);
1130 return !(CONSP (options));
1133 static Lisp_Object
1134 simple_dialog_show (struct frame *f, Lisp_Object contents, Lisp_Object header)
1136 int answer;
1137 UINT type;
1138 Lisp_Object lispy_answer = Qnil, temp = XCAR (contents);
1140 type = MB_YESNO;
1142 /* Since we only handle Yes/No dialogs, and we already checked
1143 is_simple_dialog, we don't need to worry about checking contents
1144 to see what type of dialog to use. */
1146 /* Use Unicode if possible, so any language can be displayed. */
1147 if (unicode_message_box)
1149 WCHAR *text, *title;
1150 USE_SAFE_ALLOCA;
1152 if (STRINGP (temp))
1154 char *utf8_text = SDATA (ENCODE_UTF_8 (temp));
1155 /* Be pessimistic about the number of characters needed.
1156 Remember characters outside the BMP will take more than
1157 one utf16 word, so we cannot simply use the character
1158 length of temp. */
1159 int utf8_len = strlen (utf8_text);
1160 text = SAFE_ALLOCA ((utf8_len + 1) * sizeof (WCHAR));
1161 utf8to16 (utf8_text, utf8_len, text);
1163 else
1165 text = L"";
1168 if (NILP (header))
1170 title = L"Question";
1171 type |= MB_ICONQUESTION;
1173 else
1175 title = L"Information";
1176 type |= MB_ICONINFORMATION;
1179 answer = unicode_message_box (FRAME_W32_WINDOW (f), text, title, type);
1180 SAFE_FREE ();
1182 else
1184 char *text, *title;
1186 /* Fall back on ANSI message box, but at least use system
1187 encoding so questions representable by the system codepage
1188 are encoded properly. */
1189 if (STRINGP (temp))
1190 text = SDATA (ENCODE_SYSTEM (temp));
1191 else
1192 text = "";
1194 if (NILP (header))
1196 title = "Question";
1197 type |= MB_ICONQUESTION;
1199 else
1201 title = "Information";
1202 type |= MB_ICONINFORMATION;
1205 answer = MessageBox (FRAME_W32_WINDOW (f), text, title, type);
1208 if (answer == IDYES)
1209 lispy_answer = build_string ("Yes");
1210 else if (answer == IDNO)
1211 lispy_answer = build_string ("No");
1212 else
1213 Fsignal (Qquit, Qnil);
1215 for (temp = XCDR (contents); CONSP (temp); temp = XCDR (temp))
1217 Lisp_Object item, name, value;
1218 item = XCAR (temp);
1219 if (CONSP (item))
1221 name = XCAR (item);
1222 value = XCDR (item);
1224 else
1226 name = item;
1227 value = Qnil;
1230 if (!NILP (Fstring_equal (name, lispy_answer)))
1232 return value;
1235 Fsignal (Qquit, Qnil);
1236 return Qnil;
1238 #endif /* !HAVE_DIALOGS */
1241 /* UTF8: 0xxxxxxx, 110xxxxx 10xxxxxx, 1110xxxx, 10xxxxxx, 10xxxxxx */
1242 static void
1243 utf8to16 (unsigned char * src, int len, WCHAR * dest)
1245 while (len > 0)
1247 if (*src < 0x80)
1249 *dest = (WCHAR) *src;
1250 dest++; src++; len--;
1252 /* Since we might get >3 byte sequences which we don't handle, ignore the extra parts. */
1253 else if (*src < 0xC0)
1255 src++; len--;
1257 /* 2 char UTF-8 sequence. */
1258 else if (*src < 0xE0)
1260 *dest = (WCHAR) (((*src & 0x1f) << 6)
1261 | (*(src + 1) & 0x3f));
1262 src += 2; len -= 2; dest++;
1264 else if (*src < 0xF0)
1266 *dest = (WCHAR) (((*src & 0x0f) << 12)
1267 | ((*(src + 1) & 0x3f) << 6)
1268 | (*(src + 2) & 0x3f));
1269 src += 3; len -= 3; dest++;
1271 else /* Not encodable. Insert Unicode Substitution char. */
1273 *dest = (WCHAR) 0xfffd;
1274 src++; len--; dest++;
1277 *dest = 0;
1280 static int
1281 add_menu_item (HMENU menu, widget_value *wv, HMENU item)
1283 UINT fuFlags;
1284 char *out_string, *p, *q;
1285 int return_value;
1286 size_t nlen, orig_len;
1287 USE_SAFE_ALLOCA;
1289 if (menu_separator_name_p (wv->name))
1291 fuFlags = MF_SEPARATOR;
1292 out_string = NULL;
1294 else
1296 if (wv->enabled)
1297 fuFlags = MF_STRING;
1298 else
1299 fuFlags = MF_STRING | MF_GRAYED;
1301 if (wv->key != NULL)
1303 out_string = SAFE_ALLOCA (strlen (wv->name) + strlen (wv->key) + 2);
1304 strcpy (out_string, wv->name);
1305 strcat (out_string, "\t");
1306 strcat (out_string, wv->key);
1308 else
1309 out_string = (char *)wv->name;
1311 /* Quote any special characters within the menu item's text and
1312 key binding. */
1313 nlen = orig_len = strlen (out_string);
1314 if (unicode_append_menu)
1316 /* With UTF-8, & cannot be part of a multibyte character. */
1317 for (p = out_string; *p; p++)
1319 if (*p == '&')
1320 nlen++;
1323 #ifndef NTGUI_UNICODE
1324 else
1326 /* If encoded with the system codepage, use multibyte string
1327 functions in case of multibyte characters that contain '&'. */
1328 for (p = out_string; *p; p = _mbsinc (p))
1330 if (_mbsnextc (p) == '&')
1331 nlen++;
1334 #endif /* !NTGUI_UNICODE */
1336 if (nlen > orig_len)
1338 p = out_string;
1339 out_string = SAFE_ALLOCA (nlen + 1);
1340 q = out_string;
1341 while (*p)
1343 if (unicode_append_menu)
1345 if (*p == '&')
1346 *q++ = *p;
1347 *q++ = *p++;
1349 #ifndef NTGUI_UNICODE
1350 else
1352 if (_mbsnextc (p) == '&')
1354 _mbsncpy (q, p, 1);
1355 q = _mbsinc (q);
1357 _mbsncpy (q, p, 1);
1358 p = _mbsinc (p);
1359 q = _mbsinc (q);
1361 #endif /* !NTGUI_UNICODE */
1363 *q = '\0';
1366 if (item != NULL)
1367 fuFlags = MF_POPUP;
1368 else if (wv->title || wv->call_data == 0)
1370 /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since
1371 we can't deallocate the memory otherwise. */
1372 if (get_menu_item_info)
1374 out_string = (char *) local_alloc (strlen (wv->name) + 1);
1375 strcpy (out_string, wv->name);
1376 #ifdef MENU_DEBUG
1377 DebPrint ("Menu: allocating %ld for owner-draw", out_string);
1378 #endif
1379 fuFlags = MF_OWNERDRAW | MF_DISABLED;
1381 else
1382 fuFlags = MF_DISABLED;
1385 /* Draw radio buttons and tickboxes. */
1386 else if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE ||
1387 wv->button_type == BUTTON_TYPE_RADIO))
1388 fuFlags |= MF_CHECKED;
1389 else
1390 fuFlags |= MF_UNCHECKED;
1393 if (unicode_append_menu && out_string)
1395 /* Convert out_string from UTF-8 to UTF-16-LE. */
1396 int utf8_len = strlen (out_string);
1397 WCHAR * utf16_string;
1398 if (fuFlags & MF_OWNERDRAW)
1399 utf16_string = local_alloc ((utf8_len + 1) * sizeof (WCHAR));
1400 else
1401 utf16_string = SAFE_ALLOCA ((utf8_len + 1) * sizeof (WCHAR));
1403 utf8to16 (out_string, utf8_len, utf16_string);
1404 return_value = unicode_append_menu (menu, fuFlags,
1405 item != NULL ? (UINT_PTR) item
1406 : (UINT_PTR) wv->call_data,
1407 utf16_string);
1409 #ifndef NTGUI_UNICODE /* Fallback does not apply when always UNICODE */
1410 if (!return_value)
1412 /* On W9x/ME, Unicode menus are not supported, though AppendMenuW
1413 apparently does exist at least in some cases and appears to be
1414 stubbed out to do nothing. out_string is UTF-8, but since
1415 our standard menus are in English and this is only going to
1416 happen the first time a menu is used, the encoding is
1417 of minor importance compared with menus not working at all. */
1418 return_value =
1419 AppendMenu (menu, fuFlags,
1420 item != NULL ? (UINT_PTR) item: (UINT_PTR) wv->call_data,
1421 out_string);
1422 /* Don't use Unicode menus in future, unless this is Windows
1423 NT or later, where a failure of AppendMenuW does NOT mean
1424 Unicode menus are unsupported. */
1425 if (osinfo_cache.dwPlatformId != VER_PLATFORM_WIN32_NT)
1426 unicode_append_menu = NULL;
1428 #endif /* NTGUI_UNICODE */
1430 if (unicode_append_menu && (fuFlags & MF_OWNERDRAW))
1431 local_free (out_string);
1433 else
1435 return_value =
1436 AppendMenu (menu,
1437 fuFlags,
1438 item != NULL ? (UINT_PTR) item : (UINT_PTR) wv->call_data,
1439 out_string );
1442 /* This must be done after the menu item is created. */
1443 if (!wv->title && wv->call_data != 0)
1445 if (set_menu_item_info)
1447 MENUITEMINFO info;
1448 memset (&info, 0, sizeof (info));
1449 info.cbSize = sizeof (info);
1450 info.fMask = MIIM_DATA;
1452 /* Set help string for menu item. Leave it as a Lisp_Object
1453 until it is ready to be displayed, since GC can happen while
1454 menus are active. */
1455 if (!NILP (wv->help))
1457 /* As of Jul-2012, w32api headers say that dwItemData
1458 has DWORD type, but that's a bug: it should actually
1459 be ULONG_PTR, which is correct for 32-bit and 64-bit
1460 Windows alike. MSVC headers get it right; hopefully,
1461 MinGW headers will, too. */
1462 info.dwItemData = (ULONG_PTR) XLI (wv->help);
1464 if (wv->button_type == BUTTON_TYPE_RADIO)
1466 /* CheckMenuRadioItem allows us to differentiate TOGGLE and
1467 RADIO items, but is not available on NT 3.51 and earlier. */
1468 info.fMask |= MIIM_TYPE | MIIM_STATE;
1469 info.fType = MFT_RADIOCHECK | MFT_STRING;
1470 info.dwTypeData = out_string;
1471 info.fState = wv->selected ? MFS_CHECKED : MFS_UNCHECKED;
1474 set_menu_item_info (menu,
1475 item != NULL ? (UINT_PTR) item : (UINT_PTR) wv->call_data,
1476 FALSE, &info);
1479 SAFE_FREE ();
1480 return return_value;
1483 /* Construct native Windows menu(bar) based on widget_value tree. */
1484 static int
1485 fill_in_menu (HMENU menu, widget_value *wv)
1487 for ( ; wv != NULL; wv = wv->next)
1489 if (wv->contents)
1491 HMENU sub_menu = CreatePopupMenu ();
1493 if (sub_menu == NULL)
1494 return 0;
1496 if (!fill_in_menu (sub_menu, wv->contents) ||
1497 !add_menu_item (menu, wv, sub_menu))
1499 DestroyMenu (sub_menu);
1500 return 0;
1503 else
1505 if (!add_menu_item (menu, wv, NULL))
1506 return 0;
1509 return 1;
1512 /* Display help string for currently pointed to menu item. Not
1513 supported on NT 3.51 and earlier, as GetMenuItemInfo is not
1514 available. */
1515 void
1516 w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags)
1518 if (get_menu_item_info)
1520 struct frame *f = x_window_to_frame (&one_w32_display_info, owner);
1521 Lisp_Object frame, help;
1523 /* No help echo on owner-draw menu items, or when the keyboard is used
1524 to navigate the menus, since tooltips are distracting if they pop
1525 up elsewhere. */
1526 if (flags & MF_OWNERDRAW || flags & MF_POPUP
1527 || !(flags & MF_MOUSESELECT))
1528 help = Qnil;
1529 else
1531 MENUITEMINFO info;
1533 memset (&info, 0, sizeof (info));
1534 info.cbSize = sizeof (info);
1535 info.fMask = MIIM_DATA;
1536 get_menu_item_info (menu, item, FALSE, &info);
1538 help = info.dwItemData ? XIL (info.dwItemData) : Qnil;
1541 /* Store the help echo in the keyboard buffer as the X toolkit
1542 version does, rather than directly showing it. This seems to
1543 solve the GC problems that were present when we based the
1544 Windows code on the non-toolkit version. */
1545 if (f)
1547 XSETFRAME (frame, f);
1548 kbd_buffer_store_help_event (frame, help);
1550 else
1551 /* X version has a loop through frames here, which doesn't
1552 appear to do anything, unless it has some side effect. */
1553 show_help_echo (help, Qnil, Qnil, Qnil);
1557 /* Free memory used by owner-drawn strings. */
1558 static void
1559 w32_free_submenu_strings (HMENU menu)
1561 int i, num = GetMenuItemCount (menu);
1562 for (i = 0; i < num; i++)
1564 MENUITEMINFO info;
1565 memset (&info, 0, sizeof (info));
1566 info.cbSize = sizeof (info);
1567 info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_SUBMENU;
1569 get_menu_item_info (menu, i, TRUE, &info);
1571 /* Owner-drawn names are held in dwItemData. */
1572 if ((info.fType & MF_OWNERDRAW) && info.dwItemData)
1574 #ifdef MENU_DEBUG
1575 DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData);
1576 #endif
1577 local_free (info.dwItemData);
1580 /* Recurse down submenus. */
1581 if (info.hSubMenu)
1582 w32_free_submenu_strings (info.hSubMenu);
1586 void
1587 w32_free_menu_strings (HWND hwnd)
1589 HMENU menu = current_popup_menu;
1591 if (get_menu_item_info)
1593 /* If there is no popup menu active, free the strings from the frame's
1594 menubar. */
1595 if (!menu)
1596 menu = GetMenu (hwnd);
1598 if (menu)
1599 w32_free_submenu_strings (menu);
1602 current_popup_menu = NULL;
1605 #endif /* HAVE_MENUS */
1607 /* The following is used by delayed window autoselection. */
1609 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
1610 doc: /* Return t if a menu or popup dialog is active on selected frame. */)
1611 (void)
1613 #ifdef HAVE_MENUS
1614 struct frame *f;
1615 f = SELECTED_FRAME ();
1616 return (f->output_data.w32->menubar_active > 0) ? Qt : Qnil;
1617 #else
1618 return Qnil;
1619 #endif /* HAVE_MENUS */
1622 void
1623 syms_of_w32menu (void)
1625 globals_of_w32menu ();
1627 current_popup_menu = NULL;
1629 DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
1631 defsubr (&Smenu_or_popup_active_p);
1635 globals_of_w32menu is used to initialize those global variables that
1636 must always be initialized on startup even when the global variable
1637 initialized is non zero (see the function main in emacs.c).
1638 globals_of_w32menu is called from syms_of_w32menu when the global
1639 variable initialized is 0 and directly from main when initialized
1640 is non zero.
1642 void
1643 globals_of_w32menu (void)
1645 #ifndef NTGUI_UNICODE
1646 /* See if Get/SetMenuItemInfo functions are available. */
1647 HMODULE user32 = GetModuleHandle ("user32.dll");
1648 get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA");
1649 set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA");
1650 unicode_append_menu = (AppendMenuW_Proc) GetProcAddress (user32, "AppendMenuW");
1651 unicode_message_box = (MessageBoxW_Proc) GetProcAddress (user32, "MessageBoxW");
1652 #endif /* !NTGUI_UNICODE */