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