Merge changes from emacs-23 branch.
[emacs.git] / src / w32menu.c
blobff6bd977bea7e8b55aeb854523911bb1709a2b9c
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, 2010
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/>. */
21 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <mbstring.h>
26 #include <setjmp.h>
28 #include "lisp.h"
29 #include "keyboard.h"
30 #include "keymap.h"
31 #include "frame.h"
32 #include "termhooks.h"
33 #include "window.h"
34 #include "blockinput.h"
35 #include "buffer.h"
36 #include "charset.h"
37 #include "character.h"
38 #include "coding.h"
39 #include "menu.h"
41 /* This may include sys/types.h, and that somehow loses
42 if this is not done before the other system files. */
43 #include "w32term.h"
45 /* Load sys/types.h if not already loaded.
46 In some systems loading it twice is suicidal. */
47 #ifndef makedev
48 #include <sys/types.h>
49 #endif
51 #include "dispextern.h"
53 #undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
55 #ifndef TRUE
56 #define TRUE 1
57 #define FALSE 0
58 #endif /* no TRUE */
60 HMENU current_popup_menu;
62 void syms_of_w32menu (void);
63 void globals_of_w32menu (void);
65 typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (
66 IN HMENU,
67 IN UINT,
68 IN BOOL,
69 IN OUT LPMENUITEMINFOA);
70 typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) (
71 IN HMENU,
72 IN UINT,
73 IN BOOL,
74 IN LPCMENUITEMINFOA);
75 typedef int (WINAPI * MessageBoxW_Proc) (
76 IN HWND window,
77 IN WCHAR *text,
78 IN WCHAR *caption,
79 IN UINT type);
81 GetMenuItemInfoA_Proc get_menu_item_info = NULL;
82 SetMenuItemInfoA_Proc set_menu_item_info = NULL;
83 AppendMenuW_Proc unicode_append_menu = NULL;
84 MessageBoxW_Proc unicode_message_box = NULL;
86 Lisp_Object Qdebug_on_next_call;
88 extern Lisp_Object Qmenu_bar;
90 extern Lisp_Object QCtoggle, QCradio;
92 extern Lisp_Object Voverriding_local_map;
93 extern Lisp_Object Voverriding_local_map_menu_flag;
95 extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
97 extern Lisp_Object Qmenu_bar_update_hook;
99 void set_frame_menubar (FRAME_PTR, int, int);
101 #ifdef HAVE_DIALOGS
102 static Lisp_Object w32_dialog_show (FRAME_PTR, int, Lisp_Object, char**);
103 #else
104 static int is_simple_dialog (Lisp_Object);
105 static Lisp_Object simple_dialog_show (FRAME_PTR, Lisp_Object, Lisp_Object);
106 #endif
108 static void utf8to16 (unsigned char *, int, WCHAR *);
109 static int fill_in_menu (HMENU, widget_value *);
111 void w32_free_menu_strings (HWND);
114 /* This is set nonzero after the user activates the menu bar, and set
115 to zero again after the menu bars are redisplayed by prepare_menu_bar.
116 While it is nonzero, all calls to set_frame_menubar go deep.
118 I don't understand why this is needed, but it does seem to be
119 needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
121 int pending_menu_activation;
123 #ifdef HAVE_MENUS
125 DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
126 doc: /* Pop up a dialog box and return user's selection.
127 POSITION specifies which frame to use.
128 This is normally a mouse button event or a window or frame.
129 If POSITION is t, it means to use the frame the mouse is on.
130 The dialog box appears in the middle of the specified frame.
132 CONTENTS specifies the alternatives to display in the dialog box.
133 It is a list of the form (TITLE ITEM1 ITEM2...).
134 Each ITEM is a cons cell (STRING . VALUE).
135 The return value is VALUE from the chosen item.
137 An ITEM may also be just a string--that makes a nonselectable item.
138 An ITEM may also be nil--that means to put all preceding items
139 on the left of the dialog box and all following items on the right.
140 \(By default, approximately half appear on each side.)
142 If HEADER is non-nil, the frame title for the box is "Information",
143 otherwise it is "Question". */)
144 (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
146 FRAME_PTR f = NULL;
147 Lisp_Object window;
149 check_w32 ();
151 /* Decode the first argument: find the window or frame to use. */
152 if (EQ (position, Qt)
153 || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
154 || EQ (XCAR (position), Qtool_bar))))
156 #if 0 /* Using the frame the mouse is on may not be right. */
157 /* Use the mouse's current position. */
158 FRAME_PTR new_f = SELECTED_FRAME ();
159 Lisp_Object bar_window;
160 enum scroll_bar_part part;
161 unsigned long time;
162 Lisp_Object x, y;
164 (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
166 if (new_f != 0)
167 XSETFRAME (window, new_f);
168 else
169 window = selected_window;
170 #endif
171 window = selected_window;
173 else if (CONSP (position))
175 Lisp_Object tem;
176 tem = Fcar (position);
177 if (CONSP (tem))
178 window = Fcar (Fcdr (position));
179 else
181 tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
182 window = Fcar (tem); /* POSN_WINDOW (tem) */
185 else if (WINDOWP (position) || FRAMEP (position))
186 window = position;
187 else
188 window = Qnil;
190 /* Decode where to put the menu. */
192 if (FRAMEP (window))
193 f = XFRAME (window);
194 else if (WINDOWP (window))
196 CHECK_LIVE_WINDOW (window);
197 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
199 else
200 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
201 but I don't want to make one now. */
202 CHECK_WINDOW (window);
204 #ifndef HAVE_DIALOGS
207 /* Handle simple Yes/No choices as MessageBox popups. */
208 if (is_simple_dialog (contents))
209 return simple_dialog_show (f, contents, header);
210 else
212 /* Display a menu with these alternatives
213 in the middle of frame F. */
214 Lisp_Object x, y, frame, newpos;
215 XSETFRAME (frame, f);
216 XSETINT (x, x_pixel_width (f) / 2);
217 XSETINT (y, x_pixel_height (f) / 2);
218 newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
219 return Fx_popup_menu (newpos,
220 Fcons (Fcar (contents), Fcons (contents, Qnil)));
223 #else /* HAVE_DIALOGS */
225 Lisp_Object title;
226 char *error_name;
227 Lisp_Object selection;
229 /* Decode the dialog items from what was specified. */
230 title = Fcar (contents);
231 CHECK_STRING (title);
233 list_of_panes (Fcons (contents, Qnil));
235 /* Display them in a dialog box. */
236 BLOCK_INPUT;
237 selection = w32_dialog_show (f, 0, title, header, &error_name);
238 UNBLOCK_INPUT;
240 discard_menu_items ();
241 FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
243 if (error_name) error (error_name);
244 return selection;
246 #endif /* HAVE_DIALOGS */
249 /* Activate the menu bar of frame F.
250 This is called from keyboard.c when it gets the
251 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
253 To activate the menu bar, we signal to the input thread that it can
254 return from the WM_INITMENU message, allowing the normal Windows
255 processing of the menus.
257 But first we recompute the menu bar contents (the whole tree).
259 This way we can safely execute Lisp code. */
261 void
262 x_activate_menubar (FRAME_PTR f)
264 set_frame_menubar (f, 0, 1);
266 /* Lock out further menubar changes while active. */
267 f->output_data.w32->menubar_active = 1;
269 /* Signal input thread to return from WM_INITMENU. */
270 complete_deferred_msg (FRAME_W32_WINDOW (f), WM_INITMENU, 0);
273 /* This callback is called from the menu bar pulldown menu
274 when the user makes a selection.
275 Figure out what the user chose
276 and put the appropriate events into the keyboard buffer. */
278 void
279 menubar_selection_callback (FRAME_PTR f, void * client_data)
281 Lisp_Object prefix, entry;
282 Lisp_Object vector;
283 Lisp_Object *subprefix_stack;
284 int submenu_depth = 0;
285 int i;
287 if (!f)
288 return;
289 entry = Qnil;
290 subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof (Lisp_Object));
291 vector = f->menu_bar_vector;
292 prefix = Qnil;
293 i = 0;
294 while (i < f->menu_bar_items_used)
296 if (EQ (AREF (vector, i), Qnil))
298 subprefix_stack[submenu_depth++] = prefix;
299 prefix = entry;
300 i++;
302 else if (EQ (AREF (vector, i), Qlambda))
304 prefix = subprefix_stack[--submenu_depth];
305 i++;
307 else if (EQ (AREF (vector, i), Qt))
309 prefix = AREF (vector, i + MENU_ITEMS_PANE_PREFIX);
310 i += MENU_ITEMS_PANE_LENGTH;
312 else
314 entry = AREF (vector, i + MENU_ITEMS_ITEM_VALUE);
315 /* The EMACS_INT cast avoids a warning. There's no problem
316 as long as pointers have enough bits to hold small integers. */
317 if ((int) (EMACS_INT) client_data == i)
319 int j;
320 struct input_event buf;
321 Lisp_Object frame;
322 EVENT_INIT (buf);
324 XSETFRAME (frame, f);
325 buf.kind = MENU_BAR_EVENT;
326 buf.frame_or_window = frame;
327 buf.arg = frame;
328 kbd_buffer_store_event (&buf);
330 for (j = 0; j < submenu_depth; j++)
331 if (!NILP (subprefix_stack[j]))
333 buf.kind = MENU_BAR_EVENT;
334 buf.frame_or_window = frame;
335 buf.arg = subprefix_stack[j];
336 kbd_buffer_store_event (&buf);
339 if (!NILP (prefix))
341 buf.kind = MENU_BAR_EVENT;
342 buf.frame_or_window = frame;
343 buf.arg = prefix;
344 kbd_buffer_store_event (&buf);
347 buf.kind = MENU_BAR_EVENT;
348 buf.frame_or_window = frame;
349 buf.arg = entry;
350 /* Free memory used by owner-drawn and help-echo strings. */
351 w32_free_menu_strings (FRAME_W32_WINDOW (f));
352 kbd_buffer_store_event (&buf);
354 f->output_data.w32->menubar_active = 0;
355 return;
357 i += MENU_ITEMS_ITEM_LENGTH;
360 /* Free memory used by owner-drawn and help-echo strings. */
361 w32_free_menu_strings (FRAME_W32_WINDOW (f));
362 f->output_data.w32->menubar_active = 0;
366 /* Set the contents of the menubar widgets of frame F.
367 The argument FIRST_TIME is currently ignored;
368 it is set the first time this is called, from initialize_frame_menubar. */
370 void
371 set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
373 HMENU menubar_widget = f->output_data.w32->menubar_widget;
374 Lisp_Object items;
375 widget_value *wv, *first_wv, *prev_wv = 0;
376 int i, last_i;
377 int *submenu_start, *submenu_end;
378 int *submenu_top_level_items, *submenu_n_panes;
380 /* We must not change the menubar when actually in use. */
381 if (f->output_data.w32->menubar_active)
382 return;
384 XSETFRAME (Vmenu_updating_frame, f);
386 if (! menubar_widget)
387 deep_p = 1;
388 else if (pending_menu_activation && !deep_p)
389 deep_p = 1;
391 if (deep_p)
393 /* Make a widget-value tree representing the entire menu trees. */
395 struct buffer *prev = current_buffer;
396 Lisp_Object buffer;
397 int specpdl_count = SPECPDL_INDEX ();
398 int previous_menu_items_used = f->menu_bar_items_used;
399 Lisp_Object *previous_items
400 = (Lisp_Object *) alloca (previous_menu_items_used
401 * sizeof (Lisp_Object));
403 /* If we are making a new widget, its contents are empty,
404 do always reinitialize them. */
405 if (! menubar_widget)
406 previous_menu_items_used = 0;
408 buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
409 specbind (Qinhibit_quit, Qt);
410 /* Don't let the debugger step into this code
411 because it is not reentrant. */
412 specbind (Qdebug_on_next_call, Qnil);
414 record_unwind_save_match_data ();
416 if (NILP (Voverriding_local_map_menu_flag))
418 specbind (Qoverriding_terminal_local_map, Qnil);
419 specbind (Qoverriding_local_map, Qnil);
422 set_buffer_internal_1 (XBUFFER (buffer));
424 /* Run the hooks. */
425 safe_run_hooks (Qactivate_menubar_hook);
426 safe_run_hooks (Qmenu_bar_update_hook);
427 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
429 items = FRAME_MENU_BAR_ITEMS (f);
431 /* Save the frame's previous menu bar contents data. */
432 if (previous_menu_items_used)
433 memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
434 previous_menu_items_used * sizeof (Lisp_Object));
436 /* Fill in menu_items with the current menu bar contents.
437 This can evaluate Lisp code. */
438 save_menu_items ();
440 menu_items = f->menu_bar_vector;
441 menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
442 submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
443 submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
444 submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int));
445 submenu_top_level_items
446 = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
447 init_menu_items ();
448 for (i = 0; i < ASIZE (items); i += 4)
450 Lisp_Object key, string, maps;
452 last_i = i;
454 key = AREF (items, i);
455 string = AREF (items, i + 1);
456 maps = AREF (items, i + 2);
457 if (NILP (string))
458 break;
460 submenu_start[i] = menu_items_used;
462 menu_items_n_panes = 0;
463 submenu_top_level_items[i]
464 = parse_single_submenu (key, string, maps);
465 submenu_n_panes[i] = menu_items_n_panes;
467 submenu_end[i] = menu_items_used;
470 finish_menu_items ();
472 /* Convert menu_items into widget_value trees
473 to display the menu. This cannot evaluate Lisp code. */
475 wv = xmalloc_widget_value ();
476 wv->name = "menubar";
477 wv->value = 0;
478 wv->enabled = 1;
479 wv->button_type = BUTTON_TYPE_NONE;
480 wv->help = Qnil;
481 first_wv = wv;
483 for (i = 0; i < last_i; i += 4)
485 menu_items_n_panes = submenu_n_panes[i];
486 wv = digest_single_submenu (submenu_start[i], submenu_end[i],
487 submenu_top_level_items[i]);
488 if (prev_wv)
489 prev_wv->next = wv;
490 else
491 first_wv->contents = wv;
492 /* Don't set wv->name here; GC during the loop might relocate it. */
493 wv->enabled = 1;
494 wv->button_type = BUTTON_TYPE_NONE;
495 prev_wv = wv;
498 set_buffer_internal_1 (prev);
500 /* If there has been no change in the Lisp-level contents
501 of the menu bar, skip redisplaying it. Just exit. */
503 for (i = 0; i < previous_menu_items_used; i++)
504 if (menu_items_used == i
505 || (!EQ (previous_items[i], AREF (menu_items, i))))
506 break;
507 if (i == menu_items_used && i == previous_menu_items_used && i != 0)
509 free_menubar_widget_value_tree (first_wv);
510 discard_menu_items ();
511 unbind_to (specpdl_count, Qnil);
512 return;
515 f->menu_bar_vector = menu_items;
516 f->menu_bar_items_used = menu_items_used;
518 /* This undoes save_menu_items. */
519 unbind_to (specpdl_count, Qnil);
521 /* Now GC cannot happen during the lifetime of the widget_value,
522 so it's safe to store data from a Lisp_String, as long as
523 local copies are made when the actual menu is created.
524 Windows takes care of this for normal string items, but
525 not for owner-drawn items or additional item-info. */
526 wv = first_wv->contents;
527 for (i = 0; i < ASIZE (items); i += 4)
529 Lisp_Object string;
530 string = AREF (items, i + 1);
531 if (NILP (string))
532 break;
533 wv->name = (char *) SDATA (string);
534 update_submenu_strings (wv->contents);
535 wv = wv->next;
538 else
540 /* Make a widget-value tree containing
541 just the top level menu bar strings. */
543 wv = xmalloc_widget_value ();
544 wv->name = "menubar";
545 wv->value = 0;
546 wv->enabled = 1;
547 wv->button_type = BUTTON_TYPE_NONE;
548 wv->help = Qnil;
549 first_wv = wv;
551 items = FRAME_MENU_BAR_ITEMS (f);
552 for (i = 0; i < ASIZE (items); i += 4)
554 Lisp_Object string;
556 string = AREF (items, i + 1);
557 if (NILP (string))
558 break;
560 wv = xmalloc_widget_value ();
561 wv->name = (char *) SDATA (string);
562 wv->value = 0;
563 wv->enabled = 1;
564 wv->button_type = BUTTON_TYPE_NONE;
565 wv->help = Qnil;
566 /* This prevents lwlib from assuming this
567 menu item is really supposed to be empty. */
568 /* The EMACS_INT cast avoids a warning.
569 This value just has to be different from small integers. */
570 wv->call_data = (void *) (EMACS_INT) (-1);
572 if (prev_wv)
573 prev_wv->next = wv;
574 else
575 first_wv->contents = wv;
576 prev_wv = wv;
579 /* Forget what we thought we knew about what is in the
580 detailed contents of the menu bar menus.
581 Changing the top level always destroys the contents. */
582 f->menu_bar_items_used = 0;
585 /* Create or update the menu bar widget. */
587 BLOCK_INPUT;
589 if (menubar_widget)
591 /* Empty current menubar, rather than creating a fresh one. */
592 while (DeleteMenu (menubar_widget, 0, MF_BYPOSITION))
595 else
597 menubar_widget = CreateMenu ();
599 fill_in_menu (menubar_widget, first_wv->contents);
601 free_menubar_widget_value_tree (first_wv);
604 HMENU old_widget = f->output_data.w32->menubar_widget;
606 f->output_data.w32->menubar_widget = menubar_widget;
607 SetMenu (FRAME_W32_WINDOW (f), f->output_data.w32->menubar_widget);
608 /* Causes flicker when menu bar is updated
609 DrawMenuBar (FRAME_W32_WINDOW (f)); */
611 /* Force the window size to be recomputed so that the frame's text
612 area remains the same, if menubar has just been created. */
613 if (old_widget == NULL)
614 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
617 UNBLOCK_INPUT;
620 /* Called from Fx_create_frame to create the initial menubar of a frame
621 before it is mapped, so that the window is mapped with the menubar already
622 there instead of us tacking it on later and thrashing the window after it
623 is visible. */
625 void
626 initialize_frame_menubar (FRAME_PTR f)
628 /* This function is called before the first chance to redisplay
629 the frame. It has to be, so the frame will have the right size. */
630 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
631 set_frame_menubar (f, 1, 1);
634 /* Get rid of the menu bar of frame F, and free its storage.
635 This is used when deleting a frame, and when turning off the menu bar. */
637 void
638 free_frame_menubar (FRAME_PTR f)
640 BLOCK_INPUT;
643 HMENU old = GetMenu (FRAME_W32_WINDOW (f));
644 SetMenu (FRAME_W32_WINDOW (f), NULL);
645 f->output_data.w32->menubar_widget = NULL;
646 DestroyMenu (old);
649 UNBLOCK_INPUT;
653 /* w32_menu_show actually displays a menu using the panes and items in
654 menu_items and returns the value selected from it; we assume input
655 is blocked by the caller. */
657 /* F is the frame the menu is for.
658 X and Y are the frame-relative specified position,
659 relative to the inside upper left corner of the frame F.
660 FOR_CLICK is nonzero if this menu was invoked for a mouse click.
661 KEYMAPS is 1 if this menu was specified with keymaps;
662 in that case, we return a list containing the chosen item's value
663 and perhaps also the pane's prefix.
664 TITLE is the specified menu title.
665 ERROR is a place to store an error message string in case of failure.
666 (We return nil on failure, but the value doesn't actually matter.) */
668 Lisp_Object
669 w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
670 Lisp_Object title, const char **error)
672 int i;
673 int menu_item_selection;
674 HMENU menu;
675 POINT pos;
676 widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
677 widget_value **submenu_stack
678 = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
679 Lisp_Object *subprefix_stack
680 = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
681 int submenu_depth = 0;
682 int first_pane;
684 *error = NULL;
686 if (menu_items_n_panes == 0)
687 return Qnil;
689 if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
691 *error = "Empty menu";
692 return Qnil;
695 /* Create a tree of widget_value objects
696 representing the panes and their items. */
697 wv = xmalloc_widget_value ();
698 wv->name = "menu";
699 wv->value = 0;
700 wv->enabled = 1;
701 wv->button_type = BUTTON_TYPE_NONE;
702 wv->help = Qnil;
703 first_wv = wv;
704 first_pane = 1;
706 /* Loop over all panes and items, filling in the tree. */
707 i = 0;
708 while (i < menu_items_used)
710 if (EQ (AREF (menu_items, i), Qnil))
712 submenu_stack[submenu_depth++] = save_wv;
713 save_wv = prev_wv;
714 prev_wv = 0;
715 first_pane = 1;
716 i++;
718 else if (EQ (AREF (menu_items, i), Qlambda))
720 prev_wv = save_wv;
721 save_wv = submenu_stack[--submenu_depth];
722 first_pane = 0;
723 i++;
725 else if (EQ (AREF (menu_items, i), Qt)
726 && submenu_depth != 0)
727 i += MENU_ITEMS_PANE_LENGTH;
728 /* Ignore a nil in the item list.
729 It's meaningful only for dialog boxes. */
730 else if (EQ (AREF (menu_items, i), Qquote))
731 i += 1;
732 else if (EQ (AREF (menu_items, i), Qt))
734 /* Create a new pane. */
735 Lisp_Object pane_name, prefix;
736 char *pane_string;
737 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
738 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
740 if (STRINGP (pane_name))
742 if (unicode_append_menu)
743 pane_name = ENCODE_UTF_8 (pane_name);
744 else if (STRING_MULTIBYTE (pane_name))
745 pane_name = ENCODE_SYSTEM (pane_name);
747 ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
750 pane_string = (NILP (pane_name)
751 ? "" : (char *) SDATA (pane_name));
752 /* If there is just one top-level pane, put all its items directly
753 under the top-level menu. */
754 if (menu_items_n_panes == 1)
755 pane_string = "";
757 /* If the pane has a meaningful name,
758 make the pane a top-level menu item
759 with its items as a submenu beneath it. */
760 if (!keymaps && strcmp (pane_string, ""))
762 wv = xmalloc_widget_value ();
763 if (save_wv)
764 save_wv->next = wv;
765 else
766 first_wv->contents = wv;
767 wv->name = pane_string;
768 if (keymaps && !NILP (prefix))
769 wv->name++;
770 wv->value = 0;
771 wv->enabled = 1;
772 wv->button_type = BUTTON_TYPE_NONE;
773 wv->help = Qnil;
774 save_wv = wv;
775 prev_wv = 0;
777 else if (first_pane)
779 save_wv = wv;
780 prev_wv = 0;
782 first_pane = 0;
783 i += MENU_ITEMS_PANE_LENGTH;
785 else
787 /* Create a new item within current pane. */
788 Lisp_Object item_name, enable, descrip, def, type, selected, help;
790 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
791 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
792 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
793 def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
794 type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
795 selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
796 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
798 if (STRINGP (item_name))
800 if (unicode_append_menu)
801 item_name = ENCODE_UTF_8 (item_name);
802 else if (STRING_MULTIBYTE (item_name))
803 item_name = ENCODE_SYSTEM (item_name);
805 ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
808 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
810 descrip = ENCODE_SYSTEM (descrip);
811 ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
814 wv = xmalloc_widget_value ();
815 if (prev_wv)
816 prev_wv->next = wv;
817 else
818 save_wv->contents = wv;
819 wv->name = (char *) SDATA (item_name);
820 if (!NILP (descrip))
821 wv->key = (char *) SDATA (descrip);
822 wv->value = 0;
823 /* Use the contents index as call_data, since we are
824 restricted to 16-bits. */
825 wv->call_data = !NILP (def) ? (void *) (EMACS_INT) i : 0;
826 wv->enabled = !NILP (enable);
828 if (NILP (type))
829 wv->button_type = BUTTON_TYPE_NONE;
830 else if (EQ (type, QCtoggle))
831 wv->button_type = BUTTON_TYPE_TOGGLE;
832 else if (EQ (type, QCradio))
833 wv->button_type = BUTTON_TYPE_RADIO;
834 else
835 abort ();
837 wv->selected = !NILP (selected);
839 if (!STRINGP (help))
840 help = Qnil;
842 wv->help = help;
844 prev_wv = wv;
846 i += MENU_ITEMS_ITEM_LENGTH;
850 /* Deal with the title, if it is non-nil. */
851 if (!NILP (title))
853 widget_value *wv_title = xmalloc_widget_value ();
854 widget_value *wv_sep = xmalloc_widget_value ();
856 /* Maybe replace this separator with a bitmap or owner-draw item
857 so that it looks better. Having two separators looks odd. */
858 wv_sep->name = "--";
859 wv_sep->next = first_wv->contents;
860 wv_sep->help = Qnil;
862 if (unicode_append_menu)
863 title = ENCODE_UTF_8 (title);
864 else if (STRING_MULTIBYTE (title))
865 title = ENCODE_SYSTEM (title);
867 wv_title->name = (char *) SDATA (title);
868 wv_title->enabled = TRUE;
869 wv_title->title = TRUE;
870 wv_title->button_type = BUTTON_TYPE_NONE;
871 wv_title->help = Qnil;
872 wv_title->next = wv_sep;
873 first_wv->contents = wv_title;
876 /* No selection has been chosen yet. */
877 menu_item_selection = 0;
879 /* Actually create the menu. */
880 current_popup_menu = menu = CreatePopupMenu ();
881 fill_in_menu (menu, first_wv->contents);
883 /* Adjust coordinates to be root-window-relative. */
884 pos.x = x;
885 pos.y = y;
886 ClientToScreen (FRAME_W32_WINDOW (f), &pos);
888 /* Display the menu. */
889 menu_item_selection = SendMessage (FRAME_W32_WINDOW (f),
890 WM_EMACS_TRACKPOPUPMENU,
891 (WPARAM)menu, (LPARAM)&pos);
893 /* Clean up extraneous mouse events which might have been generated
894 during the call. */
895 discard_mouse_events ();
896 FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
898 /* Free the widget_value objects we used to specify the contents. */
899 free_menubar_widget_value_tree (first_wv);
901 DestroyMenu (menu);
903 /* Free the owner-drawn and help-echo menu strings. */
904 w32_free_menu_strings (FRAME_W32_WINDOW (f));
905 f->output_data.w32->menubar_active = 0;
907 /* Find the selected item, and its pane, to return
908 the proper value. */
909 if (menu_item_selection != 0)
911 Lisp_Object prefix, entry;
913 prefix = entry = Qnil;
914 i = 0;
915 while (i < menu_items_used)
917 if (EQ (AREF (menu_items, i), Qnil))
919 subprefix_stack[submenu_depth++] = prefix;
920 prefix = entry;
921 i++;
923 else if (EQ (AREF (menu_items, i), Qlambda))
925 prefix = subprefix_stack[--submenu_depth];
926 i++;
928 else if (EQ (AREF (menu_items, i), Qt))
930 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
931 i += MENU_ITEMS_PANE_LENGTH;
933 /* Ignore a nil in the item list.
934 It's meaningful only for dialog boxes. */
935 else if (EQ (AREF (menu_items, i), Qquote))
936 i += 1;
937 else
939 entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
940 if (menu_item_selection == i)
942 if (keymaps != 0)
944 int j;
946 entry = Fcons (entry, Qnil);
947 if (!NILP (prefix))
948 entry = Fcons (prefix, entry);
949 for (j = submenu_depth - 1; j >= 0; j--)
950 if (!NILP (subprefix_stack[j]))
951 entry = Fcons (subprefix_stack[j], entry);
953 return entry;
955 i += MENU_ITEMS_ITEM_LENGTH;
959 else if (!for_click)
960 /* Make "Cancel" equivalent to C-g. */
961 Fsignal (Qquit, Qnil);
963 return Qnil;
967 #ifdef HAVE_DIALOGS
968 /* TODO: On Windows, there are two ways of defining a dialog.
970 1. Create a predefined dialog resource and include it in nt/emacs.rc.
971 Using this method, we could then set the titles and make unneeded
972 buttons invisible before displaying the dialog. Everything would
973 be a fixed size though, so there is a risk that text does not
974 fit on a button.
975 2. Create the dialog template in memory on the fly. This allows us
976 to size the dialog and buttons dynamically, probably giving more
977 natural looking results for dialogs with few buttons, and eliminating
978 the problem of text overflowing the buttons. But the API for this is
979 quite complex - structures have to be allocated in particular ways,
980 text content is tacked onto the end of structures in variable length
981 arrays with further structures tacked on after these, there are
982 certain alignment requirements for all this, and we have to
983 measure all the text and convert to "dialog coordinates" to figure
984 out how big to make everything.
986 For now, we'll just stick with menus for dialogs that are more
987 complicated than simple yes/no type questions for which we can use
988 the MessageBox function.
991 static char * button_names [] = {
992 "button1", "button2", "button3", "button4", "button5",
993 "button6", "button7", "button8", "button9", "button10" };
995 static Lisp_Object
996 w32_dialog_show (FRAME_PTR f, int keymaps,
997 Lisp_Object title, Lisp_Object header,
998 char **error)
1000 int i, nb_buttons = 0;
1001 char dialog_name[6];
1002 int menu_item_selection;
1004 widget_value *wv, *first_wv = 0, *prev_wv = 0;
1006 /* Number of elements seen so far, before boundary. */
1007 int left_count = 0;
1008 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
1009 int boundary_seen = 0;
1011 *error = NULL;
1013 if (menu_items_n_panes > 1)
1015 *error = "Multiple panes in dialog box";
1016 return Qnil;
1019 /* Create a tree of widget_value objects
1020 representing the text label and buttons. */
1022 Lisp_Object pane_name, prefix;
1023 char *pane_string;
1024 pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
1025 prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX);
1026 pane_string = (NILP (pane_name)
1027 ? "" : (char *) SDATA (pane_name));
1028 prev_wv = xmalloc_widget_value ();
1029 prev_wv->value = pane_string;
1030 if (keymaps && !NILP (prefix))
1031 prev_wv->name++;
1032 prev_wv->enabled = 1;
1033 prev_wv->name = "message";
1034 prev_wv->help = Qnil;
1035 first_wv = prev_wv;
1037 /* Loop over all panes and items, filling in the tree. */
1038 i = MENU_ITEMS_PANE_LENGTH;
1039 while (i < menu_items_used)
1042 /* Create a new item within current pane. */
1043 Lisp_Object item_name, enable, descrip, help;
1045 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
1046 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
1047 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
1048 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
1050 if (NILP (item_name))
1052 free_menubar_widget_value_tree (first_wv);
1053 *error = "Submenu in dialog items";
1054 return Qnil;
1056 if (EQ (item_name, Qquote))
1058 /* This is the boundary between left-side elts
1059 and right-side elts. Stop incrementing right_count. */
1060 boundary_seen = 1;
1061 i++;
1062 continue;
1064 if (nb_buttons >= 9)
1066 free_menubar_widget_value_tree (first_wv);
1067 *error = "Too many dialog items";
1068 return Qnil;
1071 wv = xmalloc_widget_value ();
1072 prev_wv->next = wv;
1073 wv->name = (char *) button_names[nb_buttons];
1074 if (!NILP (descrip))
1075 wv->key = (char *) SDATA (descrip);
1076 wv->value = (char *) SDATA (item_name);
1077 wv->call_data = (void *) &AREF (menu_items, i);
1078 wv->enabled = !NILP (enable);
1079 wv->help = Qnil;
1080 prev_wv = wv;
1082 if (! boundary_seen)
1083 left_count++;
1085 nb_buttons++;
1086 i += MENU_ITEMS_ITEM_LENGTH;
1089 /* If the boundary was not specified,
1090 by default put half on the left and half on the right. */
1091 if (! boundary_seen)
1092 left_count = nb_buttons - nb_buttons / 2;
1094 wv = xmalloc_widget_value ();
1095 wv->name = dialog_name;
1096 wv->help = Qnil;
1098 /* Frame title: 'Q' = Question, 'I' = Information.
1099 Can also have 'E' = Error if, one day, we want
1100 a popup for errors. */
1101 if (NILP (header))
1102 dialog_name[0] = 'Q';
1103 else
1104 dialog_name[0] = 'I';
1106 /* Dialog boxes use a really stupid name encoding
1107 which specifies how many buttons to use
1108 and how many buttons are on the right. */
1109 dialog_name[1] = '0' + nb_buttons;
1110 dialog_name[2] = 'B';
1111 dialog_name[3] = 'R';
1112 /* Number of buttons to put on the right. */
1113 dialog_name[4] = '0' + nb_buttons - left_count;
1114 dialog_name[5] = 0;
1115 wv->contents = first_wv;
1116 first_wv = wv;
1119 /* Actually create the dialog. */
1120 dialog_id = widget_id_tick++;
1121 menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
1122 f->output_data.w32->widget, 1, 0,
1123 dialog_selection_callback, 0);
1124 lw_modify_all_widgets (dialog_id, first_wv->contents, TRUE);
1126 /* Free the widget_value objects we used to specify the contents. */
1127 free_menubar_widget_value_tree (first_wv);
1129 /* No selection has been chosen yet. */
1130 menu_item_selection = 0;
1132 /* Display the menu. */
1133 lw_pop_up_all_widgets (dialog_id);
1135 /* Process events that apply to the menu. */
1136 popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id);
1138 lw_destroy_all_widgets (dialog_id);
1140 /* Find the selected item, and its pane, to return
1141 the proper value. */
1142 if (menu_item_selection != 0)
1144 Lisp_Object prefix;
1146 prefix = Qnil;
1147 i = 0;
1148 while (i < menu_items_used)
1150 Lisp_Object entry;
1152 if (EQ (AREF (menu_items, i), Qt))
1154 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
1155 i += MENU_ITEMS_PANE_LENGTH;
1157 else
1159 entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
1160 if (menu_item_selection == i)
1162 if (keymaps != 0)
1164 entry = Fcons (entry, Qnil);
1165 if (!NILP (prefix))
1166 entry = Fcons (prefix, entry);
1168 return entry;
1170 i += MENU_ITEMS_ITEM_LENGTH;
1174 else
1175 /* Make "Cancel" equivalent to C-g. */
1176 Fsignal (Qquit, Qnil);
1178 return Qnil;
1180 #else /* !HAVE_DIALOGS */
1182 /* Currently we only handle Yes No dialogs (y-or-n-p and yes-or-no-p) as
1183 simple dialogs. We could handle a few more, but I'm not aware of
1184 anywhere in Emacs that uses the other specific dialog choices that
1185 MessageBox provides. */
1187 static int
1188 is_simple_dialog (Lisp_Object contents)
1190 Lisp_Object options = XCDR (contents);
1191 Lisp_Object name, yes, no, other;
1193 yes = build_string ("Yes");
1194 no = build_string ("No");
1196 if (!CONSP (options))
1197 return 0;
1199 name = XCAR (XCAR (options));
1200 if (!CONSP (options))
1201 return 0;
1203 if (!NILP (Fstring_equal (name, yes)))
1204 other = no;
1205 else if (!NILP (Fstring_equal (name, no)))
1206 other = yes;
1207 else
1208 return 0;
1210 options = XCDR (options);
1211 if (!CONSP (options))
1212 return 0;
1214 name = XCAR (XCAR (options));
1215 if (NILP (Fstring_equal (name, other)))
1216 return 0;
1218 /* Check there are no more options. */
1219 options = XCDR (options);
1220 return !(CONSP (options));
1223 static Lisp_Object
1224 simple_dialog_show (FRAME_PTR f, Lisp_Object contents, Lisp_Object header)
1226 int answer;
1227 UINT type;
1228 Lisp_Object lispy_answer = Qnil, temp = XCAR (contents);
1230 type = MB_YESNO;
1232 /* Since we only handle Yes/No dialogs, and we already checked
1233 is_simple_dialog, we don't need to worry about checking contents
1234 to see what type of dialog to use. */
1236 /* Use unicode if possible, so any language can be displayed. */
1237 if (unicode_message_box)
1239 WCHAR *text, *title;
1241 if (STRINGP (temp))
1243 char *utf8_text = SDATA (ENCODE_UTF_8 (temp));
1244 /* Be pessimistic about the number of characters needed.
1245 Remember characters outside the BMP will take more than
1246 one utf16 word, so we cannot simply use the character
1247 length of temp. */
1248 int utf8_len = strlen (utf8_text);
1249 text = alloca ((utf8_len + 1) * sizeof (WCHAR));
1250 utf8to16 (utf8_text, utf8_len, text);
1252 else
1254 text = L"";
1257 if (NILP (header))
1259 title = L"Question";
1260 type |= MB_ICONQUESTION;
1262 else
1264 title = L"Information";
1265 type |= MB_ICONINFORMATION;
1268 answer = unicode_message_box (FRAME_W32_WINDOW (f), text, title, type);
1270 else
1272 char *text, *title;
1274 /* Fall back on ANSI message box, but at least use system
1275 encoding so questions representable by the system codepage
1276 are encoded properly. */
1277 if (STRINGP (temp))
1278 text = SDATA (ENCODE_SYSTEM (temp));
1279 else
1280 text = "";
1282 if (NILP (header))
1284 title = "Question";
1285 type |= MB_ICONQUESTION;
1287 else
1289 title = "Information";
1290 type |= MB_ICONINFORMATION;
1293 answer = MessageBox (FRAME_W32_WINDOW (f), text, title, type);
1296 if (answer == IDYES)
1297 lispy_answer = build_string ("Yes");
1298 else if (answer == IDNO)
1299 lispy_answer = build_string ("No");
1300 else
1301 Fsignal (Qquit, Qnil);
1303 for (temp = XCDR (contents); CONSP (temp); temp = XCDR (temp))
1305 Lisp_Object item, name, value;
1306 item = XCAR (temp);
1307 if (CONSP (item))
1309 name = XCAR (item);
1310 value = XCDR (item);
1312 else
1314 name = item;
1315 value = Qnil;
1318 if (!NILP (Fstring_equal (name, lispy_answer)))
1320 return value;
1323 Fsignal (Qquit, Qnil);
1324 return Qnil;
1326 #endif /* !HAVE_DIALOGS */
1329 /* Is this item a separator? */
1330 static int
1331 name_is_separator (const char *name)
1333 const char *start = name;
1335 /* Check if name string consists of only dashes ('-'). */
1336 while (*name == '-') name++;
1337 /* Separators can also be of the form "--:TripleSuperMegaEtched"
1338 or "--deep-shadow". We don't implement them yet, se we just treat
1339 them like normal separators. */
1340 return (*name == '\0' || start + 2 == name);
1343 /* UTF8: 0xxxxxxx, 110xxxxx 10xxxxxx, 1110xxxx, 10xxxxxx, 10xxxxxx */
1344 static void
1345 utf8to16 (unsigned char * src, int len, WCHAR * dest)
1347 while (len > 0)
1349 int utf16;
1350 if (*src < 0x80)
1352 *dest = (WCHAR) *src;
1353 dest++; src++; len--;
1355 /* Since we might get >3 byte sequences which we don't handle, ignore the extra parts. */
1356 else if (*src < 0xC0)
1358 src++; len--;
1360 /* 2 char UTF-8 sequence. */
1361 else if (*src < 0xE0)
1363 *dest = (WCHAR) (((*src & 0x1f) << 6)
1364 | (*(src + 1) & 0x3f));
1365 src += 2; len -= 2; dest++;
1367 else if (*src < 0xF0)
1369 *dest = (WCHAR) (((*src & 0x0f) << 12)
1370 | ((*(src + 1) & 0x3f) << 6)
1371 | (*(src + 2) & 0x3f));
1372 src += 3; len -= 3; dest++;
1374 else /* Not encodable. Insert Unicode Substitution char. */
1376 *dest = (WCHAR) 0xfffd;
1377 src++; len--; dest++;
1380 *dest = 0;
1383 static int
1384 add_menu_item (HMENU menu, widget_value *wv, HMENU item)
1386 UINT fuFlags;
1387 char *out_string, *p, *q;
1388 int return_value;
1389 size_t nlen, orig_len;
1391 if (name_is_separator (wv->name))
1393 fuFlags = MF_SEPARATOR;
1394 out_string = NULL;
1396 else
1398 if (wv->enabled)
1399 fuFlags = MF_STRING;
1400 else
1401 fuFlags = MF_STRING | MF_GRAYED;
1403 if (wv->key != NULL)
1405 out_string = alloca (strlen (wv->name) + strlen (wv->key) + 2);
1406 strcpy (out_string, wv->name);
1407 strcat (out_string, "\t");
1408 strcat (out_string, wv->key);
1410 else
1411 out_string = (char *)wv->name;
1413 /* Quote any special characters within the menu item's text and
1414 key binding. */
1415 nlen = orig_len = strlen (out_string);
1416 if (unicode_append_menu)
1418 /* With UTF-8, & cannot be part of a multibyte character. */
1419 for (p = out_string; *p; p++)
1421 if (*p == '&')
1422 nlen++;
1425 else
1427 /* If encoded with the system codepage, use multibyte string
1428 functions in case of multibyte characters that contain '&'. */
1429 for (p = out_string; *p; p = _mbsinc (p))
1431 if (_mbsnextc (p) == '&')
1432 nlen++;
1436 if (nlen > orig_len)
1438 p = out_string;
1439 out_string = alloca (nlen + 1);
1440 q = out_string;
1441 while (*p)
1443 if (unicode_append_menu)
1445 if (*p == '&')
1446 *q++ = *p;
1447 *q++ = *p++;
1449 else
1451 if (_mbsnextc (p) == '&')
1453 _mbsncpy (q, p, 1);
1454 q = _mbsinc (q);
1456 _mbsncpy (q, p, 1);
1457 p = _mbsinc (p);
1458 q = _mbsinc (q);
1461 *q = '\0';
1464 if (item != NULL)
1465 fuFlags = MF_POPUP;
1466 else if (wv->title || wv->call_data == 0)
1468 /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since
1469 we can't deallocate the memory otherwise. */
1470 if (get_menu_item_info)
1472 out_string = (char *) local_alloc (strlen (wv->name) + 1);
1473 strcpy (out_string, wv->name);
1474 #ifdef MENU_DEBUG
1475 DebPrint ("Menu: allocing %ld for owner-draw", out_string);
1476 #endif
1477 fuFlags = MF_OWNERDRAW | MF_DISABLED;
1479 else
1480 fuFlags = MF_DISABLED;
1483 /* Draw radio buttons and tickboxes. */
1484 else if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE ||
1485 wv->button_type == BUTTON_TYPE_RADIO))
1486 fuFlags |= MF_CHECKED;
1487 else
1488 fuFlags |= MF_UNCHECKED;
1491 if (unicode_append_menu && out_string)
1493 /* Convert out_string from UTF-8 to UTF-16-LE. */
1494 int utf8_len = strlen (out_string);
1495 WCHAR * utf16_string;
1496 if (fuFlags & MF_OWNERDRAW)
1497 utf16_string = local_alloc ((utf8_len + 1) * sizeof (WCHAR));
1498 else
1499 utf16_string = alloca ((utf8_len + 1) * sizeof (WCHAR));
1501 utf8to16 (out_string, utf8_len, utf16_string);
1502 return_value = unicode_append_menu (menu, fuFlags,
1503 item != NULL ? (UINT) item
1504 : (UINT) wv->call_data,
1505 utf16_string);
1506 if (!return_value)
1508 /* On W9x/ME, unicode menus are not supported, though AppendMenuW
1509 apparently does exist at least in some cases and appears to be
1510 stubbed out to do nothing. out_string is UTF-8, but since
1511 our standard menus are in English and this is only going to
1512 happen the first time a menu is used, the encoding is
1513 of minor importance compared with menus not working at all. */
1514 return_value =
1515 AppendMenu (menu, fuFlags,
1516 item != NULL ? (UINT) item: (UINT) wv->call_data,
1517 out_string);
1518 /* Don't use unicode menus in future. */
1519 unicode_append_menu = NULL;
1522 if (unicode_append_menu && (fuFlags & MF_OWNERDRAW))
1523 local_free (out_string);
1525 else
1527 return_value =
1528 AppendMenu (menu,
1529 fuFlags,
1530 item != NULL ? (UINT) item : (UINT) wv->call_data,
1531 out_string );
1534 /* This must be done after the menu item is created. */
1535 if (!wv->title && wv->call_data != 0)
1537 if (set_menu_item_info)
1539 MENUITEMINFO info;
1540 memset (&info, 0, sizeof (info));
1541 info.cbSize = sizeof (info);
1542 info.fMask = MIIM_DATA;
1544 /* Set help string for menu item. Leave it as a Lisp_Object
1545 until it is ready to be displayed, since GC can happen while
1546 menus are active. */
1547 if (!NILP (wv->help))
1548 #ifdef USE_LISP_UNION_TYPE
1549 info.dwItemData = (DWORD) (wv->help).i;
1550 #else
1551 info.dwItemData = (DWORD) (wv->help);
1552 #endif
1553 if (wv->button_type == BUTTON_TYPE_RADIO)
1555 /* CheckMenuRadioItem allows us to differentiate TOGGLE and
1556 RADIO items, but is not available on NT 3.51 and earlier. */
1557 info.fMask |= MIIM_TYPE | MIIM_STATE;
1558 info.fType = MFT_RADIOCHECK | MFT_STRING;
1559 info.dwTypeData = out_string;
1560 info.fState = wv->selected ? MFS_CHECKED : MFS_UNCHECKED;
1563 set_menu_item_info (menu,
1564 item != NULL ? (UINT) item : (UINT) wv->call_data,
1565 FALSE, &info);
1568 return return_value;
1571 /* Construct native Windows menu(bar) based on widget_value tree. */
1572 static int
1573 fill_in_menu (HMENU menu, widget_value *wv)
1575 int items_added = 0;
1577 for ( ; wv != NULL; wv = wv->next)
1579 if (wv->contents)
1581 HMENU sub_menu = CreatePopupMenu ();
1583 if (sub_menu == NULL)
1584 return 0;
1586 if (!fill_in_menu (sub_menu, wv->contents) ||
1587 !add_menu_item (menu, wv, sub_menu))
1589 DestroyMenu (sub_menu);
1590 return 0;
1593 else
1595 if (!add_menu_item (menu, wv, NULL))
1596 return 0;
1599 return 1;
1602 /* Display help string for currently pointed to menu item. Not
1603 supported on NT 3.51 and earlier, as GetMenuItemInfo is not
1604 available. */
1605 void
1606 w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags)
1608 if (get_menu_item_info)
1610 struct frame *f = x_window_to_frame (&one_w32_display_info, owner);
1611 Lisp_Object frame, help;
1613 /* No help echo on owner-draw menu items, or when the keyboard is used
1614 to navigate the menus, since tooltips are distracting if they pop
1615 up elsewhere. */
1616 if (flags & MF_OWNERDRAW || flags & MF_POPUP
1617 || !(flags & MF_MOUSESELECT))
1618 help = Qnil;
1619 else
1621 MENUITEMINFO info;
1623 memset (&info, 0, sizeof (info));
1624 info.cbSize = sizeof (info);
1625 info.fMask = MIIM_DATA;
1626 get_menu_item_info (menu, item, FALSE, &info);
1628 #ifdef USE_LISP_UNION_TYPE
1629 help = info.dwItemData ? (Lisp_Object) ((EMACS_INT) info.dwItemData)
1630 : Qnil;
1631 #else
1632 help = info.dwItemData ? (Lisp_Object) info.dwItemData : Qnil;
1633 #endif
1636 /* Store the help echo in the keyboard buffer as the X toolkit
1637 version does, rather than directly showing it. This seems to
1638 solve the GC problems that were present when we based the
1639 Windows code on the non-toolkit version. */
1640 if (f)
1642 XSETFRAME (frame, f);
1643 kbd_buffer_store_help_event (frame, help);
1645 else
1646 /* X version has a loop through frames here, which doesn't
1647 appear to do anything, unless it has some side effect. */
1648 show_help_echo (help, Qnil, Qnil, Qnil, 1);
1652 /* Free memory used by owner-drawn strings. */
1653 static void
1654 w32_free_submenu_strings (HMENU menu)
1656 int i, num = GetMenuItemCount (menu);
1657 for (i = 0; i < num; i++)
1659 MENUITEMINFO info;
1660 memset (&info, 0, sizeof (info));
1661 info.cbSize = sizeof (info);
1662 info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_SUBMENU;
1664 get_menu_item_info (menu, i, TRUE, &info);
1666 /* Owner-drawn names are held in dwItemData. */
1667 if ((info.fType & MF_OWNERDRAW) && info.dwItemData)
1669 #ifdef MENU_DEBUG
1670 DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData);
1671 #endif
1672 local_free (info.dwItemData);
1675 /* Recurse down submenus. */
1676 if (info.hSubMenu)
1677 w32_free_submenu_strings (info.hSubMenu);
1681 void
1682 w32_free_menu_strings (HWND hwnd)
1684 HMENU menu = current_popup_menu;
1686 if (get_menu_item_info)
1688 /* If there is no popup menu active, free the strings from the frame's
1689 menubar. */
1690 if (!menu)
1691 menu = GetMenu (hwnd);
1693 if (menu)
1694 w32_free_submenu_strings (menu);
1697 current_popup_menu = NULL;
1700 #endif /* HAVE_MENUS */
1702 /* The following is used by delayed window autoselection. */
1704 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
1705 doc: /* Return t if a menu or popup dialog is active on selected frame. */)
1706 (void)
1708 #ifdef HAVE_MENUS
1709 FRAME_PTR f;
1710 f = SELECTED_FRAME ();
1711 return (f->output_data.w32->menubar_active > 0) ? Qt : Qnil;
1712 #else
1713 return Qnil;
1714 #endif /* HAVE_MENUS */
1717 void
1718 syms_of_w32menu (void)
1720 globals_of_w32menu ();
1722 current_popup_menu = NULL;
1724 DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
1726 defsubr (&Smenu_or_popup_active_p);
1727 #ifdef HAVE_MENUS
1728 defsubr (&Sx_popup_dialog);
1729 #endif
1733 globals_of_w32menu is used to initialize those global variables that
1734 must always be initialized on startup even when the global variable
1735 initialized is non zero (see the function main in emacs.c).
1736 globals_of_w32menu is called from syms_of_w32menu when the global
1737 variable initialized is 0 and directly from main when initialized
1738 is non zero.
1740 void
1741 globals_of_w32menu (void)
1743 /* See if Get/SetMenuItemInfo functions are available. */
1744 HMODULE user32 = GetModuleHandle ("user32.dll");
1745 get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA");
1746 set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA");
1747 unicode_append_menu = (AppendMenuW_Proc) GetProcAddress (user32, "AppendMenuW");
1748 unicode_message_box = (MessageBoxW_Proc) GetProcAddress (user32, "MessageBoxW");
1751 /* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0
1752 (do not change this comment) */