]> code.delx.au - gnu-emacs/blobdiff - src/w32menu.c
Fix docstring of format-time-string to include %F.
[gnu-emacs] / src / w32menu.c
index fb1cb6069404fc5df46b76586de80317b0bbea90..4f8e8dbef052de8099875ac830dcd055c610b976 100644 (file)
@@ -1,6 +1,6 @@
 /* Menu support for GNU Emacs on the Microsoft Windows API.
-   Copyright (C) 1986, 1988, 1993-1994, 1996, 1998-1999, 2001-2012
-                 Free Software Foundation, Inc.
+   Copyright (C) 1986, 1988, 1993-1994, 1996, 1998-1999, 2001-2013 Free
+   Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -21,7 +21,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <signal.h>
 #include <stdio.h>
-#include <mbstring.h>
+#include <setjmp.h>
 
 #include "lisp.h"
 #include "keyboard.h"
@@ -40,6 +40,14 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
    if this is not done before the other system files.  */
 #include "w32term.h"
 
+/* Cygwin does not support the multibyte string functions declared in
+ * mbstring.h below --- but that's okay: because Cygwin is
+ * UNICODE-only, we don't need to use these functions anyway.  */
+
+#ifndef NTGUI_UNICODE
+#include <mbstring.h>
+#endif /* !NTGUI_UNICODE */
+
 /* Load sys/types.h if not already loaded.
    In some systems loading it twice is suicidal.  */
 #ifndef makedev
@@ -48,7 +56,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "dispextern.h"
 
-#include "w32heap.h"   /* for osinfo_cache */
+#include "w32common.h" /* for osinfo_cache */
 
 #undef HAVE_DIALOGS /* TODO: Implement native dialogs.  */
 
@@ -78,161 +86,62 @@ typedef int (WINAPI * MessageBoxW_Proc) (
     IN WCHAR *caption,
     IN UINT type);
 
+#ifdef NTGUI_UNICODE
+#define get_menu_item_info GetMenuItemInfoA
+#define set_menu_item_info SetMenuItemInfoA
+#define unicode_append_menu AppendMenuW
+#define unicode_message_box MessageBoxW
+#else /* !NTGUI_UNICODE */
 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;
+#endif /* NTGUI_UNICODE */
 
 Lisp_Object Qdebug_on_next_call;
 
-void set_frame_menubar (FRAME_PTR, bool, bool);
+void set_frame_menubar (struct frame *, bool, bool);
 
 #ifdef HAVE_DIALOGS
-static Lisp_Object w32_dialog_show (FRAME_PTR, int, Lisp_Object, char**);
+static Lisp_Object w32_dialog_show (struct frame *, int, Lisp_Object, char**);
 #else
 static int is_simple_dialog (Lisp_Object);
-static Lisp_Object simple_dialog_show (FRAME_PTR, Lisp_Object, Lisp_Object);
+static Lisp_Object simple_dialog_show (struct frame *, Lisp_Object, Lisp_Object);
 #endif
 
 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
-   to zero again after the menu bars are redisplayed by prepare_menu_bar.
-   While it is nonzero, all calls to set_frame_menubar go deep.
-
-   I don't understand why this is needed, but it does seem to be
-   needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>.  */
 
