Include w32term.h, move widget related
[bpt/emacs.git] / src / w32menu.c
CommitLineData
e9e23e23 1/* Menu support for GNU Emacs on the Microsoft W32 API.
429ab54e 2 Copyright (C) 1986, 1988, 1993, 1994, 1996, 1998, 1999, 2001, 2002,
8cabe764
GM
3 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
ee78dc32
GV
5
6This file is part of GNU Emacs.
7
9ec0b715 8GNU Emacs is free software: you can redistribute it and/or modify
ee78dc32 9it under the terms of the GNU General Public License as published by
9ec0b715
GM
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
ee78dc32
GV
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
9ec0b715 19along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
ee78dc32 20
ee78dc32 21#include <config.h>
162d2499 22
7ab7006c 23#include <signal.h>
ee78dc32 24#include <stdio.h>
af41f8a8 25#include <mbstring.h>
7ab7006c 26
ee78dc32 27#include "lisp.h"
15d36dee 28#include "keyboard.h"
5ee707b8 29#include "keymap.h"
ee78dc32 30#include "frame.h"
7ab7006c 31#include "termhooks.h"
ee78dc32 32#include "window.h"
ee78dc32 33#include "blockinput.h"
fdc12c4d 34#include "buffer.h"
6915ded0 35#include "charset.h"
c949d9d0 36#include "character.h"
6915ded0 37#include "coding.h"
ee78dc32
GV
38
39/* This may include sys/types.h, and that somehow loses
40 if this is not done before the other system files. */
41#include "w32term.h"
42
43/* Load sys/types.h if not already loaded.
44 In some systems loading it twice is suicidal. */
45#ifndef makedev
46#include <sys/types.h>
47#endif
48
49#include "dispextern.h"
50
222456a1 51#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
162d2499 52
485015ca
GV
53/******************************************************************/
54/* Definitions copied from lwlib.h */
ee78dc32 55
485015ca
GV
56typedef void * XtPointer;
57typedef char Boolean;
58
162d2499
JR
59enum button_type
60{
61 BUTTON_TYPE_NONE,
62 BUTTON_TYPE_TOGGLE,
63 BUTTON_TYPE_RADIO
64};
c8869655 65
d1fffd1d
JR
66/* This structure is based on the one in ../lwlib/lwlib.h, modified
67 for Windows. */
485015ca 68typedef struct _widget_value
ee78dc32 69{
485015ca 70 /* name of widget */
1f06d367 71 Lisp_Object lname;
485015ca
GV
72 char* name;
73 /* value (meaning depend on widget type) */
74 char* value;
177c0ea7 75 /* keyboard equivalent. no implications for XtTranslations */
1f06d367 76 Lisp_Object lkey;
485015ca 77 char* key;
d1fffd1d
JR
78 /* Help string or nil if none.
79 GC finds this string through the frame's menu_bar_vector
80 or through menu_items. */
81 Lisp_Object help;
485015ca
GV
82 /* true if enabled */
83 Boolean enabled;
84 /* true if selected */
85 Boolean selected;
162d2499
JR
86 /* The type of a button. */
87 enum button_type button_type;
485015ca
GV
88 /* true if menu title */
89 Boolean title;
90#if 0
91 /* true if was edited (maintained by get_value) */
92 Boolean edited;
93 /* true if has changed (maintained by lw library) */
94 change_type change;
95 /* true if this widget itself has changed,
96 but not counting the other widgets found in the `next' field. */
97 change_type this_one_change;
98#endif
99 /* Contents of the sub-widgets, also selected slot for checkbox */
100 struct _widget_value* contents;
101 /* data passed to callback */
102 XtPointer call_data;
103 /* next one in the list */
104 struct _widget_value* next;
105#if 0
106 /* slot for the toolkit dependent part. Always initialize to NULL. */
107 void* toolkit_data;
108 /* tell us if we should free the toolkit data slot when freeing the
109 widget_value itself. */
110 Boolean free_toolkit_data;
111
112 /* we resource the widget_value structures; this points to the next
113 one on the free list if this one has been deallocated.
114 */
115 struct _widget_value *free_list;
116#endif
117} widget_value;
118
6ed09cf0
RS
119/* Local memory management */
120#define local_heap (GetProcessHeap ())
121#define local_alloc(n) (HeapAlloc (local_heap, HEAP_ZERO_MEMORY, (n)))
122#define local_free(p) (HeapFree (local_heap, 0, ((LPVOID) (p))))
123
124#define malloc_widget_value() ((widget_value *) local_alloc (sizeof (widget_value)))
125#define free_widget_value(wv) (local_free ((wv)))
485015ca
GV
126
127/******************************************************************/
128
485015ca
GV
129#ifndef TRUE
130#define TRUE 1
131#define FALSE 0
132#endif /* no TRUE */
133
b2a916a0 134HMENU current_popup_menu;
ace9b298 135
f60ae425 136void syms_of_w32menu ();
9785d95b 137void globals_of_w32menu ();
f60ae425
BK
138
139typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (
140 IN HMENU,
141 IN UINT,
142 IN BOOL,
1f06d367 143 IN OUT LPMENUITEMINFOA);
f60ae425
BK
144typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) (
145 IN HMENU,
146 IN UINT,
147 IN BOOL,
1f06d367 148 IN LPCMENUITEMINFOA);
f60ae425 149
1f06d367
JR
150GetMenuItemInfoA_Proc get_menu_item_info = NULL;
151SetMenuItemInfoA_Proc set_menu_item_info = NULL;
152AppendMenuW_Proc unicode_append_menu = NULL;
ace9b298 153
fdc12c4d
RS
154Lisp_Object Qdebug_on_next_call;
155
0e9ffc04
YM
156extern Lisp_Object Vmenu_updating_frame;
157
ee78dc32 158extern Lisp_Object Qmenu_bar;
485015ca
GV
159
160extern Lisp_Object QCtoggle, QCradio;
ee78dc32 161
fdc12c4d
RS
162extern Lisp_Object Voverriding_local_map;
163extern Lisp_Object Voverriding_local_map_menu_flag;
164
165extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
166
167extern Lisp_Object Qmenu_bar_update_hook;
168
31403b24 169void set_frame_menubar P_ ((FRAME_PTR, int, int));
014510b0 170
162d2499
JR
171static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
172 Lisp_Object, Lisp_Object, Lisp_Object,
173 Lisp_Object, Lisp_Object));
1c5acb8c 174#ifdef HAVE_DIALOGS
31403b24
JR
175static Lisp_Object w32_dialog_show P_ ((FRAME_PTR, int, Lisp_Object, char**));
176#else
177static int is_simple_dialog P_ ((Lisp_Object));
178static Lisp_Object simple_dialog_show P_ ((FRAME_PTR, Lisp_Object, Lisp_Object));
1c5acb8c 179#endif
31403b24
JR
180static Lisp_Object w32_menu_show P_ ((FRAME_PTR, int, int, int, int,
181 Lisp_Object, char **));
182
183static void keymap_panes P_ ((Lisp_Object *, int, int));
184static void single_keymap_panes P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
185 int, int));
186static void single_menu_item P_ ((Lisp_Object, Lisp_Object,
187 Lisp_Object *, int, int));
188static void list_of_panes P_ ((Lisp_Object));
189static void list_of_items P_ ((Lisp_Object));
190void w32_free_menu_strings P_((HWND));
485015ca
GV
191\f
192/* This holds a Lisp vector that holds the results of decoding
193 the keymaps or alist-of-alists that specify a menu.
194
195 It describes the panes and items within the panes.
196
197 Each pane is described by 3 elements in the vector:
198 t, the pane name, the pane's prefix key.
199 Then follow the pane's items, with 5 elements per item:
200 the item string, the enable flag, the item's value,
201 the definition, and the equivalent keyboard key's description string.
202
203 In some cases, multiple levels of menus may be described.
204 A single vector slot containing nil indicates the start of a submenu.
205 A single vector slot containing lambda indicates the end of a submenu.
206 The submenu follows a menu item which is the way to reach the submenu.
207
208 A single vector slot containing quote indicates that the
209 following items should appear on the right of a dialog box.
210
211 Using a Lisp vector to hold this information while we decode it
212 takes care of protecting all the data from GC. */
213
214#define MENU_ITEMS_PANE_NAME 1
215#define MENU_ITEMS_PANE_PREFIX 2
216#define MENU_ITEMS_PANE_LENGTH 3
217
162d2499
JR
218enum menu_item_idx
219{
220 MENU_ITEMS_ITEM_NAME = 0,
221 MENU_ITEMS_ITEM_ENABLE,
222 MENU_ITEMS_ITEM_VALUE,
223 MENU_ITEMS_ITEM_EQUIV_KEY,
224 MENU_ITEMS_ITEM_DEFINITION,
225 MENU_ITEMS_ITEM_TYPE,
226 MENU_ITEMS_ITEM_SELECTED,
227 MENU_ITEMS_ITEM_HELP,
228 MENU_ITEMS_ITEM_LENGTH
229};
485015ca
GV
230
231static Lisp_Object menu_items;
232
233/* Number of slots currently allocated in menu_items. */
234static int menu_items_allocated;
235
236/* This is the index in menu_items of the first empty slot. */
237static int menu_items_used;
238
239/* The number of panes currently recorded in menu_items,
240 excluding those within submenus. */
241static int menu_items_n_panes;
242
243/* Current depth within submenus. */
244static int menu_items_submenu_depth;
245
162d2499
JR
246static int next_menubar_widget_id;
247
485015ca
GV
248/* This is set nonzero after the user activates the menu bar, and set
249 to zero again after the menu bars are redisplayed by prepare_menu_bar.
250 While it is nonzero, all calls to set_frame_menubar go deep.
251
252 I don't understand why this is needed, but it does seem to be
253 needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
ee78dc32 254
485015ca
GV
255int pending_menu_activation;
256\f
257
258/* Return the frame whose ->output_data.w32->menubar_widget equals
162d2499 259 ID, or 0 if none. */
485015ca
GV
260
261static struct frame *
162d2499
JR
262menubar_id_to_frame (id)
263 HMENU id;
485015ca
GV
264{
265 Lisp_Object tail, frame;
266 FRAME_PTR f;
ee78dc32 267
8e50cc2d 268 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
485015ca 269 {
8e713be6 270 frame = XCAR (tail);
8e50cc2d 271 if (!FRAMEP (frame))
485015ca
GV
272 continue;
273 f = XFRAME (frame);
162d2499 274 if (!FRAME_WINDOW_P (f))
485015ca 275 continue;
162d2499 276 if (f->output_data.w32->menubar_widget == id)
485015ca
GV
277 return f;
278 }
279 return 0;
280}
281\f
ee78dc32
GV
282/* Initialize the menu_items structure if we haven't already done so.
283 Also mark it as currently empty. */
284
485015ca
GV
285static void
286init_menu_items ()
ee78dc32 287{
485015ca 288 if (NILP (menu_items))
ee78dc32 289 {
485015ca
GV
290 menu_items_allocated = 60;
291 menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
ee78dc32 292 }
485015ca
GV
293
294 menu_items_used = 0;
295 menu_items_n_panes = 0;
296 menu_items_submenu_depth = 0;
ee78dc32
GV
297}
298
485015ca
GV
299/* Call at the end of generating the data in menu_items.
300 This fills in the number of items in the last pane. */
ee78dc32 301
485015ca
GV
302static void
303finish_menu_items ()
ee78dc32 304{
ee78dc32 305}
014510b0
GV
306
307/* Call when finished using the data for the current menu
308 in menu_items. */
309
485015ca
GV
310static void
311discard_menu_items ()
014510b0 312{
485015ca
GV
313 /* Free the structure if it is especially large.
314 Otherwise, hold on to it, to save time. */
315 if (menu_items_allocated > 200)
014510b0 316 {
485015ca
GV
317 menu_items = Qnil;
318 menu_items_allocated = 0;
014510b0 319 }
014510b0
GV
320}
321
485015ca 322/* Make the menu_items vector twice as large. */
ee78dc32 323
485015ca
GV
324static void
325grow_menu_items ()
ee78dc32 326{
485015ca 327 menu_items_allocated *= 2;
71d00ce4 328 menu_items = larger_vector (menu_items, menu_items_allocated, Qnil);
ee78dc32
GV
329}
330
485015ca 331/* Begin a submenu. */
014510b0 332
485015ca
GV
333static void
334push_submenu_start ()
335{
336 if (menu_items_used + 1 > menu_items_allocated)
337 grow_menu_items ();
014510b0 338
0f71cdf2
JB
339 ASET (menu_items, menu_items_used, Qnil);
340 menu_items_used++;
485015ca 341 menu_items_submenu_depth++;
ee78dc32 342}
485015ca
GV
343
344/* End a submenu. */
345
346static void
347push_submenu_end ()
ee78dc32 348{
485015ca
GV
349 if (menu_items_used + 1 > menu_items_allocated)
350 grow_menu_items ();
ee78dc32 351
0f71cdf2
JB
352 ASET (menu_items, menu_items_used, Qlambda);
353 menu_items_used++;
485015ca 354 menu_items_submenu_depth--;
ee78dc32
GV
355}
356
485015ca 357/* Indicate boundary between left and right. */
ee78dc32 358
485015ca
GV
359static void
360push_left_right_boundary ()
ee78dc32 361{
485015ca
GV
362 if (menu_items_used + 1 > menu_items_allocated)
363 grow_menu_items ();
364
0f71cdf2
JB
365 ASET (menu_items, menu_items_used, Qquote);
366 menu_items_used++;
ee78dc32
GV
367}
368
2cd23960 369/* Start a new menu pane in menu_items.
485015ca 370 NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
ee78dc32 371
485015ca
GV
372static void
373push_menu_pane (name, prefix_vec)
374 Lisp_Object name, prefix_vec;
ee78dc32 375{
485015ca
GV
376 if (menu_items_used + MENU_ITEMS_PANE_LENGTH > menu_items_allocated)
377 grow_menu_items ();
378
379 if (menu_items_submenu_depth == 0)
380 menu_items_n_panes++;
0f71cdf2
JB
381 ASET (menu_items, menu_items_used, Qt); menu_items_used++;
382 ASET (menu_items, menu_items_used, name); menu_items_used++;
383 ASET (menu_items, menu_items_used, prefix_vec); menu_items_used++;
485015ca 384}
ee78dc32 385
162d2499
JR
386/* Push one menu item into the current pane. NAME is the string to
387 display. ENABLE if non-nil means this item can be selected. KEY
388 is the key generated by choosing this item, or nil if this item
389 doesn't really have a definition. DEF is the definition of this
390 item. EQUIV is the textual description of the keyboard equivalent
391 for this item (or nil if none). TYPE is the type of this menu
392 item, one of nil, `toggle' or `radio'. */
485015ca
GV
393
394static void
162d2499
JR
395push_menu_item (name, enable, key, def, equiv, type, selected, help)
396 Lisp_Object name, enable, key, def, equiv, type, selected, help;
485015ca
GV
397{
398 if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
399 grow_menu_items ();
400
0f71cdf2
JB
401 ASET (menu_items, menu_items_used, name); menu_items_used++;
402 ASET (menu_items, menu_items_used, enable); menu_items_used++;
403 ASET (menu_items, menu_items_used, key); menu_items_used++;
404 ASET (menu_items, menu_items_used, equiv); menu_items_used++;
405 ASET (menu_items, menu_items_used, def); menu_items_used++;
406 ASET (menu_items, menu_items_used, type); menu_items_used++;
407 ASET (menu_items, menu_items_used, selected); menu_items_used++;
408 ASET (menu_items, menu_items_used, help); menu_items_used++;
ee78dc32
GV
409}
410\f
411/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
412 and generate menu panes for them in menu_items.
413 If NOTREAL is nonzero,
414 don't bother really computing whether an item is enabled. */
415
485015ca
GV
416static void
417keymap_panes (keymaps, nmaps, notreal)
ee78dc32
GV
418 Lisp_Object *keymaps;
419 int nmaps;
420 int notreal;
421{
422 int mapno;
014510b0 423
485015ca 424 init_menu_items ();
014510b0 425
485015ca
GV
426 /* Loop over the given keymaps, making a pane for each map.
427 But don't make a pane that is empty--ignore that map instead.
428 P is the number of panes we have made so far. */
429 for (mapno = 0; mapno < nmaps; mapno++)
e5cd3d11 430 single_keymap_panes (keymaps[mapno],
5ee707b8 431 Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10);
ee78dc32 432
485015ca 433 finish_menu_items ();
ee78dc32
GV
434}
435
436/* This is a recursive subroutine of keymap_panes.
437 It handles one keymap, KEYMAP.
438 The other arguments are passed along
439 or point to local variables of the previous function.
485015ca
GV
440 If NOTREAL is nonzero, only check for equivalent key bindings, don't
441 evaluate expressions in menu items and don't make any menu.
ee78dc32 442
485015ca
GV
443 If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
444
445static void
446single_keymap_panes (keymap, pane_name, prefix, notreal, maxdepth)
ee78dc32
GV
447 Lisp_Object keymap;
448 Lisp_Object pane_name;
449 Lisp_Object prefix;
450 int notreal;
485015ca 451 int maxdepth;
ee78dc32 452{
485015ca
GV
453 Lisp_Object pending_maps = Qnil;
454 Lisp_Object tail, item;
455 struct gcpro gcpro1, gcpro2;
485015ca
GV
456
457 if (maxdepth <= 0)
458 return;
459
460 push_menu_pane (pane_name, prefix);
461
8e713be6 462 for (tail = keymap; CONSP (tail); tail = XCDR (tail))
ee78dc32 463 {
485015ca
GV
464 GCPRO2 (keymap, pending_maps);
465 /* Look at each key binding, and if it is a menu item add it
466 to this menu. */
8e713be6 467 item = XCAR (tail);
ee78dc32 468 if (CONSP (item))
8e713be6 469 single_menu_item (XCAR (item), XCDR (item),
37ad8b63 470 &pending_maps, notreal, maxdepth);
ee78dc32
GV
471 else if (VECTORP (item))
472 {
473 /* Loop over the char values represented in the vector. */
6ed09cf0 474 int len = ASIZE (item);
ee78dc32
GV
475 int c;
476 for (c = 0; c < len; c++)
477 {
478 Lisp_Object character;
479 XSETFASTINT (character, c);
6ed09cf0 480 single_menu_item (character, AREF (item, c),
37ad8b63 481 &pending_maps, notreal, maxdepth);
ee78dc32
GV
482 }
483 }
485015ca 484 UNGCPRO;
ee78dc32
GV
485 }
486
487 /* Process now any submenus which want to be panes at this level. */
488 while (!NILP (pending_maps))
489 {
490 Lisp_Object elt, eltcdr, string;
491 elt = Fcar (pending_maps);
8e713be6
KR
492 eltcdr = XCDR (elt);
493 string = XCAR (eltcdr);
ee78dc32 494 /* We no longer discard the @ from the beginning of the string here.
485015ca
GV
495 Instead, we do this in w32_menu_show. */
496 single_keymap_panes (Fcar (elt), string,
8e713be6 497 XCDR (eltcdr), notreal, maxdepth - 1);
485015ca
GV
498 pending_maps = Fcdr (pending_maps);
499 }
500}
501\f
502/* This is a subroutine of single_keymap_panes that handles one
503 keymap entry.
177c0ea7 504 KEY is a key in a keymap and ITEM is its binding.
485015ca
GV
505 PENDING_MAPS_PTR points to a list of keymaps waiting to be made into
506 separate panes.
507 If NOTREAL is nonzero, only check for equivalent key bindings, don't
508 evaluate expressions in menu items and don't make any menu.
37ad8b63 509 If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
485015ca
GV
510
511static void
37ad8b63 512single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth)
485015ca
GV
513 Lisp_Object key, item;
514 Lisp_Object *pending_maps_ptr;
515 int maxdepth, notreal;
485015ca 516{
162d2499 517 Lisp_Object map, item_string, enabled;
485015ca
GV
518 struct gcpro gcpro1, gcpro2;
519 int res;
177c0ea7 520
485015ca
GV
521 /* Parse the menu item and leave the result in item_properties. */
522 GCPRO2 (key, item);
523 res = parse_menu_item (item, notreal, 0);
524 UNGCPRO;
525 if (!res)
526 return; /* Not a menu item. */
527
6ed09cf0 528 map = AREF (item_properties, ITEM_PROPERTY_MAP);
177c0ea7 529
485015ca
GV
530 if (notreal)
531 {
532 /* We don't want to make a menu, just traverse the keymaps to
533 precompute equivalent key bindings. */
534 if (!NILP (map))
535 single_keymap_panes (map, Qnil, key, 1, maxdepth - 1);
536 return;
537 }
538
6ed09cf0 539 enabled = AREF (item_properties, ITEM_PROPERTY_ENABLE);
177c0ea7 540 item_string = AREF (item_properties, ITEM_PROPERTY_NAME);
485015ca 541
d5db4077 542 if (!NILP (map) && SREF (item_string, 0) == '@')
485015ca
GV
543 {
544 if (!NILP (enabled))
545 /* An enabled separate pane. Remember this to handle it later. */
546 *pending_maps_ptr = Fcons (Fcons (map, Fcons (item_string, key)),
547 *pending_maps_ptr);
548 return;
549 }
550
485015ca 551 push_menu_item (item_string, enabled, key,
6ed09cf0
RS
552 AREF (item_properties, ITEM_PROPERTY_DEF),
553 AREF (item_properties, ITEM_PROPERTY_KEYEQ),
554 AREF (item_properties, ITEM_PROPERTY_TYPE),
555 AREF (item_properties, ITEM_PROPERTY_SELECTED),
556 AREF (item_properties, ITEM_PROPERTY_HELP));
485015ca 557
485015ca
GV
558 /* Display a submenu using the toolkit. */
559 if (! (NILP (map) || NILP (enabled)))
560 {
561 push_submenu_start ();
562 single_keymap_panes (map, Qnil, key, 0, maxdepth - 1);
563 push_submenu_end ();
ee78dc32 564 }
ee78dc32
GV
565}
566\f
8e6208c5 567/* Push all the panes and items of a menu described by the
ee78dc32
GV
568 alist-of-alists MENU.
569 This handles old-fashioned calls to x-popup-menu. */
570
485015ca
GV
571static void
572list_of_panes (menu)
ee78dc32
GV
573 Lisp_Object menu;
574{
575 Lisp_Object tail;
014510b0 576
485015ca 577 init_menu_items ();
014510b0 578
99784d63 579 for (tail = menu; CONSP (tail); tail = XCDR (tail))
ee78dc32
GV
580 {
581 Lisp_Object elt, pane_name, pane_data;
99784d63 582 elt = XCAR (tail);
ee78dc32 583 pane_name = Fcar (elt);
b7826503 584 CHECK_STRING (pane_name);
485015ca 585 push_menu_pane (pane_name, Qnil);
ee78dc32 586 pane_data = Fcdr (elt);
b7826503 587 CHECK_CONS (pane_data);
485015ca 588 list_of_items (pane_data);
ee78dc32 589 }
485015ca
GV
590
591 finish_menu_items ();
ee78dc32
GV
592}
593
594/* Push the items in a single pane defined by the alist PANE. */
595
485015ca
GV
596static void
597list_of_items (pane)
ee78dc32
GV
598 Lisp_Object pane;
599{
600 Lisp_Object tail, item, item1;
ee78dc32 601
99784d63 602 for (tail = pane; CONSP (tail); tail = XCDR (tail))
ee78dc32 603 {
99784d63 604 item = XCAR (tail);
ee78dc32 605 if (STRINGP (item))
162d2499 606 push_menu_item (item, Qnil, Qnil, Qt, Qnil, Qnil, Qnil, Qnil);
ee78dc32 607 else if (NILP (item))
485015ca 608 push_left_right_boundary ();
ee78dc32
GV
609 else
610 {
b7826503 611 CHECK_CONS (item);
ee78dc32 612 item1 = Fcar (item);
b7826503 613 CHECK_STRING (item1);
162d2499 614 push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil, Qnil, Qnil, Qnil);
ee78dc32
GV
615 }
616 }
ee78dc32
GV
617}
618\f
485015ca 619DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
33f09670
JR
620 doc: /* Pop up a deck-of-cards menu and return user's selection.
621POSITION is a position specification. This is either a mouse button
622event or a list ((XOFFSET YOFFSET) WINDOW) where XOFFSET and YOFFSET
623are positions in pixels from the top left corner of WINDOW's frame
624\(WINDOW may be a frame object instead of a window). This controls the
625position of the center of the first line in the first pane of the
626menu, not the top left of the menu as a whole. If POSITION is t, it
627means to use the current mouse position.
628
629MENU is a specifier for a menu. For the simplest case, MENU is a keymap.
630The menu items come from key bindings that have a menu string as well as
631a definition; actually, the \"definition\" in such a key binding looks like
632\(STRING . REAL-DEFINITION). To give the menu a title, put a string into
633the keymap as a top-level element.
634
635If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.
636Otherwise, REAL-DEFINITION should be a valid key binding definition.
637
638You can also use a list of keymaps as MENU. Then each keymap makes a
639separate pane. When MENU is a keymap or a list of keymaps, the return
640value is a list of events.
641
642Alternatively, you can specify a menu of multiple panes with a list of
643the form (TITLE PANE1 PANE2...), where each pane is a list of
644form (TITLE ITEM1 ITEM2...).
645Each ITEM is normally a cons cell (STRING . VALUE); but a string can
646appear as an item--that makes a nonselectable line in the menu.
647With this form of menu, the return value is VALUE from the chosen item.
648
649If POSITION is nil, don't display the menu at all, just precalculate the
650cached information about equivalent key sequences. */)
485015ca
GV
651 (position, menu)
652 Lisp_Object position, menu;
ee78dc32 653{
ee78dc32 654 Lisp_Object keymap, tem;
b2123f81 655 int xpos = 0, ypos = 0;
ee78dc32
GV
656 Lisp_Object title;
657 char *error_name;
658 Lisp_Object selection;
b2123f81 659 FRAME_PTR f = NULL;
ee78dc32
GV
660 Lisp_Object x, y, window;
661 int keymaps = 0;
485015ca 662 int for_click = 0;
ee78dc32 663 struct gcpro gcpro1;
485015ca
GV
664
665#ifdef HAVE_MENUS
ee78dc32
GV
666 if (! NILP (position))
667 {
485015ca
GV
668 check_w32 ();
669
ee78dc32 670 /* Decode the first argument: find the window and the coordinates. */
ef06882d 671 if (EQ (position, Qt)
0b6bb670
JR
672 || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
673 || EQ (XCAR (position), Qtool_bar))))
ee78dc32
GV
674 {
675 /* Use the mouse's current position. */
162d2499 676 FRAME_PTR new_f = SELECTED_FRAME ();
ee78dc32 677 Lisp_Object bar_window;
162d2499 678 enum scroll_bar_part part;
ee78dc32 679 unsigned long time;
485015ca 680
7ab7006c
JR
681 if (FRAME_TERMINAL (new_f)->mouse_position_hook)
682 (*FRAME_TERMINAL (new_f)->mouse_position_hook) (&new_f, 1, &bar_window,
485015ca 683 &part, &x, &y, &time);
ee78dc32
GV
684 if (new_f != 0)
685 XSETFRAME (window, new_f);
686 else
687 {
688 window = selected_window;
689 XSETFASTINT (x, 0);
690 XSETFASTINT (y, 0);
691 }
692 }
693 else
694 {
695 tem = Fcar (position);
696 if (CONSP (tem))
697 {
698 window = Fcar (Fcdr (position));
699 x = Fcar (tem);
700 y = Fcar (Fcdr (tem));
701 }
702 else
703 {
485015ca
GV
704 for_click = 1;
705 tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
706 window = Fcar (tem); /* POSN_WINDOW (tem) */
ee78dc32
GV
707 tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
708 x = Fcar (tem);
709 y = Fcdr (tem);
ee78dc32
GV
710 }
711 }
485015ca 712
b7826503
PJ
713 CHECK_NUMBER (x);
714 CHECK_NUMBER (y);
ee78dc32
GV
715
716 /* Decode where to put the menu. */
485015ca 717
ee78dc32
GV
718 if (FRAMEP (window))
719 {
720 f = XFRAME (window);
ee78dc32
GV
721 xpos = 0;
722 ypos = 0;
723 }
724 else if (WINDOWP (window))
725 {
b7826503 726 CHECK_LIVE_WINDOW (window);
ee78dc32 727 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
485015ca 728
90022f5a
KS
729 xpos = WINDOW_LEFT_EDGE_X (XWINDOW (window));
730 ypos = WINDOW_TOP_EDGE_Y (XWINDOW (window));
ee78dc32
GV
731 }
732 else
733 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
734 but I don't want to make one now. */
b7826503 735 CHECK_WINDOW (window);
485015ca 736
ee78dc32
GV
737 xpos += XINT (x);
738 ypos += XINT (y);
c8869655
GV
739
740 XSETFRAME (Vmenu_updating_frame, f);
ee78dc32 741 }
c1d9dffd
JL
742 else
743 Vmenu_updating_frame = Qnil;
485015ca 744#endif /* HAVE_MENUS */
c8869655 745
ee78dc32
GV
746 title = Qnil;
747 GCPRO1 (title);
485015ca
GV
748
749 /* Decode the menu items from what was specified. */
750
02067692
SM
751 keymap = get_keymap (menu, 0, 0);
752 if (CONSP (keymap))
485015ca
GV
753 {
754 /* We were given a keymap. Extract menu info from the keymap. */
755 Lisp_Object prompt;
485015ca
GV
756
757 /* Extract the detailed info to make one pane. */
758 keymap_panes (&menu, 1, NILP (position));
759
760 /* Search for a string appearing directly as an element of the keymap.
761 That string is the title of the menu. */
5ee707b8 762 prompt = Fkeymap_prompt (keymap);
485015ca
GV
763 if (NILP (title) && !NILP (prompt))
764 title = prompt;
765
766 /* Make that be the pane title of the first pane. */
767 if (!NILP (prompt) && menu_items_n_panes >= 0)
6ed09cf0 768 ASET (menu_items, MENU_ITEMS_PANE_NAME, prompt);
485015ca
GV
769
770 keymaps = 1;
771 }
02067692 772 else if (CONSP (menu) && KEYMAPP (XCAR (menu)))
485015ca
GV
773 {
774 /* We were given a list of keymaps. */
775 int nmaps = XFASTINT (Flength (menu));
776 Lisp_Object *maps
777 = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
778 int i;
779
780 title = Qnil;
781
782 /* The first keymap that has a prompt string
783 supplies the menu title. */
784 for (tem = menu, i = 0; CONSP (tem); tem = Fcdr (tem))
785 {
786 Lisp_Object prompt;
787
02067692 788 maps[i++] = keymap = get_keymap (Fcar (tem), 1, 0);
485015ca 789
5ee707b8 790 prompt = Fkeymap_prompt (keymap);
485015ca
GV
791 if (NILP (title) && !NILP (prompt))
792 title = prompt;
793 }
794
795 /* Extract the detailed info to make one pane. */
796 keymap_panes (maps, nmaps, NILP (position));
797
798 /* Make the title be the pane title of the first pane. */
799 if (!NILP (title) && menu_items_n_panes >= 0)
6ed09cf0 800 ASET (menu_items, MENU_ITEMS_PANE_NAME, title);
485015ca
GV
801
802 keymaps = 1;
803 }
804 else
805 {
806 /* We were given an old-fashioned menu. */
807 title = Fcar (menu);
b7826503 808 CHECK_STRING (title);
485015ca
GV
809
810 list_of_panes (Fcdr (menu));
811
812 keymaps = 0;
813 }
177c0ea7 814
ee78dc32
GV
815 if (NILP (position))
816 {
485015ca 817 discard_menu_items ();
ee78dc32
GV
818 UNGCPRO;
819 return Qnil;
820 }
485015ca
GV
821
822#ifdef HAVE_MENUS
e7b14860
JR
823 /* If resources from a previous popup menu still exist, does nothing
824 until the `menu_free_timer' has freed them (see w32fns.c). This
825 can occur if you press ESC or click outside a menu without selecting
826 a menu item.
6ed09cf0
RS
827 */
828 if (current_popup_menu)
829 {
830 discard_menu_items ();
831 UNGCPRO;
832 return Qnil;
177c0ea7
JB
833 }
834
ee78dc32
GV
835 /* Display them in a menu. */
836 BLOCK_INPUT;
485015ca
GV
837
838 selection = w32_menu_show (f, xpos, ypos, for_click,
839 keymaps, title, &error_name);
ee78dc32 840 UNBLOCK_INPUT;
485015ca
GV
841
842 discard_menu_items ();
e7b14860 843
6ed09cf0 844#endif /* HAVE_MENUS */
485015ca 845
ee78dc32 846 UNGCPRO;
485015ca 847
ee78dc32
GV
848 if (error_name) error (error_name);
849 return selection;
850}
851
485015ca
GV
852#ifdef HAVE_MENUS
853
16b12668 854DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
33f09670
JR
855 doc: /* Pop up a dialog box and return user's selection.
856POSITION specifies which frame to use.
857This is normally a mouse button event or a window or frame.
858If POSITION is t, it means to use the frame the mouse is on.
859The dialog box appears in the middle of the specified frame.
860
861CONTENTS specifies the alternatives to display in the dialog box.
862It is a list of the form (TITLE ITEM1 ITEM2...).
863Each ITEM is a cons cell (STRING . VALUE).
864The return value is VALUE from the chosen item.
865
866An ITEM may also be just a string--that makes a nonselectable item.
867An ITEM may also be nil--that means to put all preceding items
868on the left of the dialog box and all following items on the right.
d23928c7
NR
869\(By default, approximately half appear on each side.)
870
871If HEADER is non-nil, the frame title for the box is "Information",
872otherwise it is "Question". */)
873 (position, contents, header)
874 Lisp_Object position, contents, header;
ee78dc32 875{
b2123f81 876 FRAME_PTR f = NULL;
ee78dc32 877 Lisp_Object window;
485015ca
GV
878
879 check_w32 ();
880
ee78dc32 881 /* Decode the first argument: find the window or frame to use. */
485015ca 882 if (EQ (position, Qt)
0b6bb670
JR
883 || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
884 || EQ (XCAR (position), Qtool_bar))))
ee78dc32 885 {
485015ca
GV
886#if 0 /* Using the frame the mouse is on may not be right. */
887 /* Use the mouse's current position. */
162d2499 888 FRAME_PTR new_f = SELECTED_FRAME ();
485015ca 889 Lisp_Object bar_window;
15d36dee 890 enum scroll_bar_part part;
485015ca
GV
891 unsigned long time;
892 Lisp_Object x, y;
893
894 (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
895
896 if (new_f != 0)
897 XSETFRAME (window, new_f);
898 else
ee78dc32 899 window = selected_window;
485015ca
GV
900#endif
901 window = selected_window;
ee78dc32
GV
902 }
903 else if (CONSP (position))
904 {
905 Lisp_Object tem;
906 tem = Fcar (position);
485015ca 907 if (CONSP (tem))
ee78dc32
GV
908 window = Fcar (Fcdr (position));
909 else
910 {
485015ca
GV
911 tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
912 window = Fcar (tem); /* POSN_WINDOW (tem) */
ee78dc32
GV
913 }
914 }
915 else if (WINDOWP (position) || FRAMEP (position))
916 window = position;
485015ca
GV
917 else
918 window = Qnil;
919
ee78dc32 920 /* Decode where to put the menu. */
485015ca 921
ee78dc32
GV
922 if (FRAMEP (window))
923 f = XFRAME (window);
924 else if (WINDOWP (window))
925 {
b7826503 926 CHECK_LIVE_WINDOW (window);
ee78dc32
GV
927 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
928 }
929 else
930 /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
931 but I don't want to make one now. */
b7826503 932 CHECK_WINDOW (window);
485015ca 933
162d2499 934#ifndef HAVE_DIALOGS
31403b24 935
ee78dc32 936 {
31403b24
JR
937 /* Handle simple Yes/No choices as MessageBox popups. */
938 if (is_simple_dialog (contents))
939 return simple_dialog_show (f, contents, header);
940 else
941 {
942 /* Display a menu with these alternatives
943 in the middle of frame F. */
944 Lisp_Object x, y, frame, newpos;
945 XSETFRAME (frame, f);
946 XSETINT (x, x_pixel_width (f) / 2);
947 XSETINT (y, x_pixel_height (f) / 2);
948 newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
949 return Fx_popup_menu (newpos,
950 Fcons (Fcar (contents), Fcons (contents, Qnil)));
951 }
ee78dc32 952 }
162d2499 953#else /* HAVE_DIALOGS */
ee78dc32
GV
954 {
955 Lisp_Object title;
956 char *error_name;
957 Lisp_Object selection;
958
959 /* Decode the dialog items from what was specified. */
960 title = Fcar (contents);
b7826503 961 CHECK_STRING (title);
ee78dc32
GV
962
963 list_of_panes (Fcons (contents, Qnil));
964
965 /* Display them in a dialog box. */
966 BLOCK_INPUT;
d23928c7 967 selection = w32_dialog_show (f, 0, title, header, &error_name);
ee78dc32
GV
968 UNBLOCK_INPUT;
969
970 discard_menu_items ();
971
972 if (error_name) error (error_name);
973 return selection;
974 }
162d2499 975#endif /* HAVE_DIALOGS */
ee78dc32
GV
976}
977
014510b0
GV
978/* Activate the menu bar of frame F.
979 This is called from keyboard.c when it gets the
3b8f9651 980 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
014510b0
GV
981
982 To activate the menu bar, we signal to the input thread that it can
983 return from the WM_INITMENU message, allowing the normal Windows
984 processing of the menus.
985
986 But first we recompute the menu bar contents (the whole tree).
987
988 This way we can safely execute Lisp code. */
177c0ea7 989
162d2499 990void
014510b0
GV
991x_activate_menubar (f)
992 FRAME_PTR f;
993{
994 set_frame_menubar (f, 0, 1);
995
996 /* Lock out further menubar changes while active. */
997 f->output_data.w32->menubar_active = 1;
998
999 /* Signal input thread to return from WM_INITMENU. */
1000 complete_deferred_msg (FRAME_W32_WINDOW (f), WM_INITMENU, 0);
1001}
1002
485015ca
GV
1003/* This callback is called from the menu bar pulldown menu
1004 when the user makes a selection.
1005 Figure out what the user chose
1006 and put the appropriate events into the keyboard buffer. */
1007
1008void
1009menubar_selection_callback (FRAME_PTR f, void * client_data)
ee78dc32 1010{
485015ca
GV
1011 Lisp_Object prefix, entry;
1012 Lisp_Object vector;
1013 Lisp_Object *subprefix_stack;
1014 int submenu_depth = 0;
ee78dc32 1015 int i;
fdc12c4d 1016
485015ca 1017 if (!f)
014510b0 1018 return;
fe5a0162 1019 entry = Qnil;
485015ca
GV
1020 subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof (Lisp_Object));
1021 vector = f->menu_bar_vector;
1022 prefix = Qnil;
1023 i = 0;
1024 while (i < f->menu_bar_items_used)
1025 {
6ed09cf0 1026 if (EQ (AREF (vector, i), Qnil))
485015ca
GV
1027 {
1028 subprefix_stack[submenu_depth++] = prefix;
1029 prefix = entry;
1030 i++;
1031 }
6ed09cf0 1032 else if (EQ (AREF (vector, i), Qlambda))
485015ca
GV
1033 {
1034 prefix = subprefix_stack[--submenu_depth];
1035 i++;
1036 }
6ed09cf0 1037 else if (EQ (AREF (vector, i), Qt))
485015ca 1038 {
6ed09cf0 1039 prefix = AREF (vector, i + MENU_ITEMS_PANE_PREFIX);
485015ca
GV
1040 i += MENU_ITEMS_PANE_LENGTH;
1041 }
1042 else
1043 {
6ed09cf0 1044 entry = AREF (vector, i + MENU_ITEMS_ITEM_VALUE);
485015ca
GV
1045 /* The EMACS_INT cast avoids a warning. There's no problem
1046 as long as pointers have enough bits to hold small integers. */
1047 if ((int) (EMACS_INT) client_data == i)
1048 {
1049 int j;
1050 struct input_event buf;
1051 Lisp_Object frame;
f456401b 1052 EVENT_INIT (buf);
014510b0 1053
485015ca 1054 XSETFRAME (frame, f);
20501278
GM
1055 buf.kind = MENU_BAR_EVENT;
1056 buf.frame_or_window = frame;
1057 buf.arg = frame;
485015ca 1058 kbd_buffer_store_event (&buf);
014510b0 1059
485015ca
GV
1060 for (j = 0; j < submenu_depth; j++)
1061 if (!NILP (subprefix_stack[j]))
1062 {
20501278
GM
1063 buf.kind = MENU_BAR_EVENT;
1064 buf.frame_or_window = frame;
1065 buf.arg = subprefix_stack[j];
485015ca
GV
1066 kbd_buffer_store_event (&buf);
1067 }
fdc12c4d 1068
485015ca
GV
1069 if (!NILP (prefix))
1070 {
20501278
GM
1071 buf.kind = MENU_BAR_EVENT;
1072 buf.frame_or_window = frame;
1073 buf.arg = prefix;
485015ca
GV
1074 kbd_buffer_store_event (&buf);
1075 }
fdc12c4d 1076
20501278
GM
1077 buf.kind = MENU_BAR_EVENT;
1078 buf.frame_or_window = frame;
1079 buf.arg = entry;
71f6b295
JR
1080 /* Free memory used by owner-drawn and help-echo strings. */
1081 w32_free_menu_strings (FRAME_W32_WINDOW (f));
b2a916a0
JR
1082 kbd_buffer_store_event (&buf);
1083
71f6b295 1084 f->output_data.w32->menubar_active = 0;
485015ca
GV
1085 return;
1086 }
1087 i += MENU_ITEMS_ITEM_LENGTH;
1088 }
014510b0 1089 }
71f6b295
JR
1090 /* Free memory used by owner-drawn and help-echo strings. */
1091 w32_free_menu_strings (FRAME_W32_WINDOW (f));
71f6b295 1092 f->output_data.w32->menubar_active = 0;
485015ca 1093}
014510b0 1094
485015ca 1095/* Allocate a widget_value, blocking input. */
014510b0 1096
485015ca
GV
1097widget_value *
1098xmalloc_widget_value ()
1099{
1100 widget_value *value;
014510b0 1101
fdc12c4d 1102 BLOCK_INPUT;
485015ca 1103 value = malloc_widget_value ();
ee78dc32 1104 UNBLOCK_INPUT;
485015ca
GV
1105
1106 return value;
ee78dc32
GV
1107}
1108
485015ca
GV
1109/* This recursively calls free_widget_value on the tree of widgets.
1110 It must free all data that was malloc'ed for these widget_values.
1111 In Emacs, many slots are pointers into the data of Lisp_Strings, and
1112 must be left alone. */
1113
1114void
1115free_menubar_widget_value_tree (wv)
1116 widget_value *wv;
ee78dc32 1117{
485015ca 1118 if (! wv) return;
177c0ea7 1119
485015ca
GV
1120 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
1121
1122 if (wv->contents && (wv->contents != (widget_value*)1))
1123 {
1124 free_menubar_widget_value_tree (wv->contents);
1125 wv->contents = (widget_value *) 0xDEADBEEF;
1126 }
1127 if (wv->next)
1128 {
1129 free_menubar_widget_value_tree (wv->next);
1130 wv->next = (widget_value *) 0xDEADBEEF;
1131 }
1132 BLOCK_INPUT;
1133 free_widget_value (wv);
ee78dc32
GV
1134 UNBLOCK_INPUT;
1135}
ee78dc32 1136\f
6ed09cf0 1137/* Set up data i menu_items for a menu bar item
485015ca
GV
1138 whose event type is ITEM_KEY (with string ITEM_NAME)
1139 and whose contents come from the list of keymaps MAPS. */
ee78dc32 1140
6ed09cf0
RS
1141static int
1142parse_single_submenu (item_key, item_name, maps)
485015ca 1143 Lisp_Object item_key, item_name, maps;
ee78dc32 1144{
485015ca
GV
1145 Lisp_Object length;
1146 int len;
1147 Lisp_Object *mapvec;
6ed09cf0 1148 int i;
485015ca 1149 int top_level_items = 0;
ee78dc32 1150
485015ca
GV
1151 length = Flength (maps);
1152 len = XINT (length);
ee78dc32 1153
485015ca
GV
1154 /* Convert the list MAPS into a vector MAPVEC. */
1155 mapvec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
1156 for (i = 0; i < len; i++)
ee78dc32 1157 {
485015ca
GV
1158 mapvec[i] = Fcar (maps);
1159 maps = Fcdr (maps);
ee78dc32
GV
1160 }
1161
485015ca
GV
1162 /* Loop over the given keymaps, making a pane for each map.
1163 But don't make a pane that is empty--ignore that map instead. */
1164 for (i = 0; i < len; i++)
ee78dc32 1165 {
485015ca 1166 if (SYMBOLP (mapvec[i])
02067692 1167 || (CONSP (mapvec[i]) && !KEYMAPP (mapvec[i])))
485015ca
GV
1168 {
1169 /* Here we have a command at top level in the menu bar
1170 as opposed to a submenu. */
1171 top_level_items = 1;
1172 push_menu_pane (Qnil, Qnil);
162d2499
JR
1173 push_menu_item (item_name, Qt, item_key, mapvec[i],
1174 Qnil, Qnil, Qnil, Qnil);
485015ca
GV
1175 }
1176 else
fe04b8c8
JR
1177 {
1178 Lisp_Object prompt;
1179 prompt = Fkeymap_prompt (mapvec[i]);
1180 single_keymap_panes (mapvec[i],
1181 !NILP (prompt) ? prompt : item_name,
1182 item_key, 0, 10);
1183 }
ee78dc32 1184 }
177c0ea7 1185
6ed09cf0
RS
1186 return top_level_items;
1187}
485015ca 1188
6ed09cf0
RS
1189
1190/* Create a tree of widget_value objects
1191 representing the panes and items
1192 in menu_items starting at index START, up to index END. */
1193
1194static widget_value *
1195digest_single_submenu (start, end, top_level_items)
fe04b8c8 1196 int start, end, top_level_items;
6ed09cf0
RS
1197{
1198 widget_value *wv, *prev_wv, *save_wv, *first_wv;
1199 int i;
1200 int submenu_depth = 0;
1201 widget_value **submenu_stack;
485015ca
GV
1202
1203 submenu_stack
1204 = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
1205 wv = xmalloc_widget_value ();
1206 wv->name = "menu";
1207 wv->value = 0;
1208 wv->enabled = 1;
162d2499 1209 wv->button_type = BUTTON_TYPE_NONE;
2d10309f 1210 wv->help = Qnil;
485015ca
GV
1211 first_wv = wv;
1212 save_wv = 0;
1213 prev_wv = 0;
177c0ea7 1214
fe04b8c8
JR
1215 /* Loop over all panes and items made by the preceding call
1216 to parse_single_submenu and construct a tree of widget_value objects.
1217 Ignore the panes and items used by previous calls to
1218 digest_single_submenu, even though those are also in menu_items. */
6ed09cf0
RS
1219 i = start;
1220 while (i < end)
ee78dc32 1221 {
6ed09cf0 1222 if (EQ (AREF (menu_items, i), Qnil))
ee78dc32 1223 {
485015ca
GV
1224 submenu_stack[submenu_depth++] = save_wv;
1225 save_wv = prev_wv;
1226 prev_wv = 0;
ee78dc32
GV
1227 i++;
1228 }
6ed09cf0 1229 else if (EQ (AREF (menu_items, i), Qlambda))
ee78dc32 1230 {
485015ca
GV
1231 prev_wv = save_wv;
1232 save_wv = submenu_stack[--submenu_depth];
ee78dc32
GV
1233 i++;
1234 }
6ed09cf0 1235 else if (EQ (AREF (menu_items, i), Qt)
485015ca
GV
1236 && submenu_depth != 0)
1237 i += MENU_ITEMS_PANE_LENGTH;
ee78dc32
GV
1238 /* Ignore a nil in the item list.
1239 It's meaningful only for dialog boxes. */
6ed09cf0 1240 else if (EQ (AREF (menu_items, i), Qquote))
485015ca 1241 i += 1;
6ed09cf0 1242 else if (EQ (AREF (menu_items, i), Qt))
485015ca
GV
1243 {
1244 /* Create a new pane. */
1245 Lisp_Object pane_name, prefix;
1246 char *pane_string;
29250851 1247
6ed09cf0
RS
1248 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
1249 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
29250851 1250
1f06d367 1251 if (STRINGP (pane_name))
29250851 1252 {
1f06d367
JR
1253 if (unicode_append_menu)
1254 /* Encode as UTF-8 for now. */
1255 pane_name = ENCODE_UTF_8 (pane_name);
1256 else if (STRING_MULTIBYTE (pane_name))
1257 pane_name = ENCODE_SYSTEM (pane_name);
1258
6ed09cf0 1259 ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
29250851 1260 }
1f06d367 1261
485015ca 1262 pane_string = (NILP (pane_name)
d5db4077 1263 ? "" : (char *) SDATA (pane_name));
485015ca
GV
1264 /* If there is just one top-level pane, put all its items directly
1265 under the top-level menu. */
1266 if (menu_items_n_panes == 1)
1267 pane_string = "";
1268
1269 /* If the pane has a meaningful name,
1270 make the pane a top-level menu item
1271 with its items as a submenu beneath it. */
1272 if (strcmp (pane_string, ""))
1273 {
1274 wv = xmalloc_widget_value ();
1275 if (save_wv)
1276 save_wv->next = wv;
1277 else
1278 first_wv->contents = wv;
1f06d367
JR
1279 wv->lname = pane_name;
1280 /* Set value to 1 so update_submenu_strings can handle '@' */
1281 wv->value = (char *) 1;
485015ca 1282 wv->enabled = 1;
162d2499 1283 wv->button_type = BUTTON_TYPE_NONE;
2d10309f 1284 wv->help = Qnil;
485015ca
GV
1285 }
1286 save_wv = wv;
1287 prev_wv = 0;
1288 i += MENU_ITEMS_PANE_LENGTH;
1289 }
1290 else
1291 {
1292 /* Create a new item within current pane. */
162d2499
JR
1293 Lisp_Object item_name, enable, descrip, def, type, selected;
1294 Lisp_Object help;
7d8e57da 1295
29250851
JR
1296 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
1297 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
1298 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
1299 def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
1300 type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
1301 selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
1302 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
162d2499 1303
1f06d367 1304 if (STRINGP (item_name))
29250851 1305 {
1f06d367
JR
1306 if (unicode_append_menu)
1307 item_name = ENCODE_UTF_8 (item_name);
1308 else if (STRING_MULTIBYTE (item_name))
1309 item_name = ENCODE_SYSTEM (item_name);
1310
6ed09cf0 1311 ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
29250851
JR
1312 }
1313
162d2499 1314 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
29250851
JR
1315 {
1316 descrip = ENCODE_SYSTEM (descrip);
6ed09cf0 1317 ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
29250851 1318 }
485015ca
GV
1319
1320 wv = xmalloc_widget_value ();
177c0ea7 1321 if (prev_wv)
485015ca
GV
1322 prev_wv->next = wv;
1323 else
1324 save_wv->contents = wv;
1325
1f06d367 1326 wv->lname = item_name;
485015ca 1327 if (!NILP (descrip))
1f06d367 1328 wv->lkey = descrip;
485015ca
GV
1329 wv->value = 0;
1330 /* The EMACS_INT cast avoids a warning. There's no problem
1331 as long as pointers have enough bits to hold small integers. */
1332 wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0);
1333 wv->enabled = !NILP (enable);
162d2499
JR
1334
1335 if (NILP (type))
1336 wv->button_type = BUTTON_TYPE_NONE;
1337 else if (EQ (type, QCradio))
1338 wv->button_type = BUTTON_TYPE_RADIO;
1339 else if (EQ (type, QCtoggle))
1340 wv->button_type = BUTTON_TYPE_TOGGLE;
1341 else
1342 abort ();
1343
1344 wv->selected = !NILP (selected);
d1fffd1d
JR
1345 if (!STRINGP (help))
1346 help = Qnil;
1347
1348 wv->help = help;
7d8e57da 1349
485015ca
GV
1350 prev_wv = wv;
1351
1352 i += MENU_ITEMS_ITEM_LENGTH;
1353 }
1354 }
1355
1356 /* If we have just one "menu item"
1357 that was originally a button, return it by itself. */
1358 if (top_level_items && first_wv->contents && first_wv->contents->next == 0)
1359 {
1360 wv = first_wv->contents;
1361 free_widget_value (first_wv);
1362 return wv;
1363 }
1364
1365 return first_wv;
1366}
1f06d367
JR
1367
1368
1369/* Walk through the widget_value tree starting at FIRST_WV and update
1370 the char * pointers from the corresponding lisp values.
1371 We do this after building the whole tree, since GC may happen while the
1372 tree is constructed, and small strings are relocated. So we must wait
1373 until no GC can happen before storing pointers into lisp values. */
1374static void
1375update_submenu_strings (first_wv)
1376 widget_value *first_wv;
1377{
1378 widget_value *wv;
1379
1380 for (wv = first_wv; wv; wv = wv->next)
1381 {
1382 if (wv->lname && ! NILP (wv->lname))
1383 {
1384 wv->name = SDATA (wv->lname);
1385
1386 /* Ignore the @ that means "separate pane".
1387 This is a kludge, but this isn't worth more time. */
1388 if (wv->value == (char *)1)
1389 {
1390 if (wv->name[0] == '@')
1391 wv->name++;
1392 wv->value = 0;
1393 }
1394 }
1395
1396 if (wv->lkey && ! NILP (wv->lkey))
1397 wv->key = SDATA (wv->lkey);
1398
1399 if (wv->contents)
1400 update_submenu_strings (wv->contents);
1401 }
1402}
1403
485015ca
GV
1404\f
1405/* Set the contents of the menubar widgets of frame F.
1406 The argument FIRST_TIME is currently ignored;
1407 it is set the first time this is called, from initialize_frame_menubar. */
1408
1409void
1410set_frame_menubar (f, first_time, deep_p)
1411 FRAME_PTR f;
1412 int first_time;
1413 int deep_p;
1414{
1415 HMENU menubar_widget = f->output_data.w32->menubar_widget;
162d2499 1416 Lisp_Object items;
485015ca 1417 widget_value *wv, *first_wv, *prev_wv = 0;
6ed09cf0
RS
1418 int i, last_i;
1419 int *submenu_start, *submenu_end;
fe04b8c8 1420 int *submenu_top_level_items, *submenu_n_panes;
485015ca
GV
1421
1422 /* We must not change the menubar when actually in use. */
1423 if (f->output_data.w32->menubar_active)
1424 return;
1425
1426 XSETFRAME (Vmenu_updating_frame, f);
1427
1428 if (! menubar_widget)
1429 deep_p = 1;
1430 else if (pending_menu_activation && !deep_p)
1431 deep_p = 1;
1432
485015ca
GV
1433 if (deep_p)
1434 {
1435 /* Make a widget-value tree representing the entire menu trees. */
1436
1437 struct buffer *prev = current_buffer;
1438 Lisp_Object buffer;
aed13378 1439 int specpdl_count = SPECPDL_INDEX ();
485015ca
GV
1440 int previous_menu_items_used = f->menu_bar_items_used;
1441 Lisp_Object *previous_items
1442 = (Lisp_Object *) alloca (previous_menu_items_used
1443 * sizeof (Lisp_Object));
1444
1445 /* If we are making a new widget, its contents are empty,
1446 do always reinitialize them. */
1447 if (! menubar_widget)
1448 previous_menu_items_used = 0;
1449
1450 buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
1451 specbind (Qinhibit_quit, Qt);
1452 /* Don't let the debugger step into this code
1453 because it is not reentrant. */
1454 specbind (Qdebug_on_next_call, Qnil);
1455
89f2614d
KS
1456 record_unwind_save_match_data ();
1457
485015ca
GV
1458 if (NILP (Voverriding_local_map_menu_flag))
1459 {
1460 specbind (Qoverriding_terminal_local_map, Qnil);
1461 specbind (Qoverriding_local_map, Qnil);
1462 }
1463
1464 set_buffer_internal_1 (XBUFFER (buffer));
1465
1466 /* Run the Lucid hook. */
c53b6500 1467 safe_run_hooks (Qactivate_menubar_hook);
485015ca
GV
1468 /* If it has changed current-menubar from previous value,
1469 really recompute the menubar from the value. */
1470 if (! NILP (Vlucid_menu_bar_dirty_flag))
1471 call0 (Qrecompute_lucid_menubar);
1472 safe_run_hooks (Qmenu_bar_update_hook);
1473 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
1474
1475 items = FRAME_MENU_BAR_ITEMS (f);
1476
485015ca 1477 /* Save the frame's previous menu bar contents data. */
c30dce3d
AI
1478 if (previous_menu_items_used)
1479 bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
1480 previous_menu_items_used * sizeof (Lisp_Object));
485015ca 1481
6ed09cf0
RS
1482 /* Fill in menu_items with the current menu bar contents.
1483 This can evaluate Lisp code. */
485015ca 1484 menu_items = f->menu_bar_vector;
c30dce3d 1485 menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
6ed09cf0
RS
1486 submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
1487 submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
fe04b8c8 1488 submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int));
6ed09cf0
RS
1489 submenu_top_level_items
1490 = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
485015ca 1491 init_menu_items ();
6ed09cf0 1492 for (i = 0; i < ASIZE (items); i += 4)
485015ca
GV
1493 {
1494 Lisp_Object key, string, maps;
1495
6ed09cf0
RS
1496 last_i = i;
1497
1498 key = AREF (items, i);
1499 string = AREF (items, i + 1);
1500 maps = AREF (items, i + 2);
485015ca
GV
1501 if (NILP (string))
1502 break;
1503
6ed09cf0
RS
1504 submenu_start[i] = menu_items_used;
1505
1506 menu_items_n_panes = 0;
1507 submenu_top_level_items[i]
1508 = parse_single_submenu (key, string, maps);
fe04b8c8 1509 submenu_n_panes[i] = menu_items_n_panes;
6ed09cf0
RS
1510
1511 submenu_end[i] = menu_items_used;
1512 }
1513
1514 finish_menu_items ();
1515
1516 /* Convert menu_items into widget_value trees
1517 to display the menu. This cannot evaluate Lisp code. */
1518
1519 wv = xmalloc_widget_value ();
1520 wv->name = "menubar";
1521 wv->value = 0;
1522 wv->enabled = 1;
1523 wv->button_type = BUTTON_TYPE_NONE;
1524 wv->help = Qnil;
1525 first_wv = wv;
1526
1527 for (i = 0; i < last_i; i += 4)
1528 {
fe04b8c8 1529 menu_items_n_panes = submenu_n_panes[i];
6ed09cf0
RS
1530 wv = digest_single_submenu (submenu_start[i], submenu_end[i],
1531 submenu_top_level_items[i]);
177c0ea7 1532 if (prev_wv)
485015ca
GV
1533 prev_wv->next = wv;
1534 else
1535 first_wv->contents = wv;
1536 /* Don't set wv->name here; GC during the loop might relocate it. */
1537 wv->enabled = 1;
162d2499 1538 wv->button_type = BUTTON_TYPE_NONE;
485015ca
GV
1539 prev_wv = wv;
1540 }
1541
485015ca
GV
1542 set_buffer_internal_1 (prev);
1543 unbind_to (specpdl_count, Qnil);
1544
1545 /* If there has been no change in the Lisp-level contents
1546 of the menu bar, skip redisplaying it. Just exit. */
1547
1548 for (i = 0; i < previous_menu_items_used; i++)
1549 if (menu_items_used == i
6ed09cf0 1550 || (!EQ (previous_items[i], AREF (menu_items, i))))
485015ca
GV
1551 break;
1552 if (i == menu_items_used && i == previous_menu_items_used && i != 0)
1553 {
1554 free_menubar_widget_value_tree (first_wv);
1555 menu_items = Qnil;
1556
1557 return;
1558 }
1559
1560 /* Now GC cannot happen during the lifetime of the widget_value,
ace9b298
JR
1561 so it's safe to store data from a Lisp_String, as long as
1562 local copies are made when the actual menu is created.
1563 Windows takes care of this for normal string items, but
1564 not for owner-drawn items or additional item-info. */
485015ca 1565 wv = first_wv->contents;
6ed09cf0 1566 for (i = 0; i < ASIZE (items); i += 4)
485015ca
GV
1567 {
1568 Lisp_Object string;
6ed09cf0 1569 string = AREF (items, i + 1);
485015ca
GV
1570 if (NILP (string))
1571 break;
d5db4077 1572 wv->name = (char *) SDATA (string);
1f06d367 1573 update_submenu_strings (wv->contents);
485015ca
GV
1574 wv = wv->next;
1575 }
1576
1577 f->menu_bar_vector = menu_items;
1578 f->menu_bar_items_used = menu_items_used;
1579 menu_items = Qnil;
1580 }
1581 else
1582 {
1583 /* Make a widget-value tree containing
162d2499 1584 just the top level menu bar strings. */
485015ca 1585
6ed09cf0
RS
1586 wv = xmalloc_widget_value ();
1587 wv->name = "menubar";
1588 wv->value = 0;
1589 wv->enabled = 1;
1590 wv->button_type = BUTTON_TYPE_NONE;
1591 wv->help = Qnil;
1592 first_wv = wv;
1593
485015ca 1594 items = FRAME_MENU_BAR_ITEMS (f);
6ed09cf0 1595 for (i = 0; i < ASIZE (items); i += 4)
485015ca
GV
1596 {
1597 Lisp_Object string;
1598
6ed09cf0 1599 string = AREF (items, i + 1);
485015ca
GV
1600 if (NILP (string))
1601 break;
1602
1603 wv = xmalloc_widget_value ();
d5db4077 1604 wv->name = (char *) SDATA (string);
485015ca
GV
1605 wv->value = 0;
1606 wv->enabled = 1;
162d2499 1607 wv->button_type = BUTTON_TYPE_NONE;
2d10309f 1608 wv->help = Qnil;
485015ca
GV
1609 /* This prevents lwlib from assuming this
1610 menu item is really supposed to be empty. */
1611 /* The EMACS_INT cast avoids a warning.
1612 This value just has to be different from small integers. */
1613 wv->call_data = (void *) (EMACS_INT) (-1);
1614
177c0ea7 1615 if (prev_wv)
485015ca
GV
1616 prev_wv->next = wv;
1617 else
1618 first_wv->contents = wv;
1619 prev_wv = wv;
1620 }
1621
162d2499
JR
1622 /* Forget what we thought we knew about what is in the
1623 detailed contents of the menu bar menus.
1624 Changing the top level always destroys the contents. */
1625 f->menu_bar_items_used = 0;
485015ca
GV
1626 }
1627
1628 /* Create or update the menu bar widget. */
ee78dc32 1629
485015ca 1630 BLOCK_INPUT;
ee78dc32 1631
485015ca
GV
1632 if (menubar_widget)
1633 {
1634 /* Empty current menubar, rather than creating a fresh one. */
1635 while (DeleteMenu (menubar_widget, 0, MF_BYPOSITION))
1636 ;
1637 }
1638 else
1639 {
1640 menubar_widget = CreateMenu ();
1641 }
1642 fill_in_menu (menubar_widget, first_wv->contents);
ee78dc32 1643
485015ca 1644 free_menubar_widget_value_tree (first_wv);
ee78dc32 1645
485015ca
GV
1646 {
1647 HMENU old_widget = f->output_data.w32->menubar_widget;
ee78dc32 1648
485015ca
GV
1649 f->output_data.w32->menubar_widget = menubar_widget;
1650 SetMenu (FRAME_W32_WINDOW (f), f->output_data.w32->menubar_widget);
177c0ea7 1651 /* Causes flicker when menu bar is updated
485015ca 1652 DrawMenuBar (FRAME_W32_WINDOW (f)); */
ee78dc32 1653
485015ca
GV
1654 /* Force the window size to be recomputed so that the frame's text
1655 area remains the same, if menubar has just been created. */
1656 if (old_widget == NULL)
90022f5a 1657 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
ee78dc32 1658 }
485015ca
GV
1659
1660 UNBLOCK_INPUT;
ee78dc32
GV
1661}
1662
485015ca
GV
1663/* Called from Fx_create_frame to create the initial menubar of a frame
1664 before it is mapped, so that the window is mapped with the menubar already
1665 there instead of us tacking it on later and thrashing the window after it
1666 is visible. */
1667
1668void
1669initialize_frame_menubar (f)
1670 FRAME_PTR f;
1671{
1672 /* This function is called before the first chance to redisplay
1673 the frame. It has to be, so the frame will have the right size. */
1674 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
1675 set_frame_menubar (f, 1, 1);
ee78dc32
GV
1676}
1677
485015ca
GV
1678/* Get rid of the menu bar of frame F, and free its storage.
1679 This is used when deleting a frame, and when turning off the menu bar. */
1680
1681void
1682free_frame_menubar (f)
1683 FRAME_PTR f;
1684{
1685 BLOCK_INPUT;
1686
1687 {
1688 HMENU old = GetMenu (FRAME_W32_WINDOW (f));
1689 SetMenu (FRAME_W32_WINDOW (f), NULL);
1690 f->output_data.w32->menubar_widget = NULL;
1691 DestroyMenu (old);
1692 }
29250851 1693
485015ca
GV
1694 UNBLOCK_INPUT;
1695}
ee78dc32 1696
485015ca
GV
1697\f
1698/* w32_menu_show actually displays a menu using the panes and items in
1699 menu_items and returns the value selected from it; we assume input
1700 is blocked by the caller. */
ee78dc32
GV
1701
1702/* F is the frame the menu is for.
1703 X and Y are the frame-relative specified position,
1704 relative to the inside upper left corner of the frame F.
485015ca 1705 FOR_CLICK is nonzero if this menu was invoked for a mouse click.
ee78dc32 1706 KEYMAPS is 1 if this menu was specified with keymaps;
485015ca
GV
1707 in that case, we return a list containing the chosen item's value
1708 and perhaps also the pane's prefix.
ee78dc32
GV
1709 TITLE is the specified menu title.
1710 ERROR is a place to store an error message string in case of failure.
1711 (We return nil on failure, but the value doesn't actually matter.) */
1712
485015ca
GV
1713static Lisp_Object
1714w32_menu_show (f, x, y, for_click, keymaps, title, error)
ee78dc32
GV
1715 FRAME_PTR f;
1716 int x;
1717 int y;
485015ca
GV
1718 int for_click;
1719 int keymaps;
1720 Lisp_Object title;
ee78dc32
GV
1721 char **error;
1722{
485015ca
GV
1723 int i;
1724 int menu_item_selection;
1725 HMENU menu;
ee78dc32 1726 POINT pos;
485015ca
GV
1727 widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
1728 widget_value **submenu_stack
1729 = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
1730 Lisp_Object *subprefix_stack
1731 = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
1732 int submenu_depth = 0;
485015ca 1733 int first_pane;
485015ca 1734
ee78dc32 1735 *error = NULL;
485015ca
GV
1736
1737 if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
ee78dc32
GV
1738 {
1739 *error = "Empty menu";
1740 return Qnil;
1741 }
485015ca
GV
1742
1743 /* Create a tree of widget_value objects
1744 representing the panes and their items. */
1745 wv = xmalloc_widget_value ();
1746 wv->name = "menu";
1747 wv->value = 0;
1748 wv->enabled = 1;
162d2499 1749 wv->button_type = BUTTON_TYPE_NONE;
e6bb685b 1750 wv->help = Qnil;
485015ca
GV
1751 first_wv = wv;
1752 first_pane = 1;
177c0ea7 1753
485015ca
GV
1754 /* Loop over all panes and items, filling in the tree. */
1755 i = 0;
1756 while (i < menu_items_used)
1757 {
6ed09cf0 1758 if (EQ (AREF (menu_items, i), Qnil))
485015ca
GV
1759 {
1760 submenu_stack[submenu_depth++] = save_wv;
1761 save_wv = prev_wv;
1762 prev_wv = 0;
1763 first_pane = 1;
1764 i++;
1765 }
6ed09cf0 1766 else if (EQ (AREF (menu_items, i), Qlambda))
485015ca
GV
1767 {
1768 prev_wv = save_wv;
1769 save_wv = submenu_stack[--submenu_depth];
1770 first_pane = 0;
1771 i++;
1772 }
6ed09cf0 1773 else if (EQ (AREF (menu_items, i), Qt)
485015ca
GV
1774 && submenu_depth != 0)
1775 i += MENU_ITEMS_PANE_LENGTH;
1776 /* Ignore a nil in the item list.
1777 It's meaningful only for dialog boxes. */
6ed09cf0 1778 else if (EQ (AREF (menu_items, i), Qquote))
485015ca 1779 i += 1;
6ed09cf0 1780 else if (EQ (AREF (menu_items, i), Qt))
485015ca
GV
1781 {
1782 /* Create a new pane. */
1783 Lisp_Object pane_name, prefix;
1784 char *pane_string;
29250851
JR
1785 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
1786 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
1f06d367
JR
1787
1788 if (STRINGP (pane_name))
29250851 1789 {
1f06d367
JR
1790 if (unicode_append_menu)
1791 pane_name = ENCODE_UTF_8 (pane_name);
1792 else if (STRING_MULTIBYTE (pane_name))
1793 pane_name = ENCODE_SYSTEM (pane_name);
1794
6ed09cf0 1795 ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
29250851 1796 }
1f06d367 1797
485015ca 1798 pane_string = (NILP (pane_name)
d5db4077 1799 ? "" : (char *) SDATA (pane_name));
485015ca
GV
1800 /* If there is just one top-level pane, put all its items directly
1801 under the top-level menu. */
1802 if (menu_items_n_panes == 1)
1803 pane_string = "";
1804
1805 /* If the pane has a meaningful name,
1806 make the pane a top-level menu item
1807 with its items as a submenu beneath it. */
1808 if (!keymaps && strcmp (pane_string, ""))
1809 {
1810 wv = xmalloc_widget_value ();
1811 if (save_wv)
1812 save_wv->next = wv;
1813 else
1814 first_wv->contents = wv;
1815 wv->name = pane_string;
1816 if (keymaps && !NILP (prefix))
1817 wv->name++;
1818 wv->value = 0;
1819 wv->enabled = 1;
162d2499 1820 wv->button_type = BUTTON_TYPE_NONE;
2d10309f 1821 wv->help = Qnil;
485015ca
GV
1822 save_wv = wv;
1823 prev_wv = 0;
1824 }
1825 else if (first_pane)
1826 {
1827 save_wv = wv;
1828 prev_wv = 0;
1829 }
1830 first_pane = 0;
1831 i += MENU_ITEMS_PANE_LENGTH;
1832 }
1833 else
1834 {
1835 /* Create a new item within current pane. */
b65a2f83 1836 Lisp_Object item_name, enable, descrip, def, type, selected, help;
b65a2f83 1837
29250851
JR
1838 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
1839 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
1840 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
1841 def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
1842 type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
1843 selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
1844 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
162d2499 1845
1f06d367 1846 if (STRINGP (item_name))
29250851 1847 {
1f06d367
JR
1848 if (unicode_append_menu)
1849 item_name = ENCODE_UTF_8 (item_name);
1850 else if (STRING_MULTIBYTE (item_name))
1851 item_name = ENCODE_SYSTEM (item_name);
1852
6ed09cf0 1853 ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
29250851 1854 }
1f06d367
JR
1855
1856 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
29250851
JR
1857 {
1858 descrip = ENCODE_SYSTEM (descrip);
6ed09cf0 1859 ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
29250851 1860 }
485015ca
GV
1861
1862 wv = xmalloc_widget_value ();
177c0ea7 1863 if (prev_wv)
485015ca 1864 prev_wv->next = wv;
177c0ea7 1865 else
485015ca 1866 save_wv->contents = wv;
d5db4077 1867 wv->name = (char *) SDATA (item_name);
485015ca 1868 if (!NILP (descrip))
d5db4077 1869 wv->key = (char *) SDATA (descrip);
485015ca
GV
1870 wv->value = 0;
1871 /* Use the contents index as call_data, since we are
2cd23960 1872 restricted to 16-bits. */
e59fe83b 1873 wv->call_data = !NILP (def) ? (void *) (EMACS_INT) i : 0;
485015ca 1874 wv->enabled = !NILP (enable);
162d2499
JR
1875
1876 if (NILP (type))
1877 wv->button_type = BUTTON_TYPE_NONE;
1878 else if (EQ (type, QCtoggle))
1879 wv->button_type = BUTTON_TYPE_TOGGLE;
1880 else if (EQ (type, QCradio))
1881 wv->button_type = BUTTON_TYPE_RADIO;
1882 else
1883 abort ();
1884
1885 wv->selected = !NILP (selected);
d1fffd1d
JR
1886 if (!STRINGP (help))
1887 help = Qnil;
1888
1889 wv->help = help;
7d8e57da 1890
485015ca
GV
1891 prev_wv = wv;
1892
1893 i += MENU_ITEMS_ITEM_LENGTH;
1894 }
1895 }
1896
1897 /* Deal with the title, if it is non-nil. */
1898 if (!NILP (title))
1899 {
1900 widget_value *wv_title = xmalloc_widget_value ();
1901 widget_value *wv_sep = xmalloc_widget_value ();
1902
1903 /* Maybe replace this separator with a bitmap or owner-draw item
1904 so that it looks better. Having two separators looks odd. */
1905 wv_sep->name = "--";
1906 wv_sep->next = first_wv->contents;
2d10309f 1907 wv_sep->help = Qnil;
485015ca 1908
1f06d367
JR
1909 if (unicode_append_menu)
1910 title = ENCODE_UTF_8 (title);
1911 else if (STRING_MULTIBYTE (title))
6915ded0 1912 title = ENCODE_SYSTEM (title);
1f06d367 1913
d5db4077 1914 wv_title->name = (char *) SDATA (title);
02067692
SM
1915 wv_title->enabled = TRUE;
1916 wv_title->title = TRUE;
162d2499 1917 wv_title->button_type = BUTTON_TYPE_NONE;
2d10309f 1918 wv_title->help = Qnil;
485015ca
GV
1919 wv_title->next = wv_sep;
1920 first_wv->contents = wv_title;
1921 }
1922
1923 /* Actually create the menu. */
ace9b298 1924 current_popup_menu = menu = CreatePopupMenu ();
485015ca 1925 fill_in_menu (menu, first_wv->contents);
162d2499 1926
485015ca 1927 /* Adjust coordinates to be root-window-relative. */
ee78dc32
GV
1928 pos.x = x;
1929 pos.y = y;
fbd6baed 1930 ClientToScreen (FRAME_W32_WINDOW (f), &pos);
485015ca 1931
485015ca
GV
1932 /* No selection has been chosen yet. */
1933 menu_item_selection = 0;
014510b0 1934
ee78dc32 1935 /* Display the menu. */
177c0ea7 1936 menu_item_selection = SendMessage (FRAME_W32_WINDOW (f),
485015ca
GV
1937 WM_EMACS_TRACKPOPUPMENU,
1938 (WPARAM)menu, (LPARAM)&pos);
014510b0
GV
1939
1940 /* Clean up extraneous mouse events which might have been generated
1941 during the call. */
1942 discard_mouse_events ();
1943
86fb1a79
JR
1944 /* Free the widget_value objects we used to specify the contents. */
1945 free_menubar_widget_value_tree (first_wv);
1946
485015ca
GV
1947 DestroyMenu (menu);
1948
563cd4c0
JR
1949 /* Free the owner-drawn and help-echo menu strings. */
1950 w32_free_menu_strings (FRAME_W32_WINDOW (f));
5339f50c 1951 f->output_data.w32->menubar_active = 0;
563cd4c0 1952
ee78dc32
GV
1953 /* Find the selected item, and its pane, to return
1954 the proper value. */
485015ca 1955 if (menu_item_selection != 0)
ee78dc32 1956 {
485015ca
GV
1957 Lisp_Object prefix, entry;
1958
fe5a0162 1959 prefix = entry = Qnil;
485015ca
GV
1960 i = 0;
1961 while (i < menu_items_used)
1962 {
6ed09cf0 1963 if (EQ (AREF (menu_items, i), Qnil))
485015ca
GV
1964 {
1965 subprefix_stack[submenu_depth++] = prefix;
1966 prefix = entry;
1967 i++;
1968 }
6ed09cf0 1969 else if (EQ (AREF (menu_items, i), Qlambda))
485015ca
GV
1970 {
1971 prefix = subprefix_stack[--submenu_depth];
1972 i++;
1973 }
6ed09cf0 1974 else if (EQ (AREF (menu_items, i), Qt))
485015ca 1975 {
6ed09cf0 1976 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
485015ca
GV
1977 i += MENU_ITEMS_PANE_LENGTH;
1978 }
1979 /* Ignore a nil in the item list.
1980 It's meaningful only for dialog boxes. */
6ed09cf0 1981 else if (EQ (AREF (menu_items, i), Qquote))
485015ca
GV
1982 i += 1;
1983 else
1984 {
6ed09cf0 1985 entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
485015ca
GV
1986 if (menu_item_selection == i)
1987 {
1988 if (keymaps != 0)
1989 {
1990 int j;
1991
1992 entry = Fcons (entry, Qnil);
1993 if (!NILP (prefix))
1994 entry = Fcons (prefix, entry);
1995 for (j = submenu_depth - 1; j >= 0; j--)
1996 if (!NILP (subprefix_stack[j]))
1997 entry = Fcons (subprefix_stack[j], entry);
1998 }
1999 return entry;
2000 }
2001 i += MENU_ITEMS_ITEM_LENGTH;
2002 }
2003 }
ee78dc32 2004 }
f3e0a6de
JR
2005 else if (!for_click)
2006 /* Make "Cancel" equivalent to C-g. */
2007 Fsignal (Qquit, Qnil);
014510b0 2008
ee78dc32
GV
2009 return Qnil;
2010}
485015ca 2011\f
ee78dc32 2012
ace9b298 2013#ifdef HAVE_DIALOGS
31403b24
JR
2014/* TODO: On Windows, there are two ways of defining a dialog.
2015
2016 1. Create a predefined dialog resource and include it in nt/emacs.rc.
2017 Using this method, we could then set the titles and make unneeded
2018 buttons invisible before displaying the dialog. Everything would
2019 be a fixed size though, so there is a risk that text does not
2020 fit on a button.
2021 2. Create the dialog template in memory on the fly. This allows us
2022 to size the dialog and buttons dynamically, probably giving more
2023 natural looking results for dialogs with few buttons, and eliminating
2024 the problem of text overflowing the buttons. But the API for this is
2025 quite complex - structures have to be allocated in particular ways,
2026 text content is tacked onto the end of structures in variable length
2027 arrays with further structures tacked on after these, there are
2028 certain alignment requirements for all this, and we have to
2029 measure all the text and convert to "dialog coordinates" to figure
2030 out how big to make everything.
2031
2032 For now, we'll just stick with menus for dialogs that are more
2033 complicated than simple yes/no type questions for which we can use
2034 the MessageBox function.
2035*/
2036
485015ca 2037static char * button_names [] = {
ee78dc32 2038 "button1", "button2", "button3", "button4", "button5",
485015ca 2039 "button6", "button7", "button8", "button9", "button10" };
ee78dc32
GV
2040
2041static Lisp_Object
d23928c7 2042w32_dialog_show (f, keymaps, title, header, error)
ee78dc32 2043 FRAME_PTR f;
ee78dc32 2044 int keymaps;
d23928c7 2045 Lisp_Object title, header;
ee78dc32
GV
2046 char **error;
2047{
2048 int i, nb_buttons=0;
ee78dc32 2049 char dialog_name[6];
485015ca
GV
2050 int menu_item_selection;
2051
fe5a0162 2052 widget_value *wv, *first_wv = 0, *prev_wv = 0;
485015ca 2053
ee78dc32
GV
2054 /* Number of elements seen so far, before boundary. */
2055 int left_count = 0;
2056 /* 1 means we've seen the boundary between left-hand elts and right-hand. */
2057 int boundary_seen = 0;
485015ca 2058
ee78dc32 2059 *error = NULL;
485015ca 2060
ee78dc32
GV
2061 if (menu_items_n_panes > 1)
2062 {
2063 *error = "Multiple panes in dialog box";
2064 return Qnil;
2065 }
485015ca 2066
ee78dc32
GV
2067 /* Create a tree of widget_value objects
2068 representing the text label and buttons. */
2069 {
2070 Lisp_Object pane_name, prefix;
2071 char *pane_string;
6ed09cf0
RS
2072 pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
2073 prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX);
ee78dc32 2074 pane_string = (NILP (pane_name)
177c0ea7 2075 ? "" : (char *) SDATA (pane_name));
485015ca 2076 prev_wv = xmalloc_widget_value ();
ee78dc32
GV
2077 prev_wv->value = pane_string;
2078 if (keymaps && !NILP (prefix))
2079 prev_wv->name++;
2080 prev_wv->enabled = 1;
2081 prev_wv->name = "message";
2d10309f 2082 prev_wv->help = Qnil;
ee78dc32 2083 first_wv = prev_wv;
177c0ea7 2084
ee78dc32
GV
2085 /* Loop over all panes and items, filling in the tree. */
2086 i = MENU_ITEMS_PANE_LENGTH;
2087 while (i < menu_items_used)
2088 {
177c0ea7 2089
ee78dc32 2090 /* Create a new item within current pane. */
b65a2f83 2091 Lisp_Object item_name, enable, descrip, help;
b65a2f83 2092
6ed09cf0
RS
2093 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
2094 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
2095 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
2096 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
177c0ea7 2097
ee78dc32
GV
2098 if (NILP (item_name))
2099 {
2100 free_menubar_widget_value_tree (first_wv);
2101 *error = "Submenu in dialog items";
2102 return Qnil;
2103 }
2104 if (EQ (item_name, Qquote))
2105 {
2106 /* This is the boundary between left-side elts
2107 and right-side elts. Stop incrementing right_count. */
2108 boundary_seen = 1;
2109 i++;
2110 continue;
2111 }
485015ca 2112 if (nb_buttons >= 9)
ee78dc32
GV
2113 {
2114 free_menubar_widget_value_tree (first_wv);
2115 *error = "Too many dialog items";
2116 return Qnil;
2117 }
485015ca
GV
2118
2119 wv = xmalloc_widget_value ();
ee78dc32
GV
2120 prev_wv->next = wv;
2121 wv->name = (char *) button_names[nb_buttons];
2122 if (!NILP (descrip))
d5db4077
KR
2123 wv->key = (char *) SDATA (descrip);
2124 wv->value = (char *) SDATA (item_name);
6ed09cf0 2125 wv->call_data = (void *) &AREF (menu_items, i);
ee78dc32 2126 wv->enabled = !NILP (enable);
2d10309f 2127 wv->help = Qnil;
ee78dc32 2128 prev_wv = wv;
485015ca 2129
ee78dc32
GV
2130 if (! boundary_seen)
2131 left_count++;
485015ca 2132
ee78dc32
GV
2133 nb_buttons++;
2134 i += MENU_ITEMS_ITEM_LENGTH;
2135 }
485015ca 2136
ee78dc32
GV
2137 /* If the boundary was not specified,
2138 by default put half on the left and half on the right. */
2139 if (! boundary_seen)
2140 left_count = nb_buttons - nb_buttons / 2;
485015ca
GV
2141
2142 wv = xmalloc_widget_value ();
ee78dc32 2143 wv->name = dialog_name;
2d10309f 2144 wv->help = Qnil;
485015ca 2145
d23928c7
NR
2146 /* Frame title: 'Q' = Question, 'I' = Information.
2147 Can also have 'E' = Error if, one day, we want
2148 a popup for errors. */
2149 if (NILP(header))
2150 dialog_name[0] = 'Q';
2151 else
2152 dialog_name[0] = 'I';
2153
ee78dc32
GV
2154 /* Dialog boxes use a really stupid name encoding
2155 which specifies how many buttons to use
d23928c7 2156 and how many buttons are on the right. */
ee78dc32
GV
2157 dialog_name[1] = '0' + nb_buttons;
2158 dialog_name[2] = 'B';
2159 dialog_name[3] = 'R';
2160 /* Number of buttons to put on the right. */
2161 dialog_name[4] = '0' + nb_buttons - left_count;
2162 dialog_name[5] = 0;
2163 wv->contents = first_wv;
2164 first_wv = wv;
2165 }
485015ca 2166
ee78dc32 2167 /* Actually create the dialog. */
485015ca 2168 dialog_id = widget_id_tick++;
ee78dc32 2169 menu = lw_create_widget (first_wv->name, "dialog", dialog_id, first_wv,
fbd6baed 2170 f->output_data.w32->widget, 1, 0,
ee78dc32 2171 dialog_selection_callback, 0);
02067692 2172 lw_modify_all_widgets (dialog_id, first_wv->contents, TRUE);
485015ca 2173
ee78dc32
GV
2174 /* Free the widget_value objects we used to specify the contents. */
2175 free_menubar_widget_value_tree (first_wv);
485015ca 2176
ee78dc32
GV
2177 /* No selection has been chosen yet. */
2178 menu_item_selection = 0;
485015ca 2179
ee78dc32
GV
2180 /* Display the menu. */
2181 lw_pop_up_all_widgets (dialog_id);
485015ca 2182
ee78dc32 2183 /* Process events that apply to the menu. */
485015ca 2184 popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id);
ee78dc32 2185
177c0ea7 2186 lw_destroy_all_widgets (dialog_id);
ee78dc32 2187
ee78dc32
GV
2188 /* Find the selected item, and its pane, to return
2189 the proper value. */
2190 if (menu_item_selection != 0)
2191 {
2192 Lisp_Object prefix;
485015ca 2193
ee78dc32
GV
2194 prefix = Qnil;
2195 i = 0;
2196 while (i < menu_items_used)
2197 {
2198 Lisp_Object entry;
2199
6ed09cf0 2200 if (EQ (AREF (menu_items, i), Qt))
ee78dc32 2201 {
6ed09cf0 2202 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
ee78dc32
GV
2203 i += MENU_ITEMS_PANE_LENGTH;
2204 }
2205 else
2206 {
6ed09cf0 2207 entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
485015ca 2208 if (menu_item_selection == i)
ee78dc32
GV
2209 {
2210 if (keymaps != 0)
2211 {
2212 entry = Fcons (entry, Qnil);
2213 if (!NILP (prefix))
2214 entry = Fcons (prefix, entry);
2215 }
2216 return entry;
2217 }
2218 i += MENU_ITEMS_ITEM_LENGTH;
2219 }
2220 }
2221 }
f3e0a6de
JR
2222 else
2223 /* Make "Cancel" equivalent to C-g. */
2224 Fsignal (Qquit, Qnil);
485015ca 2225
ee78dc32
GV
2226 return Qnil;
2227}
31403b24
JR
2228#else /* !HAVE_DIALOGS */
2229
2230/* Currently we only handle Yes No dialogs (y-or-n-p and yes-or-no-p) as
2231 simple dialogs. We could handle a few more, but I'm not aware of
2232 anywhere in Emacs that uses the other specific dialog choices that
2233 MessageBox provides. */
2234
2235static int is_simple_dialog (contents)
2236 Lisp_Object contents;
2237{
2238 Lisp_Object options = XCDR (contents);
2239 Lisp_Object name, yes, no, other;
2240
2241 yes = build_string ("Yes");
2242 no = build_string ("No");
2243
2244 if (!CONSP (options))
2245 return 0;
2246
2247 name = XCAR (XCAR (options));
2248 if (!CONSP (options))
2249 return 0;
2250
2251 if (!NILP (Fstring_equal (name, yes)))
2252 other = no;
2253 else if (!NILP (Fstring_equal (name, no)))
2254 other = yes;
2255 else
2256 return 0;
2257
2258 options = XCDR (options);
2259 if (!CONSP (options))
2260 return 0;
2261
2262 name = XCAR (XCAR (options));
2263 if (NILP (Fstring_equal (name, other)))
2264 return 0;
2265
2266 /* Check there are no more options. */
2267 options = XCDR (options);
2268 return !(CONSP (options));
2269}
2270
2271static Lisp_Object simple_dialog_show (f, contents, header)
2272 FRAME_PTR f;
2273 Lisp_Object contents, header;
2274{
2275 int answer;
2276 UINT type;
2277 char *text, *title;
2278 Lisp_Object lispy_answer = Qnil, temp = XCAR (contents);
2279
2280 if (STRINGP (temp))
2281 text = SDATA (temp);
2282 else
2283 text = "";
2284
2285 if (NILP (header))
2286 {
2287 title = "Question";
2288 type = MB_ICONQUESTION;
2289 }
2290 else
2291 {
2292 title = "Information";
2293 type = MB_ICONINFORMATION;
2294 }
2295 type |= MB_YESNO;
2296
2297 /* Since we only handle Yes/No dialogs, and we already checked
2298 is_simple_dialog, we don't need to worry about checking contents
2299 to see what type of dialog to use. */
2300 answer = MessageBox (FRAME_W32_WINDOW (f), text, title, type);
2301
2302 if (answer == IDYES)
2303 lispy_answer = build_string ("Yes");
2304 else if (answer == IDNO)
2305 lispy_answer = build_string ("No");
2306 else
2307 Fsignal (Qquit, Qnil);
2308
2309 for (temp = XCDR (contents); CONSP (temp); temp = XCDR (temp))
2310 {
2311 Lisp_Object item, name, value;
2312 item = XCAR (temp);
2313 if (CONSP (item))
2314 {
2315 name = XCAR (item);
2316 value = XCDR (item);
2317 }
2318 else
2319 {
2320 name = item;
2321 value = Qnil;
2322 }
2323
2324 if (!NILP (Fstring_equal (name, lispy_answer)))
2325 {
2326 return value;
2327 }
2328 }
2329 Fsignal (Qquit, Qnil);
2330 return Qnil;
2331}
2332#endif /* !HAVE_DIALOGS */
485015ca
GV
2333\f
2334
2335/* Is this item a separator? */
2336static int
2337name_is_separator (name)
2338 char *name;
2339{
fe5a0162
SM
2340 char *start = name;
2341
2342 /* Check if name string consists of only dashes ('-'). */
485015ca 2343 while (*name == '-') name++;
fe5a0162
SM
2344 /* Separators can also be of the form "--:TripleSuperMegaEtched"
2345 or "--deep-shadow". We don't implement them yet, se we just treat
2346 them like normal separators. */
2347 return (*name == '\0' || start + 2 == name);
485015ca
GV
2348}
2349
2350
2351/* Indicate boundary between left and right. */
2352static int
2353add_left_right_boundary (HMENU menu)
2354{
2355 return AppendMenu (menu, MF_MENUBARBREAK, 0, NULL);
2356}
2357
1f06d367
JR
2358/* UTF8: 0xxxxxxx, 110xxxxx 10xxxxxx, 1110xxxx, 10xxxxxx, 10xxxxxx */
2359static void
2360utf8to16 (unsigned char * src, int len, WCHAR * dest)
2361{
2362 while (len > 0)
2363 {
2364 int utf16;
2365 if (*src < 0x80)
2366 {
2367 *dest = (WCHAR) *src;
2368 dest++; src++; len--;
2369 }
2370 /* Since we might get >3 byte sequences which we don't handle, ignore the extra parts. */
2371 else if (*src < 0xC0)
2372 {
2373 src++; len--;
2374 }
2375 /* 2 char UTF-8 sequence. */
2376 else if (*src < 0xE0)
2377 {
2378 *dest = (WCHAR) (((*src & 0x1f) << 6)
2379 | (*(src + 1) & 0x3f));
2380 src += 2; len -= 2; dest++;
2381 }
2382 else if (*src < 0xF0)
2383 {
2384 *dest = (WCHAR) (((*src & 0x0f) << 12)
2385 | ((*(src + 1) & 0x3f) << 6)
2386 | (*(src + 2) & 0x3f));
2387 src += 3; len -= 3; dest++;
2388 }
2389 else /* Not encodable. Insert Unicode Substitution char. */
2390 {
2391 *dest = (WCHAR) 0xfffd;
2392 src++; len--; dest++;
2393 }
2394 }
2395 *dest = 0;
2396}
2397
485015ca
GV
2398static int
2399add_menu_item (HMENU menu, widget_value *wv, HMENU item)
2400{
2401 UINT fuFlags;
af41f8a8 2402 char *out_string, *p, *q;
37ad8b63 2403 int return_value;
af41f8a8 2404 size_t nlen, orig_len;
485015ca
GV
2405
2406 if (name_is_separator (wv->name))
222456a1
JR
2407 {
2408 fuFlags = MF_SEPARATOR;
2409 out_string = NULL;
2410 }
177c0ea7 2411 else
485015ca 2412 {
070d1949 2413 if (wv->enabled)
485015ca
GV
2414 fuFlags = MF_STRING;
2415 else
2416 fuFlags = MF_STRING | MF_GRAYED;
2417
2418 if (wv->key != NULL)
2419 {
2420 out_string = alloca (strlen (wv->name) + strlen (wv->key) + 2);
2421 strcpy (out_string, wv->name);
2422 strcat (out_string, "\t");
2423 strcat (out_string, wv->key);
2424 }
2425 else
2426 out_string = wv->name;
2427
af41f8a8
EZ
2428 /* Quote any special characters within the menu item's text and
2429 key binding. */
2430 nlen = orig_len = strlen (out_string);
ff25d115
JR
2431 if (unicode_append_menu)
2432 {
2433 /* With UTF-8, & cannot be part of a multibyte character. */
2434 for (p = out_string; *p; p++)
2435 {
2436 if (*p == '&')
2437 nlen++;
2438 }
2439 }
2440 else
2441 {
2442 /* If encoded with the system codepage, use multibyte string
2443 functions in case of multibyte characters that contain '&'. */
2444 for (p = out_string; *p; p = _mbsinc (p))
2445 {
2446 if (_mbsnextc (p) == '&')
2447 nlen++;
2448 }
2449 }
2450
af41f8a8 2451 if (nlen > orig_len)
ff25d115
JR
2452 {
2453 p = out_string;
2454 out_string = alloca (nlen + 1);
2455 q = out_string;
2456 while (*p)
2457 {
2458 if (unicode_append_menu)
2459 {
2460 if (*p == '&')
2461 *q++ = *p;
2462 *q++ = *p++;
2463 }
2464 else
2465 {
2466 if (_mbsnextc (p) == '&')
2467 {
2468 _mbsncpy (q, p, 1);
2469 q = _mbsinc (q);
2470 }
2471 _mbsncpy (q, p, 1);
2472 p = _mbsinc (p);
2473 q = _mbsinc (q);
2474 }
2475 }
2476 *q = '\0';
2477 }
af41f8a8 2478
d1fffd1d
JR
2479 if (item != NULL)
2480 fuFlags = MF_POPUP;
2481 else if (wv->title || wv->call_data == 0)
485015ca 2482 {
ace9b298
JR
2483 /* Only use MF_OWNERDRAW if GetMenuItemInfo is usable, since
2484 we can't deallocate the memory otherwise. */
2485 if (get_menu_item_info)
2486 {
6ed09cf0
RS
2487 out_string = (char *) local_alloc (strlen (wv->name) + 1);
2488 strcpy (out_string, wv->name);
d1fffd1d 2489#ifdef MENU_DEBUG
6ed09cf0 2490 DebPrint ("Menu: allocing %ld for owner-draw", out_string);
d1fffd1d 2491#endif
ace9b298
JR
2492 fuFlags = MF_OWNERDRAW | MF_DISABLED;
2493 }
2494 else
2495 fuFlags = MF_DISABLED;
485015ca 2496 }
1c5acb8c 2497
162d2499 2498 /* Draw radio buttons and tickboxes. */
4cdf6a6c 2499 else if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE ||
6f665da9 2500 wv->button_type == BUTTON_TYPE_RADIO))
4cdf6a6c 2501 fuFlags |= MF_CHECKED;
37ad8b63 2502 else
4cdf6a6c 2503 fuFlags |= MF_UNCHECKED;
485015ca 2504 }
4cdf6a6c 2505
1f06d367
JR
2506 if (unicode_append_menu && out_string)
2507 {
2508 /* Convert out_string from UTF-8 to UTF-16-LE. */
2509 int utf8_len = strlen (out_string);
2510 WCHAR * utf16_string;
2511 if (fuFlags & MF_OWNERDRAW)
2512 utf16_string = local_alloc ((utf8_len + 1) * sizeof (WCHAR));
2513 else
2514 utf16_string = alloca ((utf8_len + 1) * sizeof (WCHAR));
2515
2516 utf8to16 (out_string, utf8_len, utf16_string);
2517 return_value = unicode_append_menu (menu, fuFlags,
2518 item != NULL ? (UINT) item
2519 : (UINT) wv->call_data,
2520 utf16_string);
d749b6fa
JR
2521 if (!return_value)
2522 {
2523 /* On W9x/ME, unicode menus are not supported, though AppendMenuW
2524 apparently does exist at least in some cases and appears to be
2525 stubbed out to do nothing. out_string is UTF-8, but since
2526 our standard menus are in English and this is only going to
2527 happen the first time a menu is used, the encoding is
2528 of minor importance compared with menus not working at all. */
2529 return_value =
2530 AppendMenu (menu, fuFlags,
2531 item != NULL ? (UINT) item: (UINT) wv->call_data,
2532 out_string);
2533 /* Don't use unicode menus in future. */
2534 unicode_append_menu = NULL;
2535 }
2536
2537 if (unicode_append_menu && (fuFlags & MF_OWNERDRAW))
1f06d367
JR
2538 local_free (out_string);
2539 }
2540 else
2541 {
2542 return_value =
2543 AppendMenu (menu,
2544 fuFlags,
2545 item != NULL ? (UINT) item : (UINT) wv->call_data,
2546 out_string );
2547 }
37ad8b63
JR
2548
2549 /* This must be done after the menu item is created. */
6f665da9 2550 if (!wv->title && wv->call_data != 0)
4cdf6a6c 2551 {
4cdf6a6c
AI
2552 if (set_menu_item_info)
2553 {
2554 MENUITEMINFO info;
2555 bzero (&info, sizeof (info));
2556 info.cbSize = sizeof (info);
2557 info.fMask = MIIM_DATA;
2558
d1fffd1d
JR
2559 /* Set help string for menu item. Leave it as a Lisp_Object
2560 until it is ready to be displayed, since GC can happen while
2561 menus are active. */
24ee9763
JR
2562 if (!NILP (wv->help))
2563#ifdef USE_LISP_UNION_TYPE
2564 info.dwItemData = (DWORD) (wv->help).i;
2565#else
2566 info.dwItemData = (DWORD) (wv->help);
2567#endif
4cdf6a6c
AI
2568 if (wv->button_type == BUTTON_TYPE_RADIO)
2569 {
2570 /* CheckMenuRadioItem allows us to differentiate TOGGLE and
2571 RADIO items, but is not available on NT 3.51 and earlier. */
2572 info.fMask |= MIIM_TYPE | MIIM_STATE;
2573 info.fType = MFT_RADIOCHECK | MFT_STRING;
2574 info.dwTypeData = out_string;
2575 info.fState = wv->selected ? MFS_CHECKED : MFS_UNCHECKED;
2576 }
2577
2578 set_menu_item_info (menu,
2579 item != NULL ? (UINT) item : (UINT) wv->call_data,
2580 FALSE, &info);
2581 }
2582 }
37ad8b63 2583 return return_value;
485015ca
GV
2584}
2585
2586/* Construct native Windows menu(bar) based on widget_value tree. */
15d36dee 2587int
485015ca
GV
2588fill_in_menu (HMENU menu, widget_value *wv)
2589{
2590 int items_added = 0;
ee78dc32 2591
485015ca
GV
2592 for ( ; wv != NULL; wv = wv->next)
2593 {
2594 if (wv->contents)
2595 {
2596 HMENU sub_menu = CreatePopupMenu ();
2597
2598 if (sub_menu == NULL)
2599 return 0;
2600
2601 if (!fill_in_menu (sub_menu, wv->contents) ||
2602 !add_menu_item (menu, wv, sub_menu))
2603 {
2604 DestroyMenu (sub_menu);
2605 return 0;
2606 }
2607 }
2608 else
2609 {
2610 if (!add_menu_item (menu, wv, NULL))
2611 return 0;
2612 }
2613 }
2614 return 1;
2615}
2616
7d8e57da
JR
2617/* Display help string for currently pointed to menu item. Not
2618 supported on NT 3.51 and earlier, as GetMenuItemInfo is not
2619 available. */
2620void
59a86c99 2621w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags)
7d8e57da 2622{
7d8e57da
JR
2623 if (get_menu_item_info)
2624 {
1c5acb8c
JR
2625 struct frame *f = x_window_to_frame (&one_w32_display_info, owner);
2626 Lisp_Object frame, help;
7d8e57da 2627
94c7f257
JR
2628 /* No help echo on owner-draw menu items, or when the keyboard is used
2629 to navigate the menus, since tooltips are distracting if they pop
2630 up elsewhere. */
2631 if (flags & MF_OWNERDRAW || flags & MF_POPUP
2632 || !(flags & MF_MOUSESELECT))
ace9b298
JR
2633 help = Qnil;
2634 else
2635 {
2636 MENUITEMINFO info;
7d8e57da 2637
ace9b298
JR
2638 bzero (&info, sizeof (info));
2639 info.cbSize = sizeof (info);
2640 info.fMask = MIIM_DATA;
2641 get_menu_item_info (menu, item, FALSE, &info);
2642
24ee9763
JR
2643#ifdef USE_LISP_UNION_TYPE
2644 help = info.dwItemData ? (Lisp_Object) ((EMACS_INT) info.dwItemData)
2645 : Qnil;
2646#else
d1fffd1d 2647 help = info.dwItemData ? (Lisp_Object) info.dwItemData : Qnil;
24ee9763 2648#endif
ace9b298 2649 }
e5cd3d11 2650
1c5acb8c
JR
2651 /* Store the help echo in the keyboard buffer as the X toolkit
2652 version does, rather than directly showing it. This seems to
2653 solve the GC problems that were present when we based the
2654 Windows code on the non-toolkit version. */
2655 if (f)
2656 {
2657 XSETFRAME (frame, f);
2658 kbd_buffer_store_help_event (frame, help);
2659 }
2660 else
2661 /* X version has a loop through frames here, which doesn't
2662 appear to do anything, unless it has some side effect. */
2663 show_help_echo (help, Qnil, Qnil, Qnil, 1);
7d8e57da
JR
2664 }
2665}
2666
d1fffd1d 2667/* Free memory used by owner-drawn strings. */
ace9b298
JR
2668static void
2669w32_free_submenu_strings (menu)
2670 HMENU menu;
2671{
2672 int i, num = GetMenuItemCount (menu);
2673 for (i = 0; i < num; i++)
2674 {
2675 MENUITEMINFO info;
37647b2d 2676 bzero (&info, sizeof (info));
ace9b298 2677 info.cbSize = sizeof (info);
d1fffd1d 2678 info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_SUBMENU;
7d8e57da 2679
ace9b298
JR
2680 get_menu_item_info (menu, i, TRUE, &info);
2681
d1fffd1d
JR
2682 /* Owner-drawn names are held in dwItemData. */
2683 if ((info.fType & MF_OWNERDRAW) && info.dwItemData)
2684 {
2685#ifdef MENU_DEBUG
2686 DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData);
2687#endif
6ed09cf0 2688 local_free (info.dwItemData);
d1fffd1d 2689 }
ace9b298
JR
2690
2691 /* Recurse down submenus. */
2692 if (info.hSubMenu)
2693 w32_free_submenu_strings (info.hSubMenu);
2694 }
2695}
2696
2697void
2698w32_free_menu_strings (hwnd)
2699 HWND hwnd;
2700{
2701 HMENU menu = current_popup_menu;
2702
2703 if (get_menu_item_info)
2704 {
2705 /* If there is no popup menu active, free the strings from the frame's
2706 menubar. */
2707 if (!menu)
2708 menu = GetMenu (hwnd);
2709
2710 if (menu)
2711 w32_free_submenu_strings (menu);
2712 }
2713
2714 current_popup_menu = NULL;
2715}
7d8e57da 2716
485015ca 2717#endif /* HAVE_MENUS */
ace9b298 2718
e3135734
CY
2719/* The following is used by delayed window autoselection. */
2720
2721DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
2722 doc: /* Return t if a menu or popup dialog is active on selected frame. */)
2723 ()
2724{
2725#ifdef HAVE_MENUS
2726 FRAME_PTR f;
2727 f = SELECTED_FRAME ();
2728 return (f->output_data.w32->menubar_active > 0) ? Qt : Qnil;
2729#else
2730 return Qnil;
2731#endif /* HAVE_MENUS */
2732}
2733
f60ae425 2734void syms_of_w32menu ()
ee78dc32 2735{
019e3c1a 2736 globals_of_w32menu ();
485015ca
GV
2737 staticpro (&menu_items);
2738 menu_items = Qnil;
2739
ace9b298
JR
2740 current_popup_menu = NULL;
2741
019e3c1a 2742 DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
fdc12c4d 2743
ee78dc32 2744 defsubr (&Sx_popup_menu);
e5d3d18d 2745 defsubr (&Smenu_or_popup_active_p);
485015ca 2746#ifdef HAVE_MENUS
ee78dc32 2747 defsubr (&Sx_popup_dialog);
485015ca 2748#endif
ee78dc32 2749}
9785d95b
BK
2750
2751/*
2752 globals_of_w32menu is used to initialize those global variables that
2753 must always be initialized on startup even when the global variable
2754 initialized is non zero (see the function main in emacs.c).
2755 globals_of_w32menu is called from syms_of_w32menu when the global
2756 variable initialized is 0 and directly from main when initialized
2757 is non zero.
2758 */
2759void globals_of_w32menu ()
2760{
2761 /* See if Get/SetMenuItemInfo functions are available. */
2762 HMODULE user32 = GetModuleHandle ("user32.dll");
2763 get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA");
2764 set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA");
1f06d367 2765 unicode_append_menu = (AppendMenuW_Proc) GetProcAddress (user32, "AppendMenuW");
9785d95b 2766}
ab5796a9
MB
2767
2768/* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0
2769 (do not change this comment) */