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