-int pending_menu_activation;
-\f
-#ifdef HAVE_MENUS
-
-DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
-       doc: /* Pop up a dialog box and return user's selection.
-POSITION specifies which frame to use.
-This is normally a mouse button event or a window or frame.
-If POSITION is t, it means to use the frame the mouse is on.
-The dialog box appears in the middle of the specified frame.
-
-CONTENTS specifies the alternatives to display in the dialog box.
-It is a list of the form (TITLE ITEM1 ITEM2...).
-Each ITEM is a cons cell (STRING . VALUE).
-The return value is VALUE from the chosen item.
-
-An ITEM may also be just a string--that makes a nonselectable item.
-An ITEM may also be nil--that means to put all preceding items
-on the left of the dialog box and all following items on the right.
-\(By default, approximately half appear on each side.)
-
-If HEADER is non-nil, the frame title for the box is "Information",
-otherwise it is "Question". */)
-  (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
+#ifdef HAVE_DIALOGS
+Lisp_Object
+w32_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
 {
-  FRAME_PTR f = NULL;
-  Lisp_Object window;
-
-  check_w32 ();
-
-  /* Decode the first argument: find the window or frame to use.  */
-  if (EQ (position, Qt)
-      || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
-                               || EQ (XCAR (position), Qtool_bar))))
-    {
-#if 0 /* Using the frame the mouse is on may not be right.  */
-      /* Use the mouse's current position.  */
-      FRAME_PTR new_f = SELECTED_FRAME ();
-      Lisp_Object bar_window;
-      enum scroll_bar_part part;
-      Time time;
-      Lisp_Object x, y;
-
-      (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
-
-      if (new_f != 0)
-       XSETFRAME (window, new_f);
-      else
-       window = selected_window;
-#endif
-      window = selected_window;
-    }
-  else if (CONSP (position))
-    {
-      Lisp_Object tem = XCAR (position);
-      if (CONSP (tem))
-       window = Fcar (XCDR (position));
-      else
-       {
-         tem = Fcar (XCDR (position));  /* EVENT_START (position) */
-         window = Fcar (tem);       /* POSN_WINDOW (tem) */
-       }
-    }
-  else if (WINDOWP (position) || FRAMEP (position))
-    window = position;
-  else
-    window = Qnil;
-
-  /* Decode where to put the menu.  */
-
-  if (FRAMEP (window))
-    f = XFRAME (window);
-  else if (WINDOWP (window))
-    {
-      CHECK_LIVE_WINDOW (window);
-      f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
-    }
-  else
-    /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
-       but I don't want to make one now.  */
-    CHECK_WINDOW (window);
+  Lisp_Object title;
+  char *error_name;
+  Lisp_Object selection;
 
-#ifndef HAVE_DIALOGS
+  check_window_system (f);
 
-  {
-    /* Handle simple Yes/No choices as MessageBox popups.  */
-    if (is_simple_dialog (contents))
-      return simple_dialog_show (f, contents, header);
-    else
-      {
-       /* Display a menu with these alternatives
-          in the middle of frame F.  */
-       Lisp_Object x, y, frame, newpos;
-       XSETFRAME (frame, f);
-       XSETINT (x, x_pixel_width (f) / 2);
-       XSETINT (y, x_pixel_height (f) / 2);
-       newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
-       return Fx_popup_menu (newpos,
-                             Fcons (Fcar (contents), Fcons (contents, Qnil)));
-      }
-  }
-#else /* HAVE_DIALOGS */
-  {
-    Lisp_Object title;
-    char *error_name;
-    Lisp_Object selection;
+  /* Decode the dialog items from what was specified.  */
+  title = Fcar (contents);
+  CHECK_STRING (title);
 
-    /* Decode the dialog items from what was specified.  */
-    title = Fcar (contents);
-    CHECK_STRING (title);
+  list_of_panes (Fcons (contents, Qnil));
 
-    list_of_panes (Fcons (contents, Qnil));
-
-    /* Display them in a dialog box.  */
-    block_input ();
-    selection = w32_dialog_show (f, 0, title, header, &error_name);
-    unblock_input ();
+  /* Display them in a dialog box.  */
+  block_input ();
+  selection = w32_dialog_show (f, 0, title, header, &error_name);
+  unblock_input ();
 
-    discard_menu_items ();
-    FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+  discard_menu_items ();
+  FRAME_DISPLAY_INFO (f)->grabbed = 0;
 
-    if (error_name) error (error_name);
-    return selection;
-  }
-#endif /* HAVE_DIALOGS */
+  if (error_name) error (error_name);
+  return selection;
 }
+#endif /* HAVE_DIALOGS */
 
 /* Activate the menu bar of frame F.
    This is called from keyboard.c when it gets the
@@ -247,7 +156,7 @@ otherwise it is "Question". */)
    This way we can safely execute Lisp code.  */
 
 void
