Merge changes from emacs-24 branch
[bpt/emacs.git] / src / w32menu.c
index ff6bd97..5b95a08 100644 (file)
@@ -1,6 +1,5 @@
 /* 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, 2008, 2009, 2010
+   Copyright (C) 1986, 1988, 1993-1994, 1996, 1998-1999, 2001-2012
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -34,7 +33,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "blockinput.h"
 #include "buffer.h"
 #include "charset.h"
-#include "character.h"
 #include "coding.h"
 #include "menu.h"
 
@@ -50,6 +48,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "dispextern.h"
 
+#include "w32heap.h"   /* for osinfo_cache */
+
 #undef HAVE_DIALOGS /* TODO: Implement native dialogs.  */
 
 #ifndef TRUE
@@ -85,17 +85,6 @@ MessageBoxW_Proc unicode_message_box = NULL;
 
 Lisp_Object Qdebug_on_next_call;
 
-extern Lisp_Object Qmenu_bar;
-
-extern Lisp_Object QCtoggle, QCradio;
-
-extern Lisp_Object Voverriding_local_map;
-extern Lisp_Object Voverriding_local_map_menu_flag;
-
-extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
-
-extern Lisp_Object Qmenu_bar_update_hook;
-
 void set_frame_menubar (FRAME_PTR, int, int);
 
 #ifdef HAVE_DIALOGS
@@ -158,7 +147,7 @@ otherwise it is "Question". */)
       FRAME_PTR new_f = SELECTED_FRAME ();
       Lisp_Object bar_window;
       enum scroll_bar_part part;
-      unsigned long time;
+      Time time;
       Lisp_Object x, y;
 
       (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
@@ -439,11 +428,10 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
 
       menu_items = f->menu_bar_vector;
       menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
-      submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
-      submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
-      submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int));
-      submenu_top_level_items
-       = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
+      submenu_start = (int *) alloca (ASIZE (items) * sizeof (int));
+      submenu_end = (int *) alloca (ASIZE (items) * sizeof (int));
+      submenu_n_panes = (int *) alloca (ASIZE (items) * sizeof (int));
+      submenu_top_level_items = (int *) alloca (ASIZE (items) * sizeof (int));
       init_menu_items ();
       for (i = 0; i < ASIZE (items); i += 4)
        {
@@ -530,7 +518,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
          string = AREF (items, i + 1);
          if (NILP (string))
            break;
-         wv->name = (char *) SDATA (string);
+         wv->name = SSDATA (string);
          update_submenu_strings (wv->contents);
          wv = wv->next;
        }
@@ -558,7 +546,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
            break;
 
          wv = xmalloc_widget_value ();
-         wv->name = (char *) SDATA (string);
+         wv->name = SSDATA (string);
          wv->value = 0;
          wv->enabled = 1;
          wv->button_type = BUTTON_TYPE_NONE;
@@ -748,7 +736,7 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
            }
 
          pane_string = (NILP (pane_name)
-                        ? "" : (char *) SDATA (pane_name));
+                        ? "" : SSDATA (pane_name));
          /* If there is just one top-level pane, put all its items directly
             under the top-level menu.  */
          if (menu_items_n_panes == 1)
@@ -816,9 +804,9 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
            prev_wv->next = wv;
          else
            save_wv->contents = wv;
-         wv->name = (char *) SDATA (item_name);
+         wv->name = SSDATA (item_name);
          if (!NILP (descrip))
-           wv->key = (char *) SDATA (descrip);
+           wv->key = SSDATA (descrip);
          wv->value = 0;
          /* Use the contents index as call_data, since we are
              restricted to 16-bits.  */
@@ -864,7 +852,7 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
       else if (STRING_MULTIBYTE (title))
        title = ENCODE_SYSTEM (title);
 
-      wv_title->name = (char *) SDATA (title);
+      wv_title->name = SSDATA (title);
       wv_title->enabled = TRUE;
       wv_title->title = TRUE;
       wv_title->button_type = BUTTON_TYPE_NONE;
@@ -1024,7 +1012,7 @@ w32_dialog_show (FRAME_PTR f, int keymaps,
     pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
     prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX);
     pane_string = (NILP (pane_name)
-                  ? "" : (char *) SDATA (pane_name));
+                  ? "" : SSDATA (pane_name));
     prev_wv = xmalloc_widget_value ();
     prev_wv->value = pane_string;
     if (keymaps && !NILP (prefix))
