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