-x_activate_menubar (FRAME_PTR f)
+x_activate_menubar (struct frame *f)
 {
   set_frame_menubar (f, 0, 1);
 
@@ -264,7 +173,7 @@ x_activate_menubar (FRAME_PTR f)
    and put the appropriate events into the keyboard buffer.  */
 
 void
-menubar_selection_callback (FRAME_PTR f, void * client_data)
+menubar_selection_callback (struct frame *f, void * client_data)
 {
   Lisp_Object prefix, entry;
   Lisp_Object vector;
@@ -356,7 +265,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 (FRAME_PTR f, bool first_time, bool deep_p)
+set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
 {
   HMENU menubar_widget = f->output_data.w32->menubar_widget;
   Lisp_Object items;
@@ -373,8 +282,6 @@ set_frame_menubar (FRAME_PTR f, bool first_time, bool deep_p)
 
   if (! menubar_widget)
     deep_p = 1;
-  else if (pending_menu_activation && !deep_p)
-    deep_p = 1;
 
   if (deep_p)
     {
@@ -393,7 +300,7 @@ set_frame_menubar (FRAME_PTR f, bool first_time, bool deep_p)
       if (! menubar_widget)
        previous_menu_items_used = 0;
 
-      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
+      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents;
       specbind (Qinhibit_quit, Qt);
       /* Don't let the debugger step into this code
         because it is not reentrant.  */
@@ -598,7 +505,7 @@ set_frame_menubar (FRAME_PTR f, bool first_time, bool deep_p)
     /* Force the window size to be recomputed so that the frame's text
        area remains the same, if menubar has just been created.  */
     if (old_widget == NULL)
-      x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+      x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
   }
 
   unblock_input ();
@@ -610,7 +517,7 @@ set_frame_menubar (FRAME_PTR f, bool first_time, bool deep_p)
    is visible.  */
 
 void
-initialize_frame_menubar (FRAME_PTR f)
+initialize_frame_menubar (struct frame *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.  */
@@ -622,7 +529,7 @@ initialize_frame_menubar (FRAME_PTR f)
    This is used when deleting a frame, and when turning off the menu bar.  */
 
 void
-free_frame_menubar (FRAME_PTR f)
+free_frame_menubar (struct frame *f)
 {
   block_input ();
 
@@ -653,7 +560,7 @@ free_frame_menubar (FRAME_PTR f)
    (We return nil on failure, but the value doesn't actually matter.)  */
 
 Lisp_Object
-w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
+w32_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
               Lisp_Object title, const char **error)
 {
   int i;
@@ -679,6 +586,8 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
       return Qnil;
     }
 
+  block_input ();
+
   /* Create a tree of widget_value objects
      representing the panes and their items.  */
   wv = xmalloc_widget_value ();
@@ -880,7 +789,7 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
   /* Clean up extraneous mouse events which might have been generated
      during the call. */
   discard_mouse_events ();
-  FRAME_X_DISPLAY_INFO (f)->grabbed = 0;
+  FRAME_DISPLAY_INFO (f)->grabbed = 0;
 
   /* Free the widget_value objects we used to specify the contents.  */
   free_menubar_widget_value_tree (first_wv);
@@ -937,6 +846,7 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
                        if (!NILP (subprefix_stack[j]))
                          entry = Fcons (subprefix_stack[j], entry);
                    }
+                 unblock_input ();
                  return entry;
                }
              i += MENU_ITEMS_ITEM_LENGTH;
@@ -944,9 +854,13 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
        }
     }
   else if (!for_click)
-    /* Make "Cancel" equivalent to C-g.  */
-    Fsignal (Qquit, Qnil);
+    {
+      unblock_input ();
+      /* Make "Cancel" equivalent to C-g.  */
+      Fsignal (Qquit, Qnil);
+    }
 
+  unblock_input ();
   return Qnil;
 }
 \f
@@ -980,7 +894,7 @@ static char * button_names [] = {
   "button6", "button7", "button8", "button9", "button10" };
 
 static Lisp_Object
