* dbusbind.c (xd_retrieve_arg): Pacify GCC on x86_64 GNU/Linux.
[bpt/emacs.git] / src / w32menu.c
index a0aef4b..e258ec9 100644 (file)
@@ -1,12 +1,13 @@
 /* Menu support for GNU Emacs on the Microsoft W32 API.
    Copyright (C) 1986, 1988, 1993, 1994, 1996, 1998, 1999, 2001, 2002,
-                 2003, 2004, 2005, 2006, 2007  Free Software Foundation, Inc.
+                 2003, 2004, 2005, 2006, 2007, 2008
+                 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -20,14 +21,16 @@ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 Boston, MA 02110-1301, USA.  */
 
 #include <config.h>
-#include <signal.h>
 
+#include <signal.h>
 #include <stdio.h>
+#include <mbstring.h>
+
 #include "lisp.h"
-#include "termhooks.h"
 #include "keyboard.h"
 #include "keymap.h"
 #include "frame.h"
+#include "termhooks.h"
 #include "window.h"
 #include "blockinput.h"
 #include "buffer.h"
@@ -316,14 +319,8 @@ discard_menu_items ()
 static void
 grow_menu_items ()
 {
-  Lisp_Object old;
-  int old_size = menu_items_allocated;
-  old = menu_items;
-
   menu_items_allocated *= 2;
-  menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
-  bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents,
-        old_size * sizeof (Lisp_Object));
+  menu_items = larger_vector (menu_items, menu_items_allocated, Qnil);
 }
 
 /* Begin a submenu.  */
@@ -571,10 +568,10 @@ list_of_panes (menu)
 
   init_menu_items ();
 
-  for (tail = menu; !NILP (tail); tail = Fcdr (tail))
+  for (tail = menu; CONSP (tail); tail = XCDR (tail))
     {
       Lisp_Object elt, pane_name, pane_data;
-      elt = Fcar (tail);
+      elt = XCAR (tail);
       pane_name = Fcar (elt);
       CHECK_STRING (pane_name);
       push_menu_pane (pane_name, Qnil);
@@ -594,9 +591,9 @@ list_of_items (pane)
 {
   Lisp_Object tail, item, item1;
 
-  for (tail = pane; !NILP (tail); tail = Fcdr (tail))
+  for (tail = pane; CONSP (tail); tail = XCDR (tail))
     {
-      item = Fcar (tail);
+      item = XCAR (tail);
       if (STRINGP (item))
        push_menu_item (item, Qnil, Qnil, Qt, Qnil, Qnil, Qnil, Qnil);
       else if (NILP (item))
@@ -673,8 +670,8 @@ cached information about equivalent key sequences.  */)
          enum scroll_bar_part part;
          unsigned long time;
 
-         if (mouse_position_hook)
-           (*mouse_position_hook) (&new_f, 1, &bar_window,
+         if (FRAME_TERMINAL (new_f)->mouse_position_hook)
+           (*FRAME_TERMINAL (new_f)->mouse_position_hook) (&new_f, 1, &bar_window,
                                    &part, &x, &y, &time);
          if (new_f != 0)
            XSETFRAME (window, new_f);
@@ -1937,6 +1934,7 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
 
   /* Free the owner-drawn and help-echo menu strings.  */
   w32_free_menu_strings (FRAME_W32_WINDOW (f));
+  f->output_data.w32->menubar_active = 0;
 
   /* Find the selected item, and its pane, to return
      the proper value.  */
@@ -2260,8 +2258,9 @@ static int
 add_menu_item (HMENU menu, widget_value *wv, HMENU item)
 {
   UINT fuFlags;
-  char *out_string;
+  char *out_string, *p, *q;
   int return_value;
+  size_t nlen, orig_len;
 
   if (name_is_separator (wv->name))
     {
@@ -2285,6 +2284,57 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
       else
        out_string = wv->name;
 
+      /* Quote any special characters within the menu item's text and
+        key binding.  */
+      nlen = orig_len = strlen (out_string);
+      if (unicode_append_menu)
+        {
+          /* With UTF-8, & cannot be part of a multibyte character.  */
+          for (p = out_string; *p; p++)
+            {
+              if (*p == '&')
+                nlen++;
+            }
+        }
+      else
+        {
+          /* If encoded with the system codepage, use multibyte string
+             functions in case of multibyte characters that contain '&'.  */
+          for (p = out_string; *p; p = _mbsinc (p))
+            {
+              if (_mbsnextc (p) == '&')
+                nlen++;
+            }
+        }
+
+      if (nlen > orig_len)
+        {
+          p = out_string;
+          out_string = alloca (nlen + 1);
+          q = out_string;
+          while (*p)
+            {
+              if (unicode_append_menu)
+                {
+                  if (*p == '&')
+                    *q++ = *p;
+                  *q++ = *p++;
+                }
+              else
+                {
+                  if (_mbsnextc (p) == '&')
+                    {
+                      _mbsncpy (q, p, 1);
+                      q = _mbsinc (q);
+                    }
+                  _mbsncpy (q, p, 1);
+                  p = _mbsinc (p);
+                  q = _mbsinc (q);
+                }
+            }
+          *q = '\0';
+        }
+
       if (item != NULL)
        fuFlags = MF_POPUP;
       else if (wv->title || wv->call_data == 0)