1 /* Menu support for GNU Emacs on the Microsoft Windows API.
2    Copyright (C) 1986, 1988, 1993-1994, 1996, 1998-1999, 2001-2021 Free
3    Software Foundation, Inc.
4 
5 This file is part of GNU Emacs.
6 
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
11 
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
19 
20 #include <config.h>
21 
22 #include <signal.h>
23 #include <stdio.h>
24 #include <setjmp.h>
25 
26 #include "lisp.h"
27 #include "keyboard.h"
28 #include "frame.h"
29 #include "blockinput.h"
30 #include "buffer.h"
31 #include "coding.h"	/* for ENCODE_SYSTEM */
32 #include "menu.h"
33 #include "pdumper.h"
34 
35 /* This may include sys/types.h, and that somehow loses
36    if this is not done before the other system files.  */
37 #include "w32term.h"
38 
39 /* Cygwin does not support the multibyte string functions declared in
40  * mbstring.h below --- but that's okay: because Cygwin is
41  * UNICODE-only, we don't need to use these functions anyway.  */
42 
43 #ifndef NTGUI_UNICODE
44 #include <mbstring.h>
45 #endif /* !NTGUI_UNICODE */
46 
47 /* Load sys/types.h if not already loaded.
48    In some systems loading it twice is suicidal.  */
49 #ifndef makedev
50 #include <sys/types.h>
51 #endif
52 
53 #include "w32common.h"	/* for osinfo_cache */
54 
55 #undef HAVE_DIALOGS /* TODO: Implement native dialogs.  */
56 
57 #ifndef TRUE
58 #define TRUE 1
59 #define FALSE 0
60 #endif /* no TRUE */
61 
62 HMENU current_popup_menu;
63 
64 typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (
65     IN HMENU,
66     IN UINT,
67     IN BOOL,
68     IN OUT LPMENUITEMINFOA);
69 typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) (
70     IN HMENU,
71     IN UINT,
72     IN BOOL,
73     IN LPCMENUITEMINFOA);
74 typedef int (WINAPI * MessageBoxW_Proc) (
75     IN HWND window,
76     IN const WCHAR *text,
77     IN const WCHAR *caption,
78     IN UINT type);
79 
80 #ifdef NTGUI_UNICODE
81 GetMenuItemInfoA_Proc get_menu_item_info = GetMenuItemInfoA;
82 SetMenuItemInfoA_Proc set_menu_item_info = SetMenuItemInfoA;
83 AppendMenuW_Proc unicode_append_menu = AppendMenuW;
84 MessageBoxW_Proc unicode_message_box = MessageBoxW;
85 #else /* !NTGUI_UNICODE */
86 GetMenuItemInfoA_Proc get_menu_item_info = NULL;
87 SetMenuItemInfoA_Proc set_menu_item_info = NULL;
88 AppendMenuW_Proc unicode_append_menu = NULL;
89 MessageBoxW_Proc unicode_message_box = NULL;
90 #endif /* NTGUI_UNICODE */
91 
92 #ifdef HAVE_DIALOGS
93 static Lisp_Object w32_dialog_show (struct frame *, Lisp_Object, Lisp_Object, char **);
94 #else
95 static bool is_simple_dialog (Lisp_Object);
96 static Lisp_Object simple_dialog_show (struct frame *, Lisp_Object, Lisp_Object);
97 #endif
98 
99 static void utf8to16 (unsigned char *, int, WCHAR *);
100 static int fill_in_menu (HMENU, widget_value *);
101 
102 void w32_free_menu_strings (HWND);
103 
104 Lisp_Object
w32_popup_dialog(struct frame * f,Lisp_Object header,Lisp_Object contents)105 w32_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
106 {
107 
108   check_window_system (f);
109 
110 #ifndef HAVE_DIALOGS
111 
112   /* Handle simple Yes/No choices as MessageBox popups.  */
113   if (is_simple_dialog (contents))
114     return simple_dialog_show (f, contents, header);
115   else
116     return Qunsupported__w32_dialog;
117 #else  /* HAVE_DIALOGS */
118     {
119       Lisp_Object title;
120       char *error_name;
121       Lisp_Object selection;
122 
123       /* Decode the dialog items from what was specified.  */
124       title = Fcar (contents);
125       CHECK_STRING (title);
126 
127       list_of_panes (Fcons (contents, Qnil));
128 
129       /* Display them in a dialog box.  */
130       block_input ();
131       selection = w32_dialog_show (f, title, header, &error_name);
132       unblock_input ();
133 
134       discard_menu_items ();
135       FRAME_DISPLAY_INFO (f)->grabbed = 0;
136 
137       if (error_name) error (error_name);
138       return selection;
139     }
140 #endif /* HAVE_DIALOGS */
141 }
142 
143 /* Activate the menu bar of frame F.
144    This is called from keyboard.c when it gets the
145    MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
146 
147    To activate the menu bar, we signal to the input thread that it can
148    return from the WM_INITMENU message, allowing the normal Windows
149    processing of the menus.
150 
151    But first we recompute the menu bar contents (the whole tree).
152 
153    This way we can safely execute Lisp code.  */
154 
155 void
w32_activate_menubar(struct frame * f)156 w32_activate_menubar (struct frame *f)
157 {
158   set_frame_menubar (f, true);
159 
160   /* Lock out further menubar changes while active.  */
161   f->output_data.w32->menubar_active = 1;
162 
163   /* Signal input thread to return from WM_INITMENU.  */
164   complete_deferred_msg (FRAME_W32_WINDOW (f), WM_INITMENU, 0);
165 }
166 
167 /* This callback is called from the menu bar pulldown menu
168    when the user makes a selection.
169    Figure out what the user chose
170    and put the appropriate events into the keyboard buffer.  */
171 void menubar_selection_callback (struct frame *, void *);
172 
173 void
menubar_selection_callback(struct frame * f,void * client_data)174 menubar_selection_callback (struct frame *f, void * client_data)
175 {
176   Lisp_Object prefix, entry;
177   Lisp_Object vector;
178   Lisp_Object *subprefix_stack;
179   int submenu_depth = 0;
180   int i;
181 
182   if (!f)
183     return;
184   entry = Qnil;
185   subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * word_size);
186   vector = f->menu_bar_vector;
187   prefix = Qnil;
188   i = 0;
189   while (i < f->menu_bar_items_used)
190     {
191       if (EQ (AREF (vector, i), Qnil))
192 	{
193 	  subprefix_stack[submenu_depth++] = prefix;
194 	  prefix = entry;
195 	  i++;
196 	}
197       else if (EQ (AREF (vector, i), Qlambda))
198 	{
199 	  prefix = subprefix_stack[--submenu_depth];
200 	  i++;
201 	}
202       else if (EQ (AREF (vector, i), Qt))
203 	{
204 	  prefix = AREF (vector, i + MENU_ITEMS_PANE_PREFIX);
205 	  i += MENU_ITEMS_PANE_LENGTH;
206 	}
207       else
208 	{
209 	  entry = AREF (vector, i + MENU_ITEMS_ITEM_VALUE);
210 	  /* The UINT_PTR cast avoids a warning.  There's no problem
211 	     as long as pointers have enough bits to hold small integers.  */
212 	  if ((int) (UINT_PTR) client_data == i)
213 	    {
214 	      int j;
215 	      struct input_event buf;
216 	      Lisp_Object frame;
217 	      EVENT_INIT (buf);
218 
219 	      XSETFRAME (frame, f);
220 	      buf.kind = MENU_BAR_EVENT;
221 	      buf.frame_or_window = frame;
222 	      buf.arg = frame;
223 	      kbd_buffer_store_event (&buf);
224 
225 	      for (j = 0; j < submenu_depth; j++)
226 		if (!NILP (subprefix_stack[j]))
227 		  {
228 		    buf.kind = MENU_BAR_EVENT;
229 		    buf.frame_or_window = frame;
230 		    buf.arg = subprefix_stack[j];
231 		    kbd_buffer_store_event (&buf);
232 		  }
233 
234 	      if (!NILP (prefix))
235 		{
236 		  buf.kind = MENU_BAR_EVENT;
237 		  buf.frame_or_window = frame;
238 		  buf.arg = prefix;
239 		  kbd_buffer_store_event (&buf);
240 		}
241 
242 	      buf.kind = MENU_BAR_EVENT;
243 	      buf.frame_or_window = frame;
244 	      buf.arg = entry;
245 	      /* Free memory used by owner-drawn and help-echo strings.  */
246 	      w32_free_menu_strings (FRAME_W32_WINDOW (f));
247 	      kbd_buffer_store_event (&buf);
248 
249 	      f->output_data.w32->menubar_active = 0;
250 	      return;
251 	    }
252 	  i += MENU_ITEMS_ITEM_LENGTH;
253 	}
254     }
255   /* Free memory used by owner-drawn and help-echo strings.  */
256   w32_free_menu_strings (FRAME_W32_WINDOW (f));
257   f->output_data.w32->menubar_active = 0;
258 }
259 
260 
261 /* Set the contents of the menubar widgets of frame F.  */
262 
263 void
set_frame_menubar(struct frame * f,bool deep_p)264 set_frame_menubar (struct frame *f, bool deep_p)
265 {
266   HMENU menubar_widget = f->output_data.w32->menubar_widget;
267   Lisp_Object items;
268   widget_value *wv, *first_wv, *prev_wv = 0;
269   int i, last_i = 0;
270   int *submenu_start, *submenu_end;
271   int *submenu_top_level_items, *submenu_n_panes;
272 
273   /* We must not change the menubar when actually in use.  */
274   if (f->output_data.w32->menubar_active)
275     return;
276 
277   XSETFRAME (Vmenu_updating_frame, f);
278 
279   if (! menubar_widget)
280     deep_p = true;
281 
282   if (deep_p)
283     {
284       /* Make a widget-value tree representing the entire menu trees.  */
285 
286       struct buffer *prev = current_buffer;
287       Lisp_Object buffer;
288       ptrdiff_t specpdl_count = SPECPDL_INDEX ();
289       int previous_menu_items_used = f->menu_bar_items_used;
290       Lisp_Object *previous_items
291 	= (Lisp_Object *) alloca (previous_menu_items_used
292 				  * word_size);
293 
294       /* If we are making a new widget, its contents are empty,
295 	 do always reinitialize them.  */
296       if (! menubar_widget)
297 	previous_menu_items_used = 0;
298 
299       buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents;
300       specbind (Qinhibit_quit, Qt);
301       /* Don't let the debugger step into this code
302 	 because it is not reentrant.  */
303       specbind (Qdebug_on_next_call, Qnil);
304 
305       record_unwind_save_match_data ();
306 
307       if (NILP (Voverriding_local_map_menu_flag))
308 	{
309 	  specbind (Qoverriding_terminal_local_map, Qnil);
310 	  specbind (Qoverriding_local_map, Qnil);
311 	}
312 
313       set_buffer_internal_1 (XBUFFER (buffer));
314 
315       /* Run the hooks.  */
316       safe_run_hooks (Qactivate_menubar_hook);
317       safe_run_hooks (Qmenu_bar_update_hook);
318       fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
319 
320       items = FRAME_MENU_BAR_ITEMS (f);
321 
322       /* Save the frame's previous menu bar contents data.  */
323       if (previous_menu_items_used)
324 	memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
325 		previous_menu_items_used * word_size);
326 
327       /* Fill in menu_items with the current menu bar contents.
328 	 This can evaluate Lisp code.  */
329       save_menu_items ();
330 
331       menu_items = f->menu_bar_vector;
332       menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
333       submenu_start = (int *) alloca (ASIZE (items) * sizeof (int));
334       submenu_end = (int *) alloca (ASIZE (items) * sizeof (int));
335       submenu_n_panes = (int *) alloca (ASIZE (items) * sizeof (int));
336       submenu_top_level_items = (int *) alloca (ASIZE (items) * sizeof (int));
337       init_menu_items ();
338       for (i = 0; i < ASIZE (items); i += 4)
339 	{
340 	  Lisp_Object key, string, maps;
341 
342 	  last_i = i;
343 
344 	  key = AREF (items, i);
345 	  string = AREF (items, i + 1);
346 	  maps = AREF (items, i + 2);
347 	  if (NILP (string))
348 	    break;
349 
350 	  submenu_start[i] = menu_items_used;
351 
352 	  menu_items_n_panes = 0;
353 	  submenu_top_level_items[i]
354 	    = parse_single_submenu (key, string, maps);
355 	  submenu_n_panes[i] = menu_items_n_panes;
356 
357 	  submenu_end[i] = menu_items_used;
358 	}
359 
360       finish_menu_items ();
361 
362       /* Convert menu_items into widget_value trees
363 	 to display the menu.  This cannot evaluate Lisp code.  */
364 
365       wv = make_widget_value ("menubar", NULL, true, Qnil);
366       wv->button_type = BUTTON_TYPE_NONE;
367       first_wv = wv;
368 
369       for (i = 0; i < last_i; i += 4)
370 	{
371 	  menu_items_n_panes = submenu_n_panes[i];
372 	  wv = digest_single_submenu (submenu_start[i], submenu_end[i],
373 				      submenu_top_level_items[i]);
374 	  if (prev_wv)
375 	    prev_wv->next = wv;
376 	  else
377 	    first_wv->contents = wv;
378 	  /* Don't set wv->name here; GC during the loop might relocate it.  */
379 	  wv->enabled = true;
380 	  wv->button_type = BUTTON_TYPE_NONE;
381 	  prev_wv = wv;
382 	}
383 
384       set_buffer_internal_1 (prev);
385 
386       /* If there has been no change in the Lisp-level contents
387 	 of the menu bar, skip redisplaying it.  Just exit.  */
388 
389       for (i = 0; i < previous_menu_items_used; i++)
390 	if (menu_items_used == i
391 	    || (!EQ (previous_items[i], AREF (menu_items, i))))
392 	  break;
393       if (i == menu_items_used && i == previous_menu_items_used && i != 0)
394 	{
395 	  free_menubar_widget_value_tree (first_wv);
396 	  discard_menu_items ();
397           unbind_to (specpdl_count, Qnil);
398 	  return;
399 	}
400 
401       fset_menu_bar_vector (f, menu_items);
402       f->menu_bar_items_used = menu_items_used;
403 
404       /* This undoes save_menu_items.  */
405       unbind_to (specpdl_count, Qnil);
406 
407       /* Now GC cannot happen during the lifetime of the widget_value,
408 	 so it's safe to store data from a Lisp_String, as long as
409 	 local copies are made when the actual menu is created.
410 	 Windows takes care of this for normal string items, but
411 	 not for owner-drawn items or additional item-info.  */
412       wv = first_wv->contents;
413       for (i = 0; i < ASIZE (items); i += 4)
414 	{
415 	  Lisp_Object string;
416 	  string = AREF (items, i + 1);
417 	  if (NILP (string))
418 	    break;
419 	  wv->name = SSDATA (string);
420 	  update_submenu_strings (wv->contents);
421 	  wv = wv->next;
422 	}
423     }
424   else
425     {
426       /* Make a widget-value tree containing
427 	 just the top level menu bar strings.  */
428 
429       wv = make_widget_value ("menubar", NULL, true, Qnil);
430       wv->button_type = BUTTON_TYPE_NONE;
431       first_wv = wv;
432 
433       items = FRAME_MENU_BAR_ITEMS (f);
434       for (i = 0; i < ASIZE (items); i += 4)
435 	{
436 	  Lisp_Object string;
437 
438 	  string = AREF (items, i + 1);
439 	  if (NILP (string))
440 	    break;
441 
442 	  wv = make_widget_value (SSDATA (string), NULL, true, Qnil);
443 	  wv->button_type = BUTTON_TYPE_NONE;
444 	  /* This prevents lwlib from assuming this
445 	     menu item is really supposed to be empty.  */
446 	  /* The EMACS_INT cast avoids a warning.
447 	     This value just has to be different from small integers.  */
448 	  wv->call_data = (void *) (EMACS_INT) (-1);
449 
450 	  if (prev_wv)
451 	    prev_wv->next = wv;
452 	  else
453 	    first_wv->contents = wv;
454 	  prev_wv = wv;
455 	}
456 
457       /* Forget what we thought we knew about what is in the
458 	 detailed contents of the menu bar menus.
459 	 Changing the top level always destroys the contents.  */
460       f->menu_bar_items_used = 0;
461     }
462 
463   /* Create or update the menu bar widget.  */
464 
465   block_input ();
466 
467   if (menubar_widget)
468     {
469       /* Empty current menubar, rather than creating a fresh one.  */
470       while (DeleteMenu (menubar_widget, 0, MF_BYPOSITION))
471 	;
472     }
473   else
474     {
475       menubar_widget = CreateMenu ();
476     }
477   fill_in_menu (menubar_widget, first_wv->contents);
478 
479   free_menubar_widget_value_tree (first_wv);
480 
481   {
482     HMENU old_widget = f->output_data.w32->menubar_widget;
483 
484     f->output_data.w32->menubar_widget = menubar_widget;
485     SetMenu (FRAME_W32_WINDOW (f), f->output_data.w32->menubar_widget);
486     /* Causes flicker when menu bar is updated
487     DrawMenuBar (FRAME_W32_WINDOW (f)); */
488 
489     /* Force the window size to be recomputed so that the frame's text
490        area remains the same, if menubar has just been created.  */
491     if (old_widget == NULL)
492       {
493 	windows_or_buffers_changed = 23;
494 	adjust_frame_size (f, -1, -1, 2, false, Qmenu_bar_lines);
495       }
496   }
497 
498   unblock_input ();
499 }
500 
501 /* Called from Fx_create_frame to create the initial menubar of a frame
502    before it is mapped, so that the window is mapped with the menubar already
503    there instead of us tacking it on later and thrashing the window after it
504    is visible.  */
505 
506 void
initialize_frame_menubar(struct frame * f)507 initialize_frame_menubar (struct frame *f)
508 {
509   /* This function is called before the first chance to redisplay
510      the frame.  It has to be, so the frame will have the right size.  */
511   fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
512   set_frame_menubar (f, true);
513 }
514 
515 /* Get rid of the menu bar of frame F, and free its storage.
516    This is used when deleting a frame, and when turning off the menu bar.  */
517 
518 void
free_frame_menubar(struct frame * f)519 free_frame_menubar (struct frame *f)
520 {
521   block_input ();
522 
523   {
524     HMENU old = GetMenu (FRAME_W32_WINDOW (f));
525     SetMenu (FRAME_W32_WINDOW (f), NULL);
526     f->output_data.w32->menubar_widget = NULL;
527     DestroyMenu (old);
528   }
529 
530   unblock_input ();
531 }
532 
533 
534 /* w32_menu_show actually displays a menu using the panes and items in
535    menu_items and returns the value selected from it; we assume input
536    is blocked by the caller.  */
537 
538 /* F is the frame the menu is for.
539    X and Y are the frame-relative specified position,
540    relative to the inside upper left corner of the frame F.
541    Bitfield MENUFLAGS bits are:
542    MENU_FOR_CLICK is set if this menu was invoked for a mouse click.
543    MENU_KEYMAPS is set if this menu was specified with keymaps;
544     in that case, we return a list containing the chosen item's value
545     and perhaps also the pane's prefix.
546    TITLE is the specified menu title.
547    ERROR is a place to store an error message string in case of failure.
548    (We return nil on failure, but the value doesn't actually matter.)  */
549 
550 Lisp_Object
w32_menu_show(struct frame * f,int x,int y,int menuflags,Lisp_Object title,const char ** error)551 w32_menu_show (struct frame *f, int x, int y, int menuflags,
552 	       Lisp_Object title, const char **error)
553 {
554   int i;
555   int menu_item_selection;
556   HMENU menu;
557   POINT pos;
558   widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
559   widget_value **submenu_stack
560     = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
561   Lisp_Object *subprefix_stack
562     = (Lisp_Object *) alloca (menu_items_used * word_size);
563   int submenu_depth = 0;
564   bool first_pane;
565 
566   *error = NULL;
567 
568   if (menu_items_n_panes == 0)
569     return Qnil;
570 
571   if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
572     {
573       *error = "Empty menu";
574       return Qnil;
575     }
576 
577   block_input ();
578 
579   /* Create a tree of widget_value objects
580      representing the panes and their items.  */
581   wv = make_widget_value ("menu", NULL, true, Qnil);
582   wv->button_type = BUTTON_TYPE_NONE;
583   first_wv = wv;
584   first_pane = true;
585 
586   /* Loop over all panes and items, filling in the tree.  */
587   i = 0;
588   while (i < menu_items_used)
589     {
590       if (EQ (AREF (menu_items, i), Qnil))
591 	{
592 	  submenu_stack[submenu_depth++] = save_wv;
593 	  save_wv = prev_wv;
594 	  prev_wv = 0;
595 	  first_pane = false;
596 	  i++;
597 	}
598       else if (EQ (AREF (menu_items, i), Qlambda))
599 	{
600 	  prev_wv = save_wv;
601 	  save_wv = submenu_stack[--submenu_depth];
602 	  first_pane = false;
603 	  i++;
604 	}
605       else if (EQ (AREF (menu_items, i), Qt)
606 	       && submenu_depth != 0)
607 	i += MENU_ITEMS_PANE_LENGTH;
608       /* Ignore a nil in the item list.
609 	 It's meaningful only for dialog boxes.  */
610       else if (EQ (AREF (menu_items, i), Qquote))
611 	i += 1;
612       else if (EQ (AREF (menu_items, i), Qt))
613 	{
614 	  /* Create a new pane.  */
615 	  Lisp_Object pane_name, prefix;
616 	  const char *pane_string;
617 	  pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
618 	  prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
619 
620 	  if (STRINGP (pane_name))
621 	    {
622 	      if (unicode_append_menu)
623 		pane_name = ENCODE_UTF_8 (pane_name);
624 	      else if (STRING_MULTIBYTE (pane_name))
625 		pane_name = ENCODE_SYSTEM (pane_name);
626 
627 	      ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
628 	    }
629 
630 	  pane_string = (NILP (pane_name)
631 			 ? "" : SSDATA (pane_name));
632 	  /* If there is just one top-level pane, put all its items directly
633 	     under the top-level menu.  */
634 	  if (menu_items_n_panes == 1)
635 	    pane_string = "";
636 
637 	  /* If the pane has a meaningful name,
638 	     make the pane a top-level menu item
639 	     with its items as a submenu beneath it.  */
640 	  if (!(menuflags & MENU_KEYMAPS) && strcmp (pane_string, ""))
641 	    {
642 	      wv = make_widget_value (pane_string, NULL, true, Qnil);
643 	      if (save_wv)
644 		save_wv->next = wv;
645 	      else
646 		first_wv->contents = wv;
647 	      if ((menuflags & MENU_KEYMAPS) && !NILP (prefix))
648 		wv->name++;
649 	      wv->button_type = BUTTON_TYPE_NONE;
650 	      save_wv = wv;
651 	      prev_wv = 0;
652 	    }
653 	  else if (first_pane)
654 	    {
655 	      save_wv = wv;
656 	      prev_wv = 0;
657 	    }
658 	  first_pane = false;
659 	  i += MENU_ITEMS_PANE_LENGTH;
660 	}
661       else
662 	{
663 	  /* Create a new item within current pane.  */
664 	  Lisp_Object item_name, enable, descrip, def, type, selected, help;
665 
666 	  item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
667 	  enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
668 	  descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
669 	  def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
670 	  type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
671 	  selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
672           help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
673 
674           if (STRINGP (item_name))
675 	    {
676 	      if (unicode_append_menu)
677 		item_name = ENCODE_UTF_8 (item_name);
678 	      else if (STRING_MULTIBYTE (item_name))
679 		item_name = ENCODE_SYSTEM (item_name);
680 
681 	      ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
682 	    }
683 
684 	  if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
685             {
686 	      descrip = ENCODE_SYSTEM (descrip);
687 	      ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
688 	    }
689 
690 	  wv = make_widget_value (SSDATA (item_name), NULL, !NILP (enable),
691 				  STRINGP (help) ? help : Qnil);
692 	  if (prev_wv)
693 	    prev_wv->next = wv;
694 	  else
695 	    save_wv->contents = wv;
696 	  if (!NILP (descrip))
697 	    wv->key = SSDATA (descrip);
698 	  /* Use the contents index as call_data, since we are
699              restricted to 16-bits.  */
700 	  wv->call_data = !NILP (def) ? (void *) (UINT_PTR) i : 0;
701 
702 	  if (NILP (type))
703 	    wv->button_type = BUTTON_TYPE_NONE;
704 	  else if (EQ (type, QCtoggle))
705 	    wv->button_type = BUTTON_TYPE_TOGGLE;
706 	  else if (EQ (type, QCradio))
707 	    wv->button_type = BUTTON_TYPE_RADIO;
708 	  else
709 	    emacs_abort ();
710 
711 	  wv->selected = !NILP (selected);
712 
713 	  prev_wv = wv;
714 
715 	  i += MENU_ITEMS_ITEM_LENGTH;
716 	}
717     }
718 
719   /* Deal with the title, if it is non-nil.  */
720   if (!NILP (title))
721     {
722       widget_value *wv_title;
723       widget_value *wv_sep = make_widget_value ("--", NULL, false, Qnil);
724 
725       /* Maybe replace this separator with a bitmap or owner-draw item
726 	 so that it looks better.  Having two separators looks odd.  */
727       wv_sep->next = first_wv->contents;
728 
729       if (unicode_append_menu)
730 	title = ENCODE_UTF_8 (title);
731       else if (STRING_MULTIBYTE (title))
732 	title = ENCODE_SYSTEM (title);
733 
734       wv_title = make_widget_value (SSDATA (title), NULL, true, Qnil);
735       wv_title->title = TRUE;
736       wv_title->button_type = BUTTON_TYPE_NONE;
737       wv_title->next = wv_sep;
738       first_wv->contents = wv_title;
739     }
740 
741   /* No selection has been chosen yet.  */
742   menu_item_selection = 0;
743 
744   /* Actually create the menu.  */
745   current_popup_menu = menu = CreatePopupMenu ();
746   fill_in_menu (menu, first_wv->contents);
747 
748   /* Adjust coordinates to be root-window-relative.  */
749   pos.x = x;
750   pos.y = y;
751   ClientToScreen (FRAME_W32_WINDOW (f), &pos);
752 
753   /* Display the menu.  */
754   menu_item_selection = SendMessage (FRAME_W32_WINDOW (f),
755 				     WM_EMACS_TRACKPOPUPMENU,
756 				     (WPARAM)menu, (LPARAM)&pos);
757 
758   /* Clean up extraneous mouse events which might have been generated
759      during the call. */
760   discard_mouse_events ();
761   FRAME_DISPLAY_INFO (f)->grabbed = 0;
762 
763   /* Free the widget_value objects we used to specify the contents.  */
764   free_menubar_widget_value_tree (first_wv);
765 
766   DestroyMenu (menu);
767 
768   /* Free the owner-drawn and help-echo menu strings.  */
769   w32_free_menu_strings (FRAME_W32_WINDOW (f));
770   f->output_data.w32->menubar_active = 0;
771 
772   /* Find the selected item, and its pane, to return
773      the proper value.  */
774   if (menu_item_selection != 0)
775     {
776       Lisp_Object prefix, entry;
777 
778       prefix = entry = Qnil;
779       i = 0;
780       while (i < menu_items_used)
781 	{
782 	  if (EQ (AREF (menu_items, i), Qnil))
783 	    {
784 	      subprefix_stack[submenu_depth++] = prefix;
785 	      prefix = entry;
786 	      i++;
787 	    }
788 	  else if (EQ (AREF (menu_items, i), Qlambda))
789 	    {
790 	      prefix = subprefix_stack[--submenu_depth];
791 	      i++;
792 	    }
793 	  else if (EQ (AREF (menu_items, i), Qt))
794 	    {
795 	      prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
796 	      i += MENU_ITEMS_PANE_LENGTH;
797 	    }
798 	  /* Ignore a nil in the item list.
799 	     It's meaningful only for dialog boxes.  */
800 	  else if (EQ (AREF (menu_items, i), Qquote))
801 	    i += 1;
802 	  else
803 	    {
804 	      entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
805 	      if (menu_item_selection == i)
806 		{
807 		  if (menuflags & MENU_KEYMAPS)
808 		    {
809 		      int j;
810 
811 		      entry = Fcons (entry, Qnil);
812 		      if (!NILP (prefix))
813 			entry = Fcons (prefix, entry);
814 		      for (j = submenu_depth - 1; j >= 0; j--)
815 			if (!NILP (subprefix_stack[j]))
816 			  entry = Fcons (subprefix_stack[j], entry);
817 		    }
818 		  unblock_input ();
819 		  return entry;
820 		}
821 	      i += MENU_ITEMS_ITEM_LENGTH;
822 	    }
823 	}
824     }
825   else if (!(menuflags & MENU_FOR_CLICK))
826     {
827       unblock_input ();
828       /* Make "Cancel" equivalent to C-g.  */
829       quit ();
830     }
831 
832   unblock_input ();
833   return Qnil;
834 }
835 
836 
837 #ifdef HAVE_DIALOGS
838 /* TODO: On Windows, there are two ways of defining a dialog.
839 
840    1. Create a predefined dialog resource and include it in nt/emacs.rc.
841       Using this method, we could then set the titles and make unneeded
842       buttons invisible before displaying the dialog.  Everything would
843       be a fixed size though, so there is a risk that text does not
844       fit on a button.
845    2. Create the dialog template in memory on the fly.  This allows us
846       to size the dialog and buttons dynamically, probably giving more
847       natural looking results for dialogs with few buttons, and eliminating
848       the problem of text overflowing the buttons.  But the API for this is
849       quite complex - structures have to be allocated in particular ways,
850       text content is tacked onto the end of structures in variable length
851       arrays with further structures tacked on after these, there are
852       certain alignment requirements for all this, and we have to
853       measure all the text and convert to "dialog coordinates" to figure
854       out how big to make everything.
855 
856       For now, we'll just stick with menus for dialogs that are more
857       complicated than simple yes/no type questions for which we can use
858       the MessageBox function.
859 */
860 
861 static char * button_names [] = {
862   "button1", "button2", "button3", "button4", "button5",
863   "button6", "button7", "button8", "button9", "button10" };
864 
865 static Lisp_Object
w32_dialog_show(struct frame * f,Lisp_Object title,Lisp_Object header,char ** error)866 w32_dialog_show (struct frame *f, Lisp_Object title,
867 		 Lisp_Object header, char **error)
868 {
869   int i, nb_buttons = 0;
870   char dialog_name[6];
871   int menu_item_selection;
872 
873   widget_value *wv, *first_wv = 0, *prev_wv = 0;
874 
875   /* Number of elements seen so far, before boundary.  */
876   int left_count = 0;
877   /* true means we've seen the boundary between left-hand elts and
878      right-hand.  */
879   bool boundary_seen = false;
880 
881   *error = NULL;
882 
883   if (menu_items_n_panes > 1)
884     {
885       *error = "Multiple panes in dialog box";
886       return Qnil;
887     }
888 
889   /* Create a tree of widget_value objects
890      representing the text label and buttons.  */
891   {
892     Lisp_Object pane_name;
893     char *pane_string;
894     pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
895     pane_string = (NILP (pane_name)
896 		   ? "" : SSDATA (pane_name));
897     prev_wv = make_widget_value ("message", pane_string, true, Qnil);
898     first_wv = prev_wv;
899 
900     /* Loop over all panes and items, filling in the tree.  */
901     i = MENU_ITEMS_PANE_LENGTH;
902     while (i < menu_items_used)
903       {
904 
905 	/* Create a new item within current pane.  */
906 	Lisp_Object item_name, enable, descrip, help;
907 
908 	item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
909 	enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
910 	descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
911         help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
912 
913 	if (NILP (item_name))
914 	  {
915 	    free_menubar_widget_value_tree (first_wv);
916 	    *error = "Submenu in dialog items";
917 	    return Qnil;
918 	  }
919 	if (EQ (item_name, Qquote))
920 	  {
921 	    /* This is the boundary between left-side elts
922 	       and right-side elts.  Stop incrementing right_count.  */
923 	    boundary_seen = true;
924 	    i++;
925 	    continue;
926 	  }
927 	if (nb_buttons >= 9)
928 	  {
929 	    free_menubar_widget_value_tree (first_wv);
930 	    *error = "Too many dialog items";
931 	    return Qnil;
932 	  }
933 
934 	wv = make_widget_value (button_names[nb_buttons],
935 				SSDATA (item_name),
936 				!NILP (enable), Qnil);
937 	prev_wv->next = wv;
938 	if (!NILP (descrip))
939 	  wv->key = SSDATA (descrip);
940 	wv->call_data = aref_addr (menu_items, i);
941 	prev_wv = wv;
942 
943 	if (! boundary_seen)
944 	  left_count++;
945 
946 	nb_buttons++;
947 	i += MENU_ITEMS_ITEM_LENGTH;
948       }
949 
950     /* If the boundary was not specified,
951        by default put half on the left and half on the right.  */
952     if (! boundary_seen)
953       left_count = nb_buttons - nb_buttons / 2;
954 
955     wv = make_widget_value (dialog_name, NULL, false, Qnil);
956 
957     /*  Frame title: 'Q' = Question, 'I' = Information.
958         Can also have 'E' = Error if, one day, we want
959         a popup for errors. */
960     if (NILP (header))
961       dialog_name[0] = 'Q';
962     else
963       dialog_name[0] = 'I';
964 
965     /* Dialog boxes use a really stupid name encoding
966        which specifies how many buttons to use
967        and how many buttons are on the right. */
968     dialog_name[1] = '0' + nb_buttons;
969     dialog_name[2] = 'B';
970     dialog_name[3] = 'R';
971     /* Number of buttons to put on the right.  */
972     dialog_name[4] = '0' + nb_buttons - left_count;
973     dialog_name[5] = 0;
974     wv->contents = first_wv;
975     first_wv = wv;
976   }
977 
978   /* Actually create the dialog.  */
979   dialog_id = widget_id_tick++;
980   menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
981 			   f->output_data.w32->widget, true, 0,
982 			   dialog_selection_callback, 0);
983   lw_modify_all_widgets (dialog_id, first_wv->contents, TRUE);
984 
985   /* Free the widget_value objects we used to specify the contents.  */
986   free_menubar_widget_value_tree (first_wv);
987 
988   /* No selection has been chosen yet.  */
989   menu_item_selection = 0;
990 
991   /* Display the menu.  */
992   lw_pop_up_all_widgets (dialog_id);
993 
994   /* Process events that apply to the menu.  */
995   popup_get_selection ((XEvent *) 0, FRAME_DISPLAY_INFO (f), dialog_id);
996 
997   lw_destroy_all_widgets (dialog_id);
998 
999   /* Find the selected item, and its pane, to return
1000      the proper value.  */
1001   if (menu_item_selection != 0)
1002     {
1003       i = 0;
1004       while (i < menu_items_used)
1005 	{
1006 	  Lisp_Object entry;
1007 
1008 	  if (EQ (AREF (menu_items, i), Qt))
1009 	    i += MENU_ITEMS_PANE_LENGTH;
1010 	  else
1011 	    {
1012 	      entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
1013 	      if (menu_item_selection == i)
1014 		return entry;
1015 	      i += MENU_ITEMS_ITEM_LENGTH;
1016 	    }
1017 	}
1018     }
1019   else
1020     /* Make "Cancel" equivalent to C-g.  */
1021     quit ();
1022 
1023   return Qnil;
1024 }
1025 #else /* !HAVE_DIALOGS  */
1026 
1027 /* Currently we only handle Yes No dialogs (y-or-n-p and yes-or-no-p) as
1028    simple dialogs.  We could handle a few more, but I'm not aware of
1029    anywhere in Emacs that uses the other specific dialog choices that
1030    MessageBox provides.  */
1031 
1032 static bool
is_simple_dialog(Lisp_Object contents)1033 is_simple_dialog (Lisp_Object contents)
1034 {
1035   Lisp_Object options;
1036   Lisp_Object name, yes, no, other;
1037 
1038   if (!CONSP (contents))
1039     return false;
1040   options = XCDR (contents);
1041 
1042   yes = build_string ("Yes");
1043   no = build_string ("No");
1044 
1045   if (!CONSP (options))
1046     return false;
1047 
1048   name = XCAR (options);
1049   if (!CONSP (name))
1050     return false;
1051   name = XCAR (name);
1052 
1053   if (!NILP (Fstring_equal (name, yes)))
1054     other = no;
1055   else if (!NILP (Fstring_equal (name, no)))
1056     other = yes;
1057   else
1058     return false;
1059 
1060   options = XCDR (options);
1061   if (!CONSP (options))
1062     return false;
1063 
1064   name = XCAR (options);
1065   if (!CONSP (name))
1066     return false;
1067   name = XCAR (name);
1068   if (NILP (Fstring_equal (name, other)))
1069     return false;
1070 
1071   /* Check there are no more options.  */
1072   options = XCDR (options);
1073   return !(CONSP (options));
1074 }
1075 
1076 static Lisp_Object
simple_dialog_show(struct frame * f,Lisp_Object contents,Lisp_Object header)1077 simple_dialog_show (struct frame *f, Lisp_Object contents, Lisp_Object header)
1078 {
1079   int answer;
1080   UINT type;
1081   Lisp_Object lispy_answer = Qnil, temp = XCAR (contents);
1082 
1083   type = MB_YESNO;
1084 
1085   /* Since we only handle Yes/No dialogs, and we already checked
1086      is_simple_dialog, we don't need to worry about checking contents
1087      to see what type of dialog to use.  */
1088 
1089   /* Use Unicode if possible, so any language can be displayed.  */
1090   if (unicode_message_box)
1091     {
1092       WCHAR *text;
1093       const WCHAR *title;
1094       USE_SAFE_ALLOCA;
1095 
1096       if (STRINGP (temp))
1097 	{
1098 	  char *utf8_text = SSDATA (ENCODE_UTF_8 (temp));
1099 	  /* Be pessimistic about the number of characters needed.
1100 	     Remember characters outside the BMP will take more than
1101 	     one utf16 word, so we cannot simply use the character
1102 	     length of temp.  */
1103 	  int utf8_len = strlen (utf8_text);
1104 	  text = SAFE_ALLOCA ((utf8_len + 1) * sizeof (WCHAR));
1105 	  utf8to16 ((unsigned char *)utf8_text, utf8_len, text);
1106 	}
1107       else
1108 	{
1109 	  text = (WCHAR *)L"";
1110 	}
1111 
1112       if (NILP (header))
1113 	{
1114 	  title = L"Question";
1115 	  type |= MB_ICONQUESTION;
1116 	}
1117       else
1118 	{
1119 	  title = L"Information";
1120 	  type |= MB_ICONINFORMATION;
1121 	}
1122 
1123       answer = unicode_message_box (FRAME_W32_WINDOW (f), text, title, type);
1124       SAFE_FREE ();
1125     }
1126   else
1127     {
1128       const char *text, *title;
1129 
1130       /* Fall back on ANSI message box, but at least use system
1131 	 encoding so questions representable by the system codepage
1132 	 are encoded properly.  */
1133       if (STRINGP (temp))
1134 	text = SSDATA (ENCODE_SYSTEM (temp));
1135       else
1136 	text = "";
1137 
1138       if (NILP (header))
1139 	{
1140 	  title = "Question";
1141 	  type |= MB_ICONQUESTION;
1142 	}
1143       else
1144 	{
1145 	  title = "Information";
1146 	  type |= MB_ICONINFORMATION;
1147 	}
1148 
1149       answer = MessageBox (FRAME_W32_WINDOW (f), text, title, type);
1150     }
1151 
1152   if (answer == IDYES)
1153     lispy_answer = build_string ("Yes");
1154   else if (answer == IDNO)
1155     lispy_answer = build_string ("No");
1156   else
1157     quit ();
1158 
1159   for (temp = XCDR (contents); CONSP (temp); temp = XCDR (temp))
1160     {
1161       Lisp_Object item, name, value;
1162       item = XCAR (temp);
1163       if (CONSP (item))
1164 	{
1165 	  name = XCAR (item);
1166 	  value = XCDR (item);
1167 	}
1168       else
1169 	{
1170 	  name = item;
1171 	  value = Qnil;
1172 	}
1173 
1174       if (!NILP (Fstring_equal (name, lispy_answer)))
1175 	{
1176 	  return value;
1177 	}
1178     }
1179   return quit ();
1180 }
1181 #endif  /* !HAVE_DIALOGS  */
1182 
1183 
1184 /* UTF8: 0xxxxxxx, 110xxxxx 10xxxxxx, 1110xxxx, 10xxxxxx, 10xxxxxx */
1185 static void
utf8to16(unsigned char * src,int len,WCHAR * dest)1186 utf8to16 (unsigned char * src, int len, WCHAR * dest)
1187 {
1188   while (len > 0)
1189     {
1190       if (*src < 0x80)
1191 	{
1192 	  *dest = (WCHAR) *src;
1193 	  dest++; src++; len--;
1194 	}
1195       /* Since we might get >3 byte sequences which we don't handle, ignore the extra parts.  */
1196       else if (*src < 0xC0)
1197 	{
1198 	  src++; len--;
1199 	}
1200       /* 2 char UTF-8 sequence.  */
1201       else if (*src <  0xE0)
1202 	{
1203 	  *dest = (WCHAR) (((*src & 0x1f) << 6)
1204 			   | (*(src + 1) & 0x3f));
1205 	  src += 2; len -= 2; dest++;
1206 	}
1207       else if (*src < 0xF0)
1208 	{
1209 	  *dest = (WCHAR) (((*src & 0x0f) << 12)
1210 			   | ((*(src + 1) & 0x3f) << 6)
1211 			   | (*(src + 2) & 0x3f));
1212 	  src += 3; len -= 3; dest++;
1213 	}
1214       else /* Not encodable. Insert Unicode Substitution char.  */
1215 	{
1216 	  *dest = (WCHAR) 0xfffd;
1217 	  src++; len--; dest++;
1218 	}
1219     }
1220   *dest = 0;
1221 }
1222 
1223 static int
add_menu_item(HMENU menu,widget_value * wv,HMENU item)1224 add_menu_item (HMENU menu, widget_value *wv, HMENU item)
1225 {
1226   UINT fuFlags;
1227   char *out_string, *p, *q;
1228   int return_value;
1229   size_t nlen, orig_len;
1230   USE_SAFE_ALLOCA;
1231 
1232   if (menu_separator_name_p (wv->name))
1233     {
1234       fuFlags = MF_SEPARATOR;
1235       out_string = NULL;
1236     }
1237   else
1238     {
1239       if (wv->enabled)
1240 	fuFlags = MF_STRING;
1241       else
1242 	fuFlags = MF_STRING | MF_GRAYED;
1243 
1244       if (wv->key != NULL)
1245 	{
1246 	  out_string = SAFE_ALLOCA (strlen (wv->name) + strlen (wv->key) + 2);
1247 	  p = stpcpy (out_string, wv->name);
1248 	  p = stpcpy (p, "\t");
1249 	  strcpy (p, wv->key);
1250 	}
1251       else
1252 	out_string = (char *)wv->name;
1253 
1254       /* Quote any special characters within the menu item's text and
1255 	 key binding.  */
1256       nlen = orig_len = strlen (out_string);
1257       if (unicode_append_menu)
1258         {
1259           /* With UTF-8, & cannot be part of a multibyte character.  */
1260           for (p = out_string; *p; p++)
1261             {
1262               if (*p == '&')
1263                 nlen++;
1264             }
1265         }
1266 #ifndef NTGUI_UNICODE
1267       else
1268         {
1269           /* If encoded with the system codepage, use multibyte string
1270              functions in case of multibyte characters that contain '&'.  */
1271           for (p = out_string; *p; p = _mbsinc (p))
1272             {
1273               if (_mbsnextc (p) == '&')
1274                 nlen++;
1275             }
1276         }
1277 #endif /* !NTGUI_UNICODE */
1278 
1279       if (nlen > orig_len)
1280         {
1281           p = out_string;
1282           out_string = SAFE_ALLOCA (nlen + 1);
1283           q = out_string;
1284           while (*p)
1285             {
1286               if (unicode_append_menu)
1287                 {
1288                   if (*p == '&')
1289                     *q++ = *p;
1290                   *q++ = *p++;
1291                 }
1292 #ifndef NTGUI_UNICODE
1293               else
1294                 {
1295                   if (_mbsnextc (p) == '&')
1296                     {
1297                       _mbsncpy (q, p, 1);
1298                       q = _mbsinc (q);
1299                     }
1300                   _mbsncpy (q, p, 1);
1301                   p = _mbsinc (p);
1302                   q = _mbsinc (q);
1303                 }
1304 #endif /* !NTGUI_UNICODE */
1305             }
1306           *q = '\0';
1307         }
1308 
1309       if (item != NULL)
1310 	fuFlags = MF_POPUP;
1311       else if (wv->title || wv->call_data == 0)
1312 	{
1313 	  /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since
1314 	     we can't deallocate the memory otherwise.  */
1315 	  if (get_menu_item_info)
1316 	    {
1317               out_string = (char *) local_alloc (strlen (wv->name) + 1);
1318               strcpy (out_string, wv->name);
1319 #ifdef MENU_DEBUG
1320 	      DebPrint ("Menu: allocating %ld for owner-draw", out_string);
1321 #endif
1322 	      fuFlags = MF_OWNERDRAW | MF_DISABLED;
1323 	    }
1324 	  else
1325 	    fuFlags = MF_DISABLED;
1326 	}
1327 
1328       /* Draw radio buttons and tickboxes. */
1329       else if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE ||
1330 				wv->button_type == BUTTON_TYPE_RADIO))
1331 	fuFlags |= MF_CHECKED;
1332       else
1333 	fuFlags |= MF_UNCHECKED;
1334     }
1335 
1336   if (unicode_append_menu && out_string)
1337     {
1338       /* Convert out_string from UTF-8 to UTF-16-LE.  */
1339       int utf8_len = strlen (out_string);
1340       WCHAR * utf16_string;
1341       if (fuFlags & MF_OWNERDRAW)
1342 	utf16_string = local_alloc ((utf8_len + 1) * sizeof (WCHAR));
1343       else
1344 	utf16_string = SAFE_ALLOCA ((utf8_len + 1) * sizeof (WCHAR));
1345 
1346       utf8to16 ((unsigned char *)out_string, utf8_len, utf16_string);
1347       return_value = unicode_append_menu (menu, fuFlags,
1348 					  item != NULL ? (UINT_PTR) item
1349 					    : (UINT_PTR) wv->call_data,
1350 					  utf16_string);
1351 
1352 #ifndef NTGUI_UNICODE /* Fallback does not apply when always UNICODE */
1353       if (!return_value)
1354 	{
1355 	  /* On W9x/ME, Unicode menus are not supported, though AppendMenuW
1356 	     apparently does exist at least in some cases and appears to be
1357 	     stubbed out to do nothing.  out_string is UTF-8, but since
1358 	     our standard menus are in English and this is only going to
1359 	     happen the first time a menu is used, the encoding is
1360 	     of minor importance compared with menus not working at all.  */
1361 	  return_value =
1362 	    AppendMenu (menu, fuFlags,
1363 			item != NULL ? (UINT_PTR) item: (UINT_PTR) wv->call_data,
1364 			out_string);
1365 	  /* Don't use Unicode menus in future, unless this is Windows
1366 	     NT or later, where a failure of AppendMenuW does NOT mean
1367 	     Unicode menus are unsupported.  */
1368 	  if (osinfo_cache.dwPlatformId != VER_PLATFORM_WIN32_NT)
1369 	    unicode_append_menu = NULL;
1370 	}
1371 #endif /* NTGUI_UNICODE */
1372 
1373       if (unicode_append_menu && (fuFlags & MF_OWNERDRAW))
1374 	local_free (out_string);
1375     }
1376   else
1377     {
1378       return_value =
1379 	AppendMenu (menu,
1380 		    fuFlags,
1381 		    item != NULL ? (UINT_PTR) item : (UINT_PTR) wv->call_data,
1382 		    out_string );
1383     }
1384 
1385   /* This must be done after the menu item is created.  */
1386   if (!wv->title && wv->call_data != 0)
1387     {
1388       if (set_menu_item_info)
1389 	{
1390 	  MENUITEMINFO info;
1391 	  memset (&info, 0, sizeof (info));
1392 	  info.cbSize = sizeof (info);
1393 	  info.fMask = MIIM_DATA;
1394 
1395 	  /* Set help string for menu item.  Leave it as a pointer to
1396 	     a Lisp_String until it is ready to be displayed, since GC
1397 	     can happen while menus are active.  */
1398 	  if (!NILP (wv->help))
1399 	    {
1400 	      /* We use XUNTAG below because in a 32-bit build
1401 		 --with-wide-int we cannot pass a Lisp_Object
1402 		 via a DWORD member of MENUITEMINFO.  */
1403 	      /* As of Jul-2012, w32api headers say that dwItemData
1404 		 has DWORD type, but that's a bug: it should actually
1405 		 be ULONG_PTR, which is correct for 32-bit and 64-bit
1406 		 Windows alike.  MSVC headers get it right; hopefully,
1407 		 MinGW headers will, too.  */
1408 	      eassert (STRINGP (wv->help));
1409 	      info.dwItemData = (ULONG_PTR) XUNTAG (wv->help, Lisp_String,
1410 						    struct Lisp_String);
1411 	    }
1412 	  if (wv->button_type == BUTTON_TYPE_RADIO)
1413 	    {
1414 	      /* CheckMenuRadioItem allows us to differentiate TOGGLE and
1415 		 RADIO items, but is not available on NT 3.51 and earlier.  */
1416 	      info.fMask |= MIIM_TYPE | MIIM_STATE;
1417 	      info.fType = MFT_RADIOCHECK | MFT_STRING;
1418 	      info.dwTypeData = out_string;
1419 	      info.fState = wv->selected ? MFS_CHECKED : MFS_UNCHECKED;
1420 	    }
1421 
1422 	  set_menu_item_info (menu,
1423 			      item != NULL ? (UINT_PTR) item : (UINT_PTR) wv->call_data,
1424 			      FALSE, &info);
1425 	}
1426     }
1427   SAFE_FREE ();
1428   return return_value;
1429 }
1430 
1431 /* Construct native Windows menu(bar) based on widget_value tree.  */
1432 static int
fill_in_menu(HMENU menu,widget_value * wv)1433 fill_in_menu (HMENU menu, widget_value *wv)
1434 {
1435   for ( ; wv != NULL; wv = wv->next)
1436     {
1437       if (wv->contents)
1438 	{
1439 	  HMENU sub_menu = CreatePopupMenu ();
1440 
1441 	  if (sub_menu == NULL)
1442 	    return 0;
1443 
1444 	  if (!fill_in_menu (sub_menu, wv->contents) ||
1445 	      !add_menu_item (menu, wv, sub_menu))
1446 	    {
1447 	      DestroyMenu (sub_menu);
1448 	      return 0;
1449 	    }
1450 	}
1451       else
1452 	{
1453 	  if (!add_menu_item (menu, wv, NULL))
1454 	    return 0;
1455 	}
1456     }
1457   return 1;
1458 }
1459 
1460 /* Display help string for currently pointed to menu item. Not
1461    supported on NT 3.51 and earlier, as GetMenuItemInfo is not
1462    available. */
1463 void w32_menu_display_help (HWND, HMENU, UINT, UINT);
1464 
1465 void
w32_menu_display_help(HWND owner,HMENU menu,UINT item,UINT flags)1466 w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags)
1467 {
1468   if (get_menu_item_info)
1469     {
1470       struct frame *f = w32_window_to_frame (&one_w32_display_info, owner);
1471       Lisp_Object frame, help;
1472 
1473       /* No help echo on owner-draw menu items, or when the keyboard
1474 	 is used to navigate the menus, since tooltips are distracting
1475 	 if they pop up elsewhere.  */
1476       if ((flags & MF_OWNERDRAW) || (flags & MF_POPUP)
1477 	  || !(flags & MF_MOUSESELECT)
1478 	  /* Ignore any dwItemData for menu items whose flags don't
1479 	     have the MF_HILITE bit set.  These are dwItemData that
1480 	     Windows sends our way, but they aren't pointers to our
1481 	     Lisp_String objects, so trying to create Lisp_Strings out
1482 	     of them below and pass that to the keyboard queue will
1483 	     crash Emacs when we try to display those "strings".  It
1484 	     is unclear why we get these dwItemData, or what they are:
1485 	     sometimes they point to a wchar_t string that is the menu
1486 	     title, sometimes to something that doesn't look like text
1487 	     at all.  (The problematic data also comes with the 0x0800
1488 	     bit set, but this bit is not documented, so we don't want
1489 	     to depend on it.)  */
1490 	  || !(flags & MF_HILITE))
1491 	help = Qnil;
1492       else
1493 	{
1494 	  MENUITEMINFO info;
1495 
1496 	  memset (&info, 0, sizeof (info));
1497 	  info.cbSize = sizeof (info);
1498 	  info.fMask = MIIM_DATA;
1499 	  get_menu_item_info (menu, item, FALSE, &info);
1500 
1501 	  help =
1502 	    info.dwItemData
1503 	    ? make_lisp_ptr ((void *) info.dwItemData, Lisp_String)
1504 	    : Qnil;
1505 	}
1506 
1507       /* Store the help echo in the keyboard buffer as the X toolkit
1508 	 version does, rather than directly showing it. This seems to
1509 	 solve the GC problems that were present when we based the
1510 	 Windows code on the non-toolkit version.  */
1511       if (f)
1512 	{
1513 	  XSETFRAME (frame, f);
1514 	  kbd_buffer_store_help_event (frame, help);
1515 	}
1516       else
1517 	/* X version has a loop through frames here, which doesn't
1518 	   appear to do anything, unless it has some side effect.  */
1519 	show_help_echo (help, Qnil, Qnil, Qnil);
1520     }
1521 }
1522 
1523 /* Free memory used by owner-drawn strings.  */
1524 static void
w32_free_submenu_strings(HMENU menu)1525 w32_free_submenu_strings (HMENU menu)
1526 {
1527   int i, num = GetMenuItemCount (menu);
1528   for (i = 0; i < num; i++)
1529     {
1530       MENUITEMINFO info;
1531       memset (&info, 0, sizeof (info));
1532       info.cbSize = sizeof (info);
1533       info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_SUBMENU;
1534 
1535       get_menu_item_info (menu, i, TRUE, &info);
1536 
1537       /* Owner-drawn names are held in dwItemData.  */
1538       if ((info.fType & MF_OWNERDRAW) && info.dwItemData)
1539 	{
1540 #ifdef MENU_DEBUG
1541 	  DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData);
1542 #endif
1543 	  local_free (info.dwItemData);
1544 	}
1545 
1546       /* Recurse down submenus.  */
1547       if (info.hSubMenu)
1548 	w32_free_submenu_strings (info.hSubMenu);
1549     }
1550 }
1551 
1552 void
w32_free_menu_strings(HWND hwnd)1553 w32_free_menu_strings (HWND hwnd)
1554 {
1555   HMENU menu = current_popup_menu;
1556 
1557   if (get_menu_item_info)
1558     {
1559       /* If there is no popup menu active, free the strings from the frame's
1560 	 menubar.  */
1561       if (!menu)
1562 	menu = GetMenu (hwnd);
1563 
1564       if (menu)
1565 	w32_free_submenu_strings (menu);
1566     }
1567 
1568   current_popup_menu = NULL;
1569 }
1570 
1571 /* The following is used by delayed window autoselection.  */
1572 
1573 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
1574        doc: /* SKIP: real doc in xmenu.c.  */)
1575   (void)
1576 {
1577   struct frame *f;
1578   f = SELECTED_FRAME ();
1579   return (f->output_data.w32->menubar_active > 0) ? Qt : Qnil;
1580 }
1581 
1582 void
syms_of_w32menu(void)1583 syms_of_w32menu (void)
1584 {
1585   globals_of_w32menu ();
1586 
1587   current_popup_menu = NULL;
1588   PDUMPER_IGNORE (current_popup_menu);
1589 
1590   DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
1591   DEFSYM (Qunsupported__w32_dialog, "unsupported--w32-dialog");
1592 
1593   defsubr (&Smenu_or_popup_active_p);
1594 }
1595 
1596 /*
1597 	globals_of_w32menu is used to initialize those global variables that
1598 	must always be initialized on startup even when the global variable
1599 	initialized is non zero (see the function main in emacs.c).
1600 	globals_of_w32menu is called from syms_of_w32menu when the global
1601 	variable initialized is 0 and directly from main when initialized
1602 	is non zero.
1603  */
1604 void
globals_of_w32menu(void)1605 globals_of_w32menu (void)
1606 {
1607 #ifndef NTGUI_UNICODE
1608   /* See if Get/SetMenuItemInfo functions are available.  */
1609   HMODULE user32 = GetModuleHandle ("user32.dll");
1610   get_menu_item_info = (GetMenuItemInfoA_Proc)
1611     get_proc_addr (user32, "GetMenuItemInfoA");
1612   set_menu_item_info = (SetMenuItemInfoA_Proc)
1613     get_proc_addr (user32, "SetMenuItemInfoA");
1614   unicode_append_menu = (AppendMenuW_Proc)
1615     get_proc_addr (user32, "AppendMenuW");
1616   unicode_message_box = (MessageBoxW_Proc)
1617     get_proc_addr (user32, "MessageBoxW");
1618 #endif /* !NTGUI_UNICODE */
1619 }
1620