-w32_dialog_show (FRAME_PTR f, int keymaps,
+w32_dialog_show (struct frame *f, int keymaps,
                 Lisp_Object title, Lisp_Object header,
                 char **error)
 {
@@ -1120,7 +1034,7 @@ w32_dialog_show (FRAME_PTR f, int keymaps,
   lw_pop_up_all_widgets (dialog_id);
 
   /* Process events that apply to the menu.  */
-  popup_get_selection ((XEvent *) 0, FRAME_X_DISPLAY_INFO (f), dialog_id);
+  popup_get_selection ((XEvent *) 0, FRAME_DISPLAY_INFO (f), dialog_id);
 
   lw_destroy_all_widgets (dialog_id);
 
@@ -1216,7 +1130,7 @@ is_simple_dialog (Lisp_Object contents)
 }
 
 static Lisp_Object
-simple_dialog_show (FRAME_PTR f, Lisp_Object contents, Lisp_Object header)
+simple_dialog_show (struct frame *f, Lisp_Object contents, Lisp_Object header)
 {
   int answer;
   UINT type;
@@ -1405,6 +1319,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
                 nlen++;
             }
         }
+#ifndef NTGUI_UNICODE
       else
         {
           /* If encoded with the system codepage, use multibyte string
@@ -1415,6 +1330,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
                 nlen++;
             }
         }
+#endif /* !NTGUI_UNICODE */
 
       if (nlen > orig_len)
         {
@@ -1429,6 +1345,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
                     *q++ = *p;
                   *q++ = *p++;
                 }
+#ifndef NTGUI_UNICODE
               else
                 {
                   if (_mbsnextc (p) == '&')
@@ -1440,6 +1357,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
                   p = _mbsinc (p);
                   q = _mbsinc (q);
                 }
+#endif /* !NTGUI_UNICODE */
             }
           *q = '\0';
         }
@@ -1483,9 +1401,11 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
 
       utf8to16 (out_string, utf8_len, utf16_string);
       return_value = unicode_append_menu (menu, fuFlags,
-                                         item != NULL ? (UINT) item
-                                           : (UINT) wv->call_data,
+                                         item != NULL ? (UINT_PTR) item
+                                           : (UINT_PTR) wv->call_data,
                                          utf16_string);
+
+#ifndef NTGUI_UNICODE /* Fallback does not apply when always UNICODE */
       if (!return_value)
        {
          /* On W9x/ME, Unicode menus are not supported, though AppendMenuW
@@ -1496,7 +1416,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
             of minor importance compared with menus not working at all.  */
          return_value =
            AppendMenu (menu, fuFlags,
-                       item != NULL ? (UINT) item: (UINT) wv->call_data,
+                       item != NULL ? (UINT_PTR) item: (UINT_PTR) wv->call_data,
                        out_string);
          /* Don't use Unicode menus in future, unless this is Windows
             NT or later, where a failure of AppendMenuW does NOT mean
@@ -1504,6 +1424,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
          if (osinfo_cache.dwPlatformId != VER_PLATFORM_WIN32_NT)
            unicode_append_menu = NULL;
        }
+#endif /* NTGUI_UNICODE */
 
       if (unicode_append_menu && (fuFlags & MF_OWNERDRAW))
        local_free (out_string);
@@ -1513,7 +1434,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
       return_value =
        AppendMenu (menu,
                    fuFlags,
-                   item != NULL ? (UINT) item : (UINT) wv->call_data,
+                   item != NULL ? (UINT_PTR) item : (UINT_PTR) wv->call_data,
                    out_string );
     }
 
@@ -1550,7 +1471,7 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
            }
 
          set_menu_item_info (menu,
-                             item != NULL ? (UINT) item : (UINT) wv->call_data,
+                             item != NULL ? (UINT_PTR) item : (UINT_PTR) wv->call_data,
                              FALSE, &info);
        }
     }
@@ -1680,21 +1601,15 @@ w32_free_menu_strings (HWND hwnd)
   current_popup_menu = NULL;
 }
 
-#endif /* HAVE_MENUS */
-
 /* The following is used by delayed window autoselection.  */
 
 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;
+  struct frame *f;
   f = SELECTED_FRAME ();
   return (f->output_data.w32->menubar_active > 0) ? Qt : Qnil;
-#else
-  return Qnil;
-#endif /* HAVE_MENUS */
 }
 
 void
@@ -1707,9 +1622,6 @@ syms_of_w32menu (void)
   DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
 
   defsubr (&Smenu_or_popup_active_p);
-#ifdef HAVE_MENUS
-  defsubr (&Sx_popup_dialog);
-#endif
 }
 
 /*
@@ -1723,10 +1635,12 @@ syms_of_w32menu (void)
 void
 globals_of_w32menu (void)
 {
+#ifndef NTGUI_UNICODE
   /* 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");
+#endif /* !NTGUI_UNICODE */
 }