]> code.delx.au - gnu-emacs/blobdiff - src/w32menu.c
Merge from emacs-23
[gnu-emacs] / src / w32menu.c
index d85a17e5b854449c88a8cad7ed2ae8e0084d88fb..fa047aee5c4a1e4f731df53860ff309060e47f29 100644 (file)
@@ -59,8 +59,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 HMENU current_popup_menu;
 
-void syms_of_w32menu ();
-void globals_of_w32menu ();
+void syms_of_w32menu (void);
+void globals_of_w32menu (void);
 
 typedef BOOL (WINAPI * GetMenuItemInfoA_Proc) (
     IN HMENU,
@@ -72,10 +72,16 @@ typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) (
     IN UINT,
     IN BOOL,
     IN LPCMENUITEMINFOA);
+typedef int (WINAPI * MessageBoxW_Proc) (
+    IN HWND window,
+    IN WCHAR *text,
+    IN WCHAR *caption,
+    IN UINT type);
 
 GetMenuItemInfoA_Proc get_menu_item_info = NULL;
 SetMenuItemInfoA_Proc set_menu_item_info = NULL;
 AppendMenuW_Proc unicode_append_menu = NULL;
+MessageBoxW_Proc unicode_message_box = NULL;
 
 Lisp_Object Qdebug_on_next_call;
 
@@ -90,16 +96,19 @@ extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
 
 extern Lisp_Object Qmenu_bar_update_hook;
 
-void set_frame_menubar P_ ((FRAME_PTR, int, int));
+void set_frame_menubar (FRAME_PTR, int, int);
 
 #ifdef HAVE_DIALOGS
-static Lisp_Object w32_dialog_show P_ ((FRAME_PTR, int, Lisp_Object, char**));
+static Lisp_Object w32_dialog_show (FRAME_PTR, int, Lisp_Object, char**);
 #else
-static int is_simple_dialog P_ ((Lisp_Object));
-static Lisp_Object simple_dialog_show P_ ((FRAME_PTR, Lisp_Object, Lisp_Object));
+static int is_simple_dialog (Lisp_Object);
+static Lisp_Object simple_dialog_show (FRAME_PTR, Lisp_Object, Lisp_Object);
 #endif
 
-void w32_free_menu_strings P_ ((HWND));
+static void utf8to16 (unsigned char *, int, WCHAR *);
+static int fill_in_menu (HMENU, widget_value *);
+
+void w32_free_menu_strings (HWND);
 \f
 
 /* This is set nonzero after the user activates the menu bar, and set
@@ -111,31 +120,6 @@ void w32_free_menu_strings P_ ((HWND));
 
 int pending_menu_activation;
 \f
-
-/* Return the frame whose ->output_data.w32->menubar_widget equals
-   ID, or 0 if none.  */
-
-static struct frame *
-menubar_id_to_frame (id)
-     HMENU id;
-{
-  Lisp_Object tail, frame;
-  FRAME_PTR f;
-
-  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
-    {
-      frame = XCAR (tail);
-      if (!FRAMEP (frame))
-        continue;
-      f = XFRAME (frame);
-      if (!FRAME_WINDOW_P (f))
-       continue;
-      if (f->output_data.w32->menubar_widget == id)
-       return f;
-    }
-  return 0;
-}
-\f
 #ifdef HAVE_MENUS
 
 DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
@@ -157,8 +141,7 @@ on the left of the dialog box and all following items on the right.
 
 If HEADER is non-nil, the frame title for the box is "Information",
 otherwise it is "Question". */)
-  (position, contents, header)
-     Lisp_Object position, contents, header;
+  (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
 {
   FRAME_PTR f = NULL;
   Lisp_Object window;
@@ -276,8 +259,7 @@ otherwise it is "Question". */)
    This way we can safely execute Lisp code.  */
 
 void
-x_activate_menubar (f)
-     FRAME_PTR f;
+x_activate_menubar (FRAME_PTR f)
 {
   set_frame_menubar (f, 0, 1);
 
@@ -386,10 +368,7 @@ menubar_selection_callback (FRAME_PTR f, void * client_data)
    it is set the first time this is called, from initialize_frame_menubar.  */
 
 void
-set_frame_menubar (f, first_time, deep_p)
-     FRAME_PTR f;
-     int first_time;
-     int deep_p;
+set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
 {
   HMENU menubar_widget = f->output_data.w32->menubar_widget;
   Lisp_Object items;
@@ -442,12 +421,8 @@ set_frame_menubar (f, first_time, deep_p)
 
       set_buffer_internal_1 (XBUFFER (buffer));
 
-      /* Run the Lucid hook.  */
+      /* Run the hooks.  */
       safe_run_hooks (Qactivate_menubar_hook);
-      /* If it has changed current-menubar from previous value,
-        really recompute the menubar from the value.  */
-      if (! NILP (Vlucid_menu_bar_dirty_flag))
-       call0 (Qrecompute_lucid_menubar);
       safe_run_hooks (Qmenu_bar_update_hook);
       FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
 
@@ -455,8 +430,8 @@ set_frame_menubar (f, first_time, deep_p)
 
       /* Save the frame's previous menu bar contents data.  */
       if (previous_menu_items_used)
-       bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
-              previous_menu_items_used * sizeof (Lisp_Object));
+       memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
+               previous_menu_items_used * sizeof (Lisp_Object));
 
       /* Fill in menu_items with the current menu bar contents.
         This can evaluate Lisp code.  */
@@ -648,8 +623,7 @@ set_frame_menubar (f, first_time, deep_p)
    is visible.  */
 
 void
-initialize_frame_menubar (f)
-     FRAME_PTR f;
+initialize_frame_menubar (FRAME_PTR f)
 {
   /* This function is called before the first chance to redisplay
      the frame.  It has to be, so the frame will have the right size.  */
@@ -661,8 +635,7 @@ initialize_frame_menubar (f)
    This is used when deleting a frame, and when turning off the menu bar.  */
 
 void
-free_frame_menubar (f)
-     FRAME_PTR f;
+free_frame_menubar (FRAME_PTR f)
 {
   BLOCK_INPUT;
 
@@ -694,7 +667,7 @@ free_frame_menubar (f)
 
 Lisp_Object
 w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
-              Lisp_Object title, char **error)
+              Lisp_Object title, const char **error)
 {
   int i;
   int menu_item_selection;
@@ -1020,11 +993,9 @@ static char * button_names [] = {
   "button6", "button7", "button8", "button9", "button10" };
 
 static Lisp_Object
-w32_dialog_show (f, keymaps, title, header, error)
-     FRAME_PTR f;
-     int keymaps;
-     Lisp_Object title, header;
-     char **error;
+w32_dialog_show (FRAME_PTR f, int keymaps,
+                Lisp_Object title, Lisp_Object header,
+                char **error)
 {
   int i, nb_buttons = 0;
   char dialog_name[6];
@@ -1214,8 +1185,7 @@ w32_dialog_show (f, keymaps, title, header, error)
    MessageBox provides.  */
 
 static int
-is_simple_dialog (contents)
-  Lisp_Object contents;
+is_simple_dialog (Lisp_Object contents)
 {
   Lisp_Object options = XCDR (contents);
   Lisp_Object name, yes, no, other;
@@ -1251,36 +1221,77 @@ is_simple_dialog (contents)
 }
 
 static Lisp_Object
-simple_dialog_show (f, contents, header)
-     FRAME_PTR f;
-     Lisp_Object contents, header;
+simple_dialog_show (FRAME_PTR f, Lisp_Object contents, Lisp_Object header)
 {
   int answer;
   UINT type;
-  char *text, *title;
   Lisp_Object lispy_answer = Qnil, temp = XCAR (contents);
 
-  if (STRINGP (temp))
-    text = SDATA (temp);
-  else
-    text = "";
+  type = MB_YESNO;
 
-  if (NILP (header))
+  /* Since we only handle Yes/No dialogs, and we already checked
+     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.  */
+  if (unicode_message_box)
     {
-      title = "Question";
-      type = MB_ICONQUESTION;
+      WCHAR *text, *title;
+
+      if (STRINGP (temp))
+       {
+         char *utf8_text = SDATA (ENCODE_UTF_8 (temp));
+         /* Be pessimistic about the number of characters needed.
+            Remember characters outside the BMP will take more than
+            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));
+         utf8to16 (utf8_text, utf8_len, text);
+       }
+      else
+       {
+         text = L"";
+       }
+
+      if (NILP (header))
+       {
+         title = L"Question";
+         type |= MB_ICONQUESTION;
+       }
+      else
+       {
+         title = L"Information";
+         type |= MB_ICONINFORMATION;
+       }
+
+      answer = unicode_message_box (FRAME_W32_WINDOW (f), text, title, type);
     }
   else
     {
-      title = "Information";
-      type = MB_ICONINFORMATION;
-    }
-  type |= MB_YESNO;
+      char *text, *title;
 
-  /* Since we only handle Yes/No dialogs, and we already checked
-     is_simple_dialog, we don't need to worry about checking contents
-     to see what type of dialog to use.  */
-  answer = MessageBox (FRAME_W32_WINDOW (f), text, title, type);
+      /* Fall back on ANSI message box, but at least use system
+        encoding so questions representable by the system codepage
+        are encoded properly.  */
+      if (STRINGP (temp))
+       text = SDATA (ENCODE_SYSTEM (temp));
+      else
+       text = "";
+
+      if (NILP (header))
+       {
+         title = "Question";
+         type |= MB_ICONQUESTION;
+       }
+      else
+       {
+         title = "Information";
+         type |= MB_ICONINFORMATION;
+       }
+
+      answer = MessageBox (FRAME_W32_WINDOW (f), text, title, type);
+    }
 
   if (answer == IDYES)
     lispy_answer = build_string ("Yes");
@@ -1315,28 +1326,6 @@ simple_dialog_show (f, contents, header)
 #endif  /* !HAVE_DIALOGS  */
 \f
 
-/* Is this item a separator? */
-static int
-name_is_separator (name)
-     char *name;
-{
-  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);
-}
-
-/* Indicate boundary between left and right.  */
-static int
-add_left_right_boundary (HMENU menu)
-{
-  return AppendMenu (menu, MF_MENUBARBREAK, 0, NULL);
-}
-
 /* UTF8: 0xxxxxxx, 110xxxxx 10xxxxxx, 1110xxxx, 10xxxxxx, 10xxxxxx */
 static void
 utf8to16 (unsigned char * src, int len, WCHAR * dest)
@@ -1385,7 +1374,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
   int return_value;
   size_t nlen, orig_len;
 
-  if (name_is_separator (wv->name))
+  if (menu_separator_name_p (wv->name))
     {
       fuFlags = MF_SEPARATOR;
       out_string = NULL;
@@ -1405,7 +1394,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
          strcat (out_string, wv->key);
        }
       else
-       out_string = wv->name;
+       out_string = (char *)wv->name;
 
       /* Quote any special characters within the menu item's text and
         key binding.  */
@@ -1534,7 +1523,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
       if (set_menu_item_info)
        {
          MENUITEMINFO info;
-         bzero (&info, sizeof (info));
+         memset (&info, 0, sizeof (info));
          info.cbSize = sizeof (info);
          info.fMask = MIIM_DATA;
 
@@ -1566,7 +1555,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
 }
 
 /* Construct native Windows menu(bar) based on widget_value tree.  */
-int
+static int
 fill_in_menu (HMENU menu, widget_value *wv)
 {
   int items_added = 0;
@@ -1617,7 +1606,7 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags)
        {
          MENUITEMINFO info;
 
-         bzero (&info, sizeof (info));
+         memset (&info, 0, sizeof (info));
          info.cbSize = sizeof (info);
          info.fMask = MIIM_DATA;
          get_menu_item_info (menu, item, FALSE, &info);
@@ -1648,14 +1637,13 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags)
 
 /* Free memory used by owner-drawn strings.  */
 static void
-w32_free_submenu_strings (menu)
-     HMENU menu;
+w32_free_submenu_strings (HMENU menu)
 {
   int i, num = GetMenuItemCount (menu);
   for (i = 0; i < num; i++)
     {
       MENUITEMINFO info;
-      bzero (&info, sizeof (info));
+      memset (&info, 0, sizeof (info));
       info.cbSize = sizeof (info);
       info.fMask = MIIM_DATA | MIIM_TYPE | MIIM_SUBMENU;
 
@@ -1677,8 +1665,7 @@ w32_free_submenu_strings (menu)
 }
 
 void
-w32_free_menu_strings (hwnd)
-     HWND hwnd;
+w32_free_menu_strings (HWND hwnd)
 {
   HMENU menu = current_popup_menu;
 
@@ -1702,7 +1689,7 @@ w32_free_menu_strings (hwnd)
 
 DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
        doc: /* Return t if a menu or popup dialog is active on selected frame.  */)
-     ()
+  (void)
 {
 #ifdef HAVE_MENUS
   FRAME_PTR f;
@@ -1714,7 +1701,7 @@ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_
 }
 
 void
-syms_of_w32menu ()
+syms_of_w32menu (void)
 {
   globals_of_w32menu ();
 
@@ -1737,13 +1724,14 @@ syms_of_w32menu ()
        is non zero.
  */
 void
-globals_of_w32menu ()
+globals_of_w32menu (void)
 {
   /* See if Get/SetMenuItemInfo functions are available.  */
   HMODULE user32 = GetModuleHandle ("user32.dll");
   get_menu_item_info = (GetMenuItemInfoA_Proc) GetProcAddress (user32, "GetMenuItemInfoA");
   set_menu_item_info = (SetMenuItemInfoA_Proc) GetProcAddress (user32, "SetMenuItemInfoA");
   unicode_append_menu = (AppendMenuW_Proc) GetProcAddress (user32, "AppendMenuW");
+  unicode_message_box = (MessageBoxW_Proc) GetProcAddress (user32, "MessageBoxW");
 }
 
 /* arch-tag: 0eaed431-bb4e-4aac-a527-95a1b4f1fed0