]> code.delx.au - gnu-emacs/blob - src/w32menu.c
Merge from emacs-23
[gnu-emacs] / src / w32menu.c
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, 2011
4 Free Software Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
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.
12
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.
17
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/>. */
20
21 #include <config.h>
22
23 #include <signal.h>
24 #include <stdio.h>
25 #include <mbstring.h>
26 #include <setjmp.h>
27
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"
40
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"
44
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
50
51 #include "dispextern.h"
52
53 #undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
54
55 #ifndef TRUE
56 #define TRUE 1
57 #define FALSE 0
58 #endif /* no TRUE */
59
60 HMENU current_popup_menu;
61
62 void syms_of_w32menu (void);
63 void globals_of_w32menu (void);
64
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);
80
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;
85
86 Lisp_Object Qdebug_on_next_call;
87
88 extern Lisp_Object Qmenu_bar;
89
90 extern Lisp_Object QCtoggle, QCradio;
91
92 extern Lisp_Object Voverriding_local_map;
93 extern Lisp_Object Voverriding_local_map_menu_flag;
94
95 extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
96
97 extern Lisp_Object Qmenu_bar_update_hook;
98
99 void set_frame_menubar (FRAME_PTR, int, int);
100
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
107
108 static void utf8to16 (unsigned char *, int, WCHAR *);
109 static int fill_in_menu (HMENU, widget_value *);
110
111 void w32_free_menu_strings (HWND);
112 \f
113
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.
117
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>. */
120
121 int pending_menu_activation;
122 \f
123 #ifdef HAVE_MENUS
124
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.
131
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.
136
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.)
141
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)
145 {
146 FRAME_PTR f = NULL;
147 Lisp_Object window;
148
149 check_w32 ();
150
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))))
155 {
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;
163
164 (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
165
166 if (new_f != 0)
167 XSETFRAME (window, new_f);
168 else
169 window = selected_window;
170 #endif
171 window = selected_window;
172 }
173 else if (CONSP (position))
174 {
175 Lisp_Object tem;
176 tem = Fcar (position);
177 if (CONSP (tem))
178 window = Fcar (Fcdr (position));
179 else
180 {
181 tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
182 window = Fcar (tem); /* POSN_WINDOW (tem) */
183 }
184 }
185 else if (WINDOWP (position) || FRAMEP (position))
186 window = position;
187 else
188 window = Qnil;
189
190 /* Decode where to put the menu. */
191
192 if (FRAMEP (window))
193 f = XFRAME (window);
194 else if (WINDOWP (window))
195 {
196 CHECK_LIVE_WINDOW (window);
197 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
198 }
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);
203
204 #ifndef HAVE_DIALOGS
205
206 {
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
211 {
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)));
221 }
222 }
223 #else /* HAVE_DIALOGS */
224 {
225 Lisp_Object title;
226 char *error_name;
227 Lisp_Object selection;
228
229 /* Decode the dialog items from what was specified. */
230 title = Fcar (contents);
231 CHECK_STRING (title);
232
233 list_of_panes (Fcons (contents, Qnil));
234
235 /* Display them in a dialog box. */
236 BLOCK_INPUT;
237 selection = w32_dialog_show (f, 0, title, header, &error_name);
238 UNBLOCK_INPUT;
239
240 discard_menu_items ();
241 FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
242
243 if (error_name) error (error_name);
244 return selection;
245 }
246 #endif /* HAVE_DIALOGS */
247 }
248
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.
252
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.
256
257 But first we recompute the menu bar contents (the whole tree).
258
259 This way we can safely execute Lisp code. */
260
261 void
262 x_activate_menubar (FRAME_PTR f)
263 {
264 set_frame_menubar (f, 0, 1);
265
266 /* Lock out further menubar changes while active. */
267 f->output_data.w32->menubar_active = 1;
268
269 /* Signal input thread to return from WM_INITMENU. */
270 complete_deferred_msg (FRAME_W32_WINDOW (f), WM_INITMENU, 0);
271 }
272
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. */
277
278 void
279 menubar_selection_callback (FRAME_PTR f, void * client_data)
280 {
281 Lisp_Object prefix, entry;
282 Lisp_Object vector;
283 Lisp_Object *subprefix_stack;
284 int submenu_depth = 0;
285 int i;
286
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)
295 {
296 if (EQ (AREF (vector, i), Qnil))
297 {
298 subprefix_stack[submenu_depth++] = prefix;
299 prefix = entry;
300 i++;
301 }
302 else if (EQ (AREF (vector, i), Qlambda))
303 {
304 prefix = subprefix_stack[--submenu_depth];
305 i++;
306 }
307 else if (EQ (AREF (vector, i), Qt))
308 {
309 prefix = AREF (vector, i + MENU_ITEMS_PANE_PREFIX);
310 i += MENU_ITEMS_PANE_LENGTH;
311 }
312 else
313 {
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)
318 {
319 int j;
320 struct input_event buf;
321 Lisp_Object frame;
322 EVENT_INIT (buf);
323
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);
329
330 for (j = 0; j < submenu_depth; j++)
331 if (!NILP (subprefix_stack[j]))
332 {
333 buf.kind = MENU_BAR_EVENT;
334 buf.frame_or_window = frame;
335 buf.arg = subprefix_stack[j];
336 kbd_buffer_store_event (&buf);
337 }
338
339 if (!NILP (prefix))
340 {
341 buf.kind = MENU_BAR_EVENT;
342 buf.frame_or_window = frame;
343 buf.arg = prefix;
344 kbd_buffer_store_event (&buf);
345 }
346
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);
353
354 f->output_data.w32->menubar_active = 0;
355 return;
356 }
357 i += MENU_ITEMS_ITEM_LENGTH;
358 }
359 }
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;
363 }
364
365 \f
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. */
369
370 void
371 set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
372 {
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;
379
380 /* We must not change the menubar when actually in use. */
381 if (f->output_data.w32->menubar_active)
382 return;
383
384 XSETFRAME (Vmenu_updating_frame, f);
385
386 if (! menubar_widget)
387 deep_p = 1;
388 else if (pending_menu_activation && !deep_p)
389 deep_p = 1;
390
391 if (deep_p)
392 {
393 /* Make a widget-value tree representing the entire menu trees. */
394
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));
402
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;
407
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);
413
414 record_unwind_save_match_data ();
415
416 if (NILP (Voverriding_local_map_menu_flag))
417 {
418 specbind (Qoverriding_terminal_local_map, Qnil);
419 specbind (Qoverriding_local_map, Qnil);
420 }
421
422 set_buffer_internal_1 (XBUFFER (buffer));
423
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));
428
429 items = FRAME_MENU_BAR_ITEMS (f);
430
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));
435
436 /* Fill in menu_items with the current menu bar contents.
437 This can evaluate Lisp code. */
438 save_menu_items ();
439
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)
449 {
450 Lisp_Object key, string, maps;
451
452 last_i = i;
453
454 key = AREF (items, i);
455 string = AREF (items, i + 1);
456 maps = AREF (items, i + 2);
457 if (NILP (string))
458 break;
459
460 submenu_start[i] = menu_items_used;
461
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;
466
467 submenu_end[i] = menu_items_used;
468 }
469
470 finish_menu_items ();
471
472 /* Convert menu_items into widget_value trees
473 to display the menu. This cannot evaluate Lisp code. */
474
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;
482
483 for (i = 0; i < last_i; i += 4)
484 {
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;
496 }
497
498 set_buffer_internal_1 (prev);
499
500 /* If there has been no change in the Lisp-level contents
501 of the menu bar, skip redisplaying it. Just exit. */
502
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)
508 {
509 free_menubar_widget_value_tree (first_wv);
510 discard_menu_items ();
511 unbind_to (specpdl_count, Qnil);
512 return;
513 }
514
515 f->menu_bar_vector = menu_items;
516 f->menu_bar_items_used = menu_items_used;
517
518 /* This undoes save_menu_items. */
519 unbind_to (specpdl_count, Qnil);
520
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)
528 {
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;
536 }
537 }
538 else
539 {
540 /* Make a widget-value tree containing
541 just the top level menu bar strings. */
542
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;
550
551 items = FRAME_MENU_BAR_ITEMS (f);
552 for (i = 0; i < ASIZE (items); i += 4)
553 {
554 Lisp_Object string;
555
556 string = AREF (items, i + 1);
557 if (NILP (string))
558 break;
559
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);
571
572 if (prev_wv)
573 prev_wv->next = wv;
574 else
575 first_wv->contents = wv;
576 prev_wv = wv;
577 }
578
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;
583 }
584
585 /* Create or update the menu bar widget. */
586
587 BLOCK_INPUT;
588
589 if (menubar_widget)
590 {
591 /* Empty current menubar, rather than creating a fresh one. */
592 while (DeleteMenu (menubar_widget, 0, MF_BYPOSITION))
593 ;
594 }
595 else
596 {
597 menubar_widget = CreateMenu ();
598 }
599 fill_in_menu (menubar_widget, first_wv->contents);
600
601 free_menubar_widget_value_tree (first_wv);
602
603 {
604 HMENU old_widget = f->output_data.w32->menubar_widget;
605
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)); */
610
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));
615 }
616
617 UNBLOCK_INPUT;
618 }
619
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. */
624
625 void
626 initialize_frame_menubar (FRAME_PTR f)
627 {
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);
632 }
633
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. */
636
637 void
638 free_frame_menubar (FRAME_PTR f)
639 {
640 BLOCK_INPUT;
641
642 {
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);
647 }
648
649 UNBLOCK_INPUT;
650 }
651
652 \f
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. */
656
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.) */
667
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)
671 {
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;
683
684 *error = NULL;
685
686 if (menu_items_n_panes == 0)
687 return Qnil;
688
689 if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
690 {
691 *error = "Empty menu";
692 return Qnil;
693 }
694
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;
705
706 /* Loop over all panes and items, filling in the tree. */
707 i = 0;
708 while (i < menu_items_used)
709 {
710 if (EQ (AREF (menu_items, i), Qnil))
711 {
712 submenu_stack[submenu_depth++] = save_wv;
713 save_wv = prev_wv;
714 prev_wv = 0;
715 first_pane = 1;
716 i++;
717 }
718 else if (EQ (AREF (menu_items, i), Qlambda))
719 {
720 prev_wv = save_wv;
721 save_wv = submenu_stack[--submenu_depth];
722 first_pane = 0;
723 i++;
724 }
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))
733 {
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);
739
740 if (STRINGP (pane_name))
741 {
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);
746
747 ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
748 }
749
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 = "";
756
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, ""))
761 {
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;
776 }
777 else if (first_pane)
778 {
779 save_wv = wv;
780 prev_wv = 0;
781 }
782 first_pane = 0;
783 i += MENU_ITEMS_PANE_LENGTH;
784 }
785 else
786 {
787 /* Create a new item within current pane. */
788 Lisp_Object item_name, enable, descrip, def, type, selected, help;
789
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);
797
798 if (STRINGP (item_name))
799 {
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);
804
805 ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
806 }
807
808 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
809 {
810 descrip = ENCODE_SYSTEM (descrip);
811 ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
812 }
813
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);
827
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 ();
836
837 wv->selected = !NILP (selected);
838
839 if (!STRINGP (help))
840 help = Qnil;
841
842 wv->help = help;
843
844 prev_wv = wv;
845
846 i += MENU_ITEMS_ITEM_LENGTH;
847 }
848 }
849
850 /* Deal with the title, if it is non-nil. */
851 if (!NILP (title))
852 {
853 widget_value *wv_title = xmalloc_widget_value ();
854 widget_value *wv_sep = xmalloc_widget_value ();
855
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;
861
862 if (unicode_append_menu)
863 title = ENCODE_UTF_8 (title);
864 else if (STRING_MULTIBYTE (title))
865 title = ENCODE_SYSTEM (title);
866
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;
874 }
875
876 /* No selection has been chosen yet. */
877 menu_item_selection = 0;
878
879 /* Actually create the menu. */
880 current_popup_menu = menu = CreatePopupMenu ();
881 fill_in_menu (menu, first_wv->contents);
882
883 /* Adjust coordinates to be root-window-relative. */
884 pos.x = x;
885 pos.y = y;
886 ClientToScreen (FRAME_W32_WINDOW (f), &pos);
887
888 /* Display the menu. */
889 menu_item_selection = SendMessage (FRAME_W32_WINDOW (f),
890 WM_EMACS_TRACKPOPUPMENU,
891 (WPARAM)menu, (LPARAM)&pos);
892
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;
897
898 /* Free the widget_value objects we used to specify the contents. */
899 free_menubar_widget_value_tree (first_wv);
900
901 DestroyMenu (menu);
902
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;
906
907 /* Find the selected item, and its pane, to return
908 the proper value. */
909 if (menu_item_selection != 0)
910 {
911 Lisp_Object prefix, entry;
912
913 prefix = entry = Qnil;
914 i = 0;
915 while (i < menu_items_used)
916 {
917 if (EQ (AREF (menu_items, i), Qnil))
918 {
919 subprefix_stack[submenu_depth++] = prefix;
920 prefix = entry;
921 i++;
922 }
923 else if (EQ (AREF (menu_items, i), Qlambda))
924 {
925 prefix = subprefix_stack[--submenu_depth];
926 i++;
927 }
928 else if (EQ (AREF (menu_items, i), Qt))
929 {
930 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
931 i += MENU_ITEMS_PANE_LENGTH;
932 }
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
938 {
939 entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
940 if (menu_item_selection == i)
941 {
942 if (keymaps != 0)
943 {
944 int j;
945
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);
952 }
953 return entry;
954 }
955 i += MENU_ITEMS_ITEM_LENGTH;
956 }
957 }
958 }
959 else if (!for_click)
960 /* Make "Cancel" equivalent to C-g. */
961 Fsignal (Qquit, Qnil);
962
963 return Qnil;
964 }
965 \f
966
967 #ifdef HAVE_DIALOGS
968 /* TODO: On Windows, there are two ways of defining a dialog.
969
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.
985
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.
989 */
990
991 static char * button_names [] = {
992 "button1", "button2", "button3", "button4", "button5",
993 "button6", "button7", "button8", "button9", "button10" };
994
995 static Lisp_Object
996 w32_dialog_show (FRAME_PTR f, int keymaps,
997 Lisp_Object title, Lisp_Object header,
998 char **error)
999 {
1000 int i, nb_buttons = 0;
1001 char dialog_name[6];
1002 int menu_item_selection;
1003
1004 widget_value *wv, *first_wv = 0, *prev_wv = 0;
1005
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;
1010
1011 *error = NULL;
1012
1013 if (menu_items_n_panes > 1)
1014 {
1015 *error = "Multiple panes in dialog box";
1016 return Qnil;
1017 }
1018
1019 /* Create a tree of widget_value objects
1020 representing the text label and buttons. */
1021 {
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;
1036
1037 /* Loop over all panes and items, filling in the tree. */
1038 i = MENU_ITEMS_PANE_LENGTH;
1039 while (i < menu_items_used)
1040 {
1041
1042 /* Create a new item within current pane. */
1043 Lisp_Object item_name, enable, descrip, help;
1044
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);
1049
1050 if (NILP (item_name))
1051 {
1052 free_menubar_widget_value_tree (first_wv);
1053 *error = "Submenu in dialog items";
1054 return Qnil;
1055 }
1056 if (EQ (item_name, Qquote))
1057 {
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;
1063 }
1064 if (nb_buttons >= 9)
1065 {
1066 free_menubar_widget_value_tree (first_wv);
1067 *error = "Too many dialog items";
1068 return Qnil;
1069 }
1070
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;
1081
1082 if (! boundary_seen)
1083 left_count++;
1084
1085 nb_buttons++;
1086 i += MENU_ITEMS_ITEM_LENGTH;
1087 }
1088
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;
1093
1094 wv = xmalloc_widget_value ();
1095 wv->name = dialog_name;
1096 wv->help = Qnil;
1097
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';
1105
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;
1117 }
1118
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);
1125
1126 /* Free the widget_value objects we used to specify the contents. */
1127 free_menubar_widget_value_tree (first_wv);
1128
1129 /* No selection has been chosen yet. */
1130 menu_item_selection = 0;
1131
1132 /* Display the menu. */
1133 lw_pop_up_all_widgets (dialog_id);
1134
1135 /* Process events that apply to the menu. */
1136 popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id);
1137
1138 lw_destroy_all_widgets (dialog_id);
1139
1140 /* Find the selected item, and its pane, to return
1141 the proper value. */
1142 if (menu_item_selection != 0)
1143 {
1144 Lisp_Object prefix;
1145
1146 prefix = Qnil;
1147 i = 0;
1148 while (i < menu_items_used)
1149 {
1150 Lisp_Object entry;
1151
1152 if (EQ (AREF (menu_items, i), Qt))
1153 {
1154 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
1155 i += MENU_ITEMS_PANE_LENGTH;
1156 }
1157 else
1158 {
1159 entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
1160 if (menu_item_selection == i)
1161 {
1162 if (keymaps != 0)
1163 {
1164 entry = Fcons (entry, Qnil);
1165 if (!NILP (prefix))
1166 entry = Fcons (prefix, entry);
1167 }
1168 return entry;
1169 }
1170 i += MENU_ITEMS_ITEM_LENGTH;
1171 }
1172 }
1173 }
1174 else
1175 /* Make "Cancel" equivalent to C-g. */
1176 Fsignal (Qquit, Qnil);
1177
1178 return Qnil;
1179 }
1180 #else /* !HAVE_DIALOGS */
1181
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. */
1186
1187 static int
1188 is_simple_dialog (Lisp_Object contents)
1189 {
1190 Lisp_Object options = XCDR (contents);
1191 Lisp_Object name, yes, no, other;
1192
1193 yes = build_string ("Yes");
1194 no = build_string ("No");
1195
1196 if (!CONSP (options))
1197 return 0;
1198
1199 name = XCAR (XCAR (options));
1200 if (!CONSP (options))
1201 return 0;
1202
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;
1209
1210 options = XCDR (options);
1211 if (!CONSP (options))
1212 return 0;
1213
1214 name = XCAR (XCAR (options));
1215 if (NILP (Fstring_equal (name, other)))
1216 return 0;
1217
1218 /* Check there are no more options. */
1219 options = XCDR (options);
1220 return !(CONSP (options));
1221 }
1222
1223 static Lisp_Object
1224 simple_dialog_show (FRAME_PTR f, Lisp_Object contents, Lisp_Object header)
1225 {
1226 int answer;
1227 UINT type;
1228 Lisp_Object lispy_answer = Qnil, temp = XCAR (contents);
1229
1230 type = MB_YESNO;
1231
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. */
1235
1236 /* Use unicode if possible, so any language can be displayed. */
1237 if (unicode_message_box)
1238 {
1239 WCHAR *text, *title;
1240
1241 if (STRINGP (temp))
1242 {
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);
1251 }
1252 else
1253 {
1254 text = L"";
1255 }
1256
1257 if (NILP (header))
1258 {
1259 title = L"Question";
1260 type |= MB_ICONQUESTION;
1261 }
1262 else
1263 {
1264 title = L"Information";
1265 type |= MB_ICONINFORMATION;
1266 }
1267
1268 answer = unicode_message_box (FRAME_W32_WINDOW (f), text, title, type);
1269 }
1270 else
1271 {
1272 char *text, *title;
1273
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 = "";
1281
1282 if (NILP (header))
1283 {
1284 title = "Question";
1285 type |= MB_ICONQUESTION;
1286 }
1287 else
1288 {
1289 title = "Information";
1290 type |= MB_ICONINFORMATION;
1291 }
1292
1293 answer = MessageBox (FRAME_W32_WINDOW (f), text, title, type);
1294 }
1295
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);
1302
1303 for (temp = XCDR (contents); CONSP (temp); temp = XCDR (temp))
1304 {
1305 Lisp_Object item, name, value;
1306 item = XCAR (temp);
1307 if (CONSP (item))
1308 {
1309 name = XCAR (item);
1310 value = XCDR (item);
1311 }
1312 else
1313 {
1314 name = item;
1315 value = Qnil;
1316 }
1317
1318 if (!NILP (Fstring_equal (name, lispy_answer)))
1319 {
1320 return value;
1321 }
1322 }
1323 Fsignal (Qquit, Qnil);
1324 return Qnil;
1325 }
1326 #endif /* !HAVE_DIALOGS */
1327 \f
1328
1329 /* UTF8: 0xxxxxxx, 110xxxxx 10xxxxxx, 1110xxxx, 10xxxxxx, 10xxxxxx */
1330 static void
1331 utf8to16 (unsigned char * src, int len, WCHAR * dest)
1332 {
1333 while (len > 0)
1334 {
1335 int utf16;
1336 if (*src < 0x80)
1337 {
1338 *dest = (WCHAR) *src;
1339 dest++; src++; len--;
1340 }
1341 /* Since we might get >3 byte sequences which we don't handle, ignore the extra parts. */
1342 else if (*src < 0xC0)
1343 {
1344 src++; len--;
1345 }
1346 /* 2 char UTF-8 sequence. */
1347 else if (*src < 0xE0)
1348 {
1349 *dest = (WCHAR) (((*src & 0x1f) << 6)
1350 | (*(src + 1) & 0x3f));
1351 src += 2; len -= 2; dest++;
1352 }
1353 else if (*src < 0xF0)
1354 {
1355 *dest = (WCHAR) (((*src & 0x0f) << 12)
1356 | ((*(src + 1) & 0x3f) << 6)
1357 | (*(src + 2) & 0x3f));
1358 src += 3; len -= 3; dest++;
1359 }
1360 else /* Not encodable. Insert Unicode Substitution char. */
1361 {
1362 *dest = (WCHAR) 0xfffd;
1363 src++; len--; dest++;
1364 }
1365 }
1366 *dest = 0;
1367 }
1368
1369 static int
1370 add_menu_item (HMENU menu, widget_value *wv, HMENU item)
1371 {
1372 UINT fuFlags;
1373 char *out_string, *p, *q;
1374 int return_value;
1375 size_t nlen, orig_len;
1376
1377 if (menu_separator_name_p (wv->name))
1378 {
1379 fuFlags = MF_SEPARATOR;
1380 out_string = NULL;
1381 }
1382 else
1383 {
1384 if (wv->enabled)
1385 fuFlags = MF_STRING;
1386 else
1387 fuFlags = MF_STRING | MF_GRAYED;
1388
1389 if (wv->key != NULL)
1390 {
1391 out_string = alloca (strlen (wv->name) + strlen (wv->key) + 2);
1392 strcpy (out_string, wv->name);
1393 strcat (out_string, "\t");
1394 strcat (out_string, wv->key);
1395 }
1396 else
1397 out_string = (char *)wv->name;
1398
1399 /* Quote any special characters within the menu item's text and
1400 key binding. */
1401 nlen = orig_len = strlen (out_string);
1402 if (unicode_append_menu)
1403 {
1404 /* With UTF-8, & cannot be part of a multibyte character. */
1405 for (p = out_string; *p; p++)
1406 {
1407 if (*p == '&')
1408 nlen++;
1409 }
1410 }
1411 else
1412 {
1413 /* If encoded with the system codepage, use multibyte string
1414 functions in case of multibyte characters that contain '&'. */
1415 for (p = out_string; *p; p = _mbsinc (p))
1416 {
1417 if (_mbsnextc (p) == '&')
1418 nlen++;
1419 }
1420 }
1421
1422 if (nlen > orig_len)
1423 {
1424 p = out_string;
1425 out_string = alloca (nlen + 1);
1426 q = out_string;
1427 while (*p)
1428 {
1429 if (unicode_append_menu)
1430 {
1431 if (*p == '&')
1432 *q++ = *p;
1433 *q++ = *p++;
1434 }
1435 else
1436 {
1437 if (_mbsnextc (p) == '&')
1438 {
1439 _mbsncpy (q, p, 1);
1440 q = _mbsinc (q);
1441 }
1442 _mbsncpy (q, p, 1);
1443 p = _mbsinc (p);
1444 q = _mbsinc (q);
1445 }
1446 }
1447 *q = '\0';
1448 }
1449
1450 if (item != NULL)
1451 fuFlags = MF_POPUP;
1452 else if (wv->title || wv->call_data == 0)
1453 {
1454 /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since
1455 we can't deallocate the memory otherwise. */
1456 if (get_menu_item_info)
1457 {
1458 out_string = (char *) local_alloc (strlen (wv->name) + 1);
1459 strcpy (out_string, wv->name);
1460 #ifdef MENU_DEBUG
1461 DebPrint ("Menu: allocing %ld for owner-draw", out_string);
1462 #endif
1463 fuFlags = MF_OWNERDRAW | MF_DISABLED;
1464 }
1465 else
1466 fuFlags = MF_DISABLED;
1467 }
1468
1469 /* Draw radio buttons and tickboxes. */
1470 else if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE ||
1471 wv->button_type == BUTTON_TYPE_RADIO))
1472 fuFlags |= MF_CHECKED;
1473 else
1474 fuFlags |= MF_UNCHECKED;
1475 }
1476
1477 if (unicode_append_menu && out_string)
1478 {
1479 /* Convert out_string from UTF-8 to UTF-16-LE. */
1480 int utf8_len = strlen (out_string);
1481 WCHAR * utf16_string;
1482 if (fuFlags & MF_OWNERDRAW)
1483 utf16_string = local_alloc ((utf8_len + 1) * sizeof (WCHAR));
1484 else
1485 utf16_string = alloca ((utf8_len + 1) * sizeof (WCHAR));
1486
1487 utf8to16 (out_string, utf8_len, utf16_string);
1488 return_value = unicode_append_menu (menu, fuFlags,
1489 item != NULL ? (UINT) item
1490 : (UINT) wv->call_data,
1491 utf16_string);
1492 if (!return_value)
1493 {
1494 /* On W9x/ME, unicode menus are not supported, though AppendMenuW
1495 apparently does exist at least in some cases and appears to be
1496 stubbed out to do nothing. out_string is UTF-8, but since
1497 our standard menus are in English and this is only going to
1498 happen the first time a menu is used, the encoding is
1499 of minor importance compared with menus not working at all. */
1500 return_value =
1501 AppendMenu (menu, fuFlags,
1502 item != NULL ? (UINT) item: (UINT) wv->call_data,
1503 out_string);
1504 /* Don't use unicode menus in future. */
1505 unicode_append_menu = NULL;
1506 }
1507
1508 if (unicode_append_menu && (fuFlags & MF_OWNERDRAW))
1509 local_free (out_string);
1510 }
1511 else
1512 {
1513 return_value =
1514 AppendMenu (menu,
1515 fuFlags,
1516 item != NULL ? (UINT) item : (UINT) wv->call_data,
1517 out_string );
1518 }
1519
1520 /* This must be done after the menu item is created. */
1521 if (!wv->title && wv->call_data != 0)
1522 {
1523 if (set_menu_item_info)
1524 {
1525 MENUITEMINFO info;
1526 memset (&info, 0, sizeof (info));
1527 info.cbSize = sizeof (info);
1528 info.fMask = MIIM_DATA;
1529
1530 /* Set help string for menu item. Leave it as a Lisp_Object
1531 until it is ready to be displayed, since GC can happen while
1532 menus are active. */
1533 if (!NILP (wv->help))
1534 #ifdef USE_LISP_UNION_TYPE
1535 info.dwItemData = (DWORD) (wv->help).i;
1536 #else
1537 info.dwItemData = (DWORD) (wv->help);
1538 #endif
1539 if (wv->button_type == BUTTON_TYPE_RADIO)
1540 {
1541 /* CheckMenuRadioItem allows us to differentiate TOGGLE and
1542 RADIO items, but is not available on NT 3.51 and earlier. */
1543 info.fMask |= MIIM_TYPE | MIIM_STATE;
1544 info.fType = MFT_RADIOCHECK | MFT_STRING;
1545 info.dwTypeData = out_string;
1546 info.fState = wv->selected ? MFS_CHECKED : MFS_UNCHECKED;
1547 }
1548
1549 set_menu_item_info (menu,
1550 item != NULL ? (UINT) item : (UINT) wv->call_data,
1551 FALSE, &info);
1552 }
1553 }
1554 return return_value;
1555 }
1556
1557 /* Construct native Windows menu(bar) based on widget_value tree. */
1558 static int
1559 fill_in_menu (HMENU menu, widget_value *wv)
1560 {
1561 int items_added = 0;
1562
1563 for ( ; wv != NULL; wv = wv->next)
1564 {
1565 if (wv->contents)
1566 {
1567 HMENU sub_menu = CreatePopupMenu ();
1568
1569 if (sub_menu == NULL)
1570 return 0;
1571
1572 if (!fill_in_menu (sub_menu, wv->contents) ||
1573 !add_menu_item (menu, wv, sub_menu))
1574 {
1575 DestroyMenu (sub_menu);
1576 return 0;
1577 }
1578 }
1579 else
1580 {
1581 if (!add_menu_item (menu, wv, NULL))
1582 return 0;
1583 }
1584 }
1585 return 1;
1586 }
1587
1588 /* Display help string for currently pointed to menu item. Not
1589 supported on NT 3.51 and earlier, as GetMenuItemInfo is not
1590 available. */
1591 void
1592 w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags)
1593 {
1594 if (get_menu_item_info)
1595 {
1596 struct frame *f = x_window_to_frame (&one_w32_display_info, owner);
1597 Lisp_Object frame, help;
1598
1599 /* No help echo on owner-draw menu items, or when the keyboard is used
1600 to navigate the menus, since tooltips are distracting if they pop
1601 up elsewhere. */
1602 if (flags & MF_OWNERDRAW || flags & MF_POPUP
1603 || !(flags & MF_MOUSESELECT))
1604 help = Qnil;
1605 else
1606 {
1607 MENUITEMINFO info;
1608
1609 memset (&info, 0, sizeof (info));
1610 info.cbSize = sizeof (info);
1611 info.fMask = MIIM_DATA;
1612 get_menu_item_info (menu, item, FALSE, &info);
1613
1614 #ifdef USE_LISP_UNION_TYPE
1615 help = info.dwItemData ? (Lisp_Object) ((EMACS_INT) info.dwItemData)
1616 : Qnil;
1617 #else
1618 help = info.dwItemData ? (Lisp_Object) info.dwItemData : Qnil;
1619 #endif
1620 }
1621
1622 /* Store the help echo in the keyboard buffer as the X toolkit
1623 version does, rather than directly showing it. This seems to
1624 solve the GC problems that were present when we based the
1625 Windows code on the non-toolkit version. */
1626 if (f)
1627 {
1628 XSETFRAME (frame, f);
1629 kbd_buffer_store_help_event (frame, help);
1630 }
1631 else
1632 /* X version has a loop through frames here, which doesn't
1633 appear to do anything, unless it has some side effect. */
1634 show_help_echo (help, Qnil, Qnil, Qnil, 1);
1635 }
1636 }
1637
1638 /* Free memory used by owner-drawn strings. */
1639 static void
1640 w32_free_submenu_strings (HMENU menu)
1641 {
1642 int i, num = GetMenuItemCount (menu);
1643 for (i = 0; i < num; i++)
1644 {
1645 MENUITEMINFO info;
1646 memset (&info, 0, sizeof (info));
1647 info.cbSize = sizeof (info);
1648 info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_SUBMENU;
1649
1650 get_menu_item_info (menu, i, TRUE, &info);
1651
1652 /* Owner-drawn names are held in dwItemData. */
1653 if ((info.fType & MF_OWNERDRAW) && info.dwItemData)
1654 {
1655 #ifdef MENU_DEBUG
1656 DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData);
1657 #endif
1658 local_free (info.dwItemData);
1659 }
1660
1661 /* Recurse down submenus. */
1662 if (info.hSubMenu)
1663 w32_free_submenu_strings (info.hSubMenu);
1664 }
1665 }
1666
1667 void
1668 w32_free_menu_strings (HWND hwnd)
1669 {
1670 HMENU menu = current_popup_menu;
1671
1672 if (get_menu_item_info)
1673 {
1674 /* If there is no popup menu active, free the strings from the frame's
1675 menubar. */
1676 if (!menu)
1677 menu = GetMenu (hwnd);
1678
1679 if (menu)
1680 w32_free_submenu_strings (menu);
1681 }
1682
1683 current_popup_menu = NULL;
1684 }
1685
1686 #endif /* HAVE_MENUS */
1687
1688 /* The following is used by delayed window autoselection. */
1689
1690 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
1691 doc: /* Return t if a menu or popup dialog is active on selected frame. */)
1692 (void)
1693 {
1694 #ifdef HAVE_MENUS
1695 FRAME_PTR f;
1696 f = SELECTED_FRAME ();
1697 return (f->output_data.w32->menubar_active > 0) ? Qt : Qnil;
1698 #else
1699 return Qnil;
1700 #endif /* HAVE_MENUS */
1701 }
1702
1703 void
1704 syms_of_w32menu (void)
1705 {
1706 globals_of_w32menu ();
1707
1708 current_popup_menu = NULL;
1709
1710 DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
1711
1712 defsubr (&Smenu_or_popup_active_p);
1713 #ifdef HAVE_MENUS
1714 defsubr (&Sx_popup_dialog);
1715 #endif
1716 }
1717
1718 /*
1719 globals_of_w32menu is used to initialize those global variables that
1720 must always be initialized on startup even when the global variable
1721 initialized is non zero (see the function main in emacs.c).
1722 globals_of_w32menu is called from syms_of_w32menu when the global
1723 variable initialized is 0 and directly from main when initialized
1724 is non zero.
1725 */
1726 void
1727 globals_of_w32menu (void)
1728 {
1729 /* See if Get/SetMenuItemInfo functions are available. */
1730 HMODULE user32 = GetModuleHandle ("user32.dll");
1731 get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA");
1732 set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA");
1733 unicode_append_menu = (AppendMenuW_Proc) GetProcAddress (user32, "AppendMenuW");
1734 unicode_message_box = (MessageBoxW_Proc) GetProcAddress (user32, "MessageBoxW");
1735 }
1736
1737 /* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0
1738 (do not change this comment) */