@@ -1072,8 +1060,8 @@ w32_dialog_show (FRAME_PTR f, int keymaps,
        prev_wv->next = wv;
        wv->name = (char *) button_names[nb_buttons];
        if (!NILP (descrip))
-         wv->key = (char *) SDATA (descrip);
-       wv->value = (char *) SDATA (item_name);
+         wv->key = SSDATA (descrip);
+       wv->value = SSDATA (item_name);
        wv->call_data = (void *) &AREF (menu_items, i);
        wv->enabled = !NILP (enable);
        wv->help = Qnil;
@@ -1187,18 +1175,23 @@ w32_dialog_show (FRAME_PTR f, int keymaps,
 static int
 is_simple_dialog (Lisp_Object contents)
 {
-  Lisp_Object options = XCDR (contents);
+  Lisp_Object options;
   Lisp_Object name, yes, no, other;
 
+  if (!CONSP (contents))
+    return 0;
+  options = XCDR (contents);
+
   yes = build_string ("Yes");
   no = build_string ("No");
 
   if (!CONSP (options))
     return 0;
 
-  name = XCAR (XCAR (options));
-  if (!CONSP (options))
+  name = XCAR (options);
+  if (!CONSP (name))
     return 0;
+  name = XCAR (name);
 
   if (!NILP (Fstring_equal (name, yes)))
     other = no;
@@ -1211,7 +1204,10 @@ is_simple_dialog (Lisp_Object contents)
   if (!CONSP (options))
     return 0;
 
-  name = XCAR (XCAR (options));
+  name = XCAR (options);
+  if (!CONSP (name))
+    return 0;
+  name = XCAR (name);
   if (NILP (Fstring_equal (name, other)))
     return 0;
 
@@ -1233,10 +1229,11 @@ simple_dialog_show (FRAME_PTR f, Lisp_Object contents, Lisp_Object header)
      is_simple_dialog, we don't need to worry about checking contents
      to see what type of dialog to use.  */
 
-  /* Use unicode if possible, so any language can be displayed.  */
+  /* Use Unicode if possible, so any language can be displayed.  */
   if (unicode_message_box)
     {
       WCHAR *text, *title;
+      USE_SAFE_ALLOCA;
 
       if (STRINGP (temp))
        {
@@ -1246,7 +1243,7 @@ simple_dialog_show (FRAME_PTR f, Lisp_Object contents, Lisp_Object header)
             one utf16 word, so we cannot simply use the character
             length of temp.  */
          int utf8_len = strlen (utf8_text);
-         text = alloca ((utf8_len + 1) * sizeof (WCHAR));
+         SAFE_ALLOCA (text, WCHAR *, (utf8_len + 1) * sizeof (WCHAR));
          utf8to16 (utf8_text, utf8_len, text);
        }
       else
@@ -1266,6 +1263,7 @@ simple_dialog_show (FRAME_PTR f, Lisp_Object contents, Lisp_Object header)
        }
 
       answer = unicode_message_box (FRAME_W32_WINDOW (f), text, title, type);
+      SAFE_FREE ();
     }
   else
     {
@@ -1326,27 +1324,12 @@ simple_dialog_show (FRAME_PTR f, Lisp_Object contents, Lisp_Object header)
 #endif  /* !HAVE_DIALOGS  */
 \f
 
-/* Is this item a separator? */
-static int
-name_is_separator (const char *name)
-{
-  const char *start = name;
-
-  /* Check if name string consists of only dashes ('-').  */
-  while (*name == '-') name++;
-  /* Separators can also be of the form "--:TripleSuperMegaEtched"
-     or "--deep-shadow".  We don't implement them yet, se we just treat
-     them like normal separators.  */
-  return (*name == '\0' || start + 2 == name);
-}
-
 /* UTF8: 0xxxxxxx, 110xxxxx 10xxxxxx, 1110xxxx, 10xxxxxx, 10xxxxxx */
 static void
 utf8to16 (unsigned char * src, int len, WCHAR * dest)
 {
   while (len > 0)
     {
-      int utf16;
       if (*src < 0x80)
        {
          *dest = (WCHAR) *src;
@@ -1387,8 +1370,9 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
   char *out_string, *p, *q;
   int return_value;
   size_t nlen, orig_len;
+  USE_SAFE_ALLOCA;
 
-  if (name_is_separator (wv->name))
+  if (menu_separator_name_p (wv->name))
     {
       fuFlags = MF_SEPARATOR;
       out_string = NULL;
@@ -1402,7 +1386,8 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
 
       if (wv->key != NULL)
        {
-         out_string = alloca (strlen (wv->name) + strlen (wv->key) + 2);
+         SAFE_ALLOCA (out_string, char *,
+                      strlen (wv->name) + strlen (wv->key) + 2);
          strcpy (out_string, wv->name);
          strcat (out_string, "\t");
          strcat (out_string, wv->key);
@@ -1436,7 +1421,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
       if (nlen > orig_len)
         {
           p = out_string;
-          out_string = alloca (nlen + 1);
+          SAFE_ALLOCA (out_string, char *, nlen + 1);
           q = out_string;
           while (*p)
             {
@@ -1472,7 +1457,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
               out_string = (char *) local_alloc (strlen (wv->name) + 1);
               strcpy (out_string, wv->name);
 #ifdef MENU_DEBUG
-             DebPrint ("Menu: allocing %ld for owner-draw", out_string);
+             DebPrint ("Menu: allocating %ld for owner-draw", out_string);
 #endif
              fuFlags = MF_OWNERDRAW | MF_DISABLED;
            }
@@ -1496,7 +1481,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
       if (fuFlags & MF_OWNERDRAW)
        utf16_string = local_alloc ((utf8_len + 1) * sizeof (WCHAR));
       else
-       utf16_string = alloca ((utf8_len + 1) * sizeof (WCHAR));
+       SAFE_ALLOCA (utf16_string, WCHAR *, (utf8_len + 1) * sizeof (WCHAR));
 
       utf8to16 (out_string, utf8_len, utf16_string);
       return_value = unicode_append_menu (menu, fuFlags,
@@ -1505,7 +1490,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
                                          utf16_string);
       if (!return_value)
        {
-         /* On W9x/ME, unicode menus are not supported, though AppendMenuW
+         /* On W9x/ME, Unicode menus are not supported, though AppendMenuW
             apparently does exist at least in some cases and appears to be
             stubbed out to do nothing.  out_string is UTF-8, but since
             our standard menus are in English and this is only going to
@@ -1515,8 +1500,11 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
            AppendMenu (menu, fuFlags,
                        item != NULL ? (UINT) item: (UINT) wv->call_data,
                        out_string);
-         /* Don't use unicode menus in future.  */
-         unicode_append_menu = NULL;
+         /* Don't use Unicode menus in future, unless this is Windows
+            NT or later, where a failure of AppendMenuW does NOT mean
+            Unicode menus are unsupported.  */
+         if (osinfo_cache.dwPlatformId != VER_PLATFORM_WIN32_NT)
+           unicode_append_menu = NULL;
        }
 
       if (unicode_append_menu && (fuFlags & MF_OWNERDRAW))
@@ -1565,6 +1553,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
                              FALSE, &info);
        }
     }
+  SAFE_FREE ();
   return return_value;
 }
 
@@ -1572,8 +1561,6 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
 static int
 fill_in_menu (HMENU menu, widget_value *wv)
 {
-  int items_added = 0;
-
   for ( ; wv != NULL; wv = wv->next)
     {
       if (wv->contents)
@@ -1645,7 +1632,7 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags)
       else
        /* X version has a loop through frames here, which doesn't
           appear to do anything, unless it has some side effect.  */
-       show_help_echo (help, Qnil, Qnil, Qnil, 1);
+       show_help_echo (help, Qnil, Qnil, Qnil);
     }
 }
 
@@ -1747,6 +1734,3 @@ globals_of_w32menu (void)
   unicode_append_menu = (AppendMenuW_Proc) GetProcAddress (user32, "AppendMenuW");
   unicode_message_box = (MessageBoxW_Proc) GetProcAddress (user32, "MessageBoxW");
 }
-
-/* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0
-   (do not change this comment) */