(w32_menu_show, w32_dialog_show): Call Fsignal to quit
[bpt/emacs.git] / src / w32menu.c
index f3f3eb7..11af1d6 100644 (file)
@@ -1,5 +1,6 @@
 /* Menu support for GNU Emacs on the Microsoft W32 API.
-   Copyright (C) 1986,88,93,94,96,98,1999,2003  Free Software Foundation, Inc.
+   Copyright (C) 1986, 1988, 1993, 1994, 1996, 1998, 1999, 2002, 2003,
+                 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -15,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include <config.h>
 #include <signal.h>
@@ -143,11 +144,6 @@ typedef BOOL (WINAPI * SetMenuItemInfoA_Proc) (
     IN UINT,
     IN BOOL,
     IN LPCMENUITEMINFOA);
-typedef BOOL (WINAPI * AppendMenuW_Proc) (
-    IN HMENU,
-    IN UINT,
-    IN UINT_PTR,
-    IN LPCWSTR);
 
 GetMenuItemInfoA_Proc get_menu_item_info = NULL;
 SetMenuItemInfoA_Proc set_menu_item_info = NULL;
@@ -742,7 +738,8 @@ cached information about equivalent key sequences.  */)
 
       XSETFRAME (Vmenu_updating_frame, f);
     }
-  Vmenu_updating_frame = Qnil;
+  else
+    Vmenu_updating_frame = Qnil;
 #endif /* HAVE_MENUS */
 
   title = Qnil;
@@ -822,8 +819,10 @@ cached information about equivalent key sequences.  */)
     }
 
 #ifdef HAVE_MENUS
-  /* If resources from a previous popup menu exist yet, does nothing
-     until the `menu_free_timer' has freed them (see w32fns.c).
+  /* If resources from a previous popup menu still exist, does nothing
+     until the `menu_free_timer' has freed them (see w32fns.c). This
+     can occur if you press ESC or click outside a menu without selecting
+     a menu item.
   */
   if (current_popup_menu)
     {
@@ -840,6 +839,8 @@ cached information about equivalent key sequences.  */)
   UNBLOCK_INPUT;
 
   discard_menu_items ();
+  w32_free_menu_strings (FRAME_W32_WINDOW (f));
+
 #endif /* HAVE_MENUS */
 
   UNGCPRO;
@@ -850,7 +851,7 @@ cached information about equivalent key sequences.  */)
 
 #ifdef HAVE_MENUS
 
-DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 2, 0,
+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.
@@ -865,9 +866,12 @@ 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.)  */)
-  (position, contents)
-     Lisp_Object position, contents;
+\(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". */)
+  (position, contents, header)
+     Lisp_Object position, contents, header;
 {
   FRAME_PTR f = NULL;
   Lisp_Object window;
@@ -954,7 +958,7 @@ on the left of the dialog box and all following items on the right.
 
     /* Display them in a dialog box.  */
     BLOCK_INPUT;
-    selection = w32_dialog_show (f, 0, title, &error_name);
+    selection = w32_dialog_show (f, 0, title, header, &error_name);
     UNBLOCK_INPUT;
 
     discard_menu_items ();
@@ -1445,7 +1449,8 @@ set_frame_menubar (f, first_time, deep_p)
         because it is not reentrant.  */
       specbind (Qdebug_on_next_call, Qnil);
 
-      record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
+      record_unwind_save_match_data ();
+
       if (NILP (Voverriding_local_map_menu_flag))
        {
          specbind (Qoverriding_terminal_local_map, Qnil);
@@ -1989,6 +1994,9 @@ w32_menu_show (f, x, y, for_click, keymaps, title, error)
            }
        }
     }
+  else if (!for_click)
+    /* Make "Cancel" equivalent to C-g.  */
+    Fsignal (Qquit, Qnil);
 
   return Qnil;
 }
@@ -2000,10 +2008,10 @@ static char * button_names [] = {
   "button6", "button7", "button8", "button9", "button10" };
 
 static Lisp_Object
-w32_dialog_show (f, keymaps, title, error)
+w32_dialog_show (f, keymaps, title, header, error)
      FRAME_PTR f;
      int keymaps;
-     Lisp_Object title;
+     Lisp_Object title, header;
      char **error;
 {
   int i, nb_buttons=0;
@@ -2104,11 +2112,17 @@ w32_dialog_show (f, keymaps, title, error)
     wv->name = dialog_name;
     wv->help = Qnil;
 
+    /*  Frame title: 'Q' = Question, 'I' = Information.
+        Can also have 'E' = Error if, one day, we want
+        a popup for errors. */
+    if (NILP(header))
+      dialog_name[0] = 'Q';
+    else
+      dialog_name[0] = 'I';
+
     /* Dialog boxes use a really stupid name encoding
        which specifies how many buttons to use
-       and how many buttons are on the right.
-       The Q means something also.  */
-    dialog_name[0] = 'Q';
+       and how many buttons are on the right. */
     dialog_name[1] = '0' + nb_buttons;
     dialog_name[2] = 'B';
     dialog_name[3] = 'R';
@@ -2175,6 +2189,9 @@ w32_dialog_show (f, keymaps, title, error)
            }
        }
     }
+  else
+    /* Make "Cancel" equivalent to C-g.  */
+    Fsignal (Qquit, Qnil);
 
   return Qnil;
 }
@@ -2315,7 +2332,23 @@ add_menu_item (HMENU menu, widget_value *wv, HMENU item)
                                          item != NULL ? (UINT) item
                                            : (UINT) wv->call_data,
                                          utf16_string);
-      if (fuFlags & MF_OWNERDRAW)
+      if (!return_value)
+       {
+         /* 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
+            happen the first time a menu is used, the encoding is
+            of minor importance compared with menus not working at all.  */
+         return_value =
+           AppendMenu (menu, fuFlags,
+                       item != NULL ? (UINT) item: (UINT) wv->call_data,
+                       out_string);
+         /* Don't use unicode menus in future.  */
+         unicode_append_menu = NULL;
+       }
+
+      if (unicode_append_menu && (fuFlags & MF_OWNERDRAW))
        local_free (out_string);
     }
   else
@@ -2413,8 +2446,11 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags)
       struct frame *f = x_window_to_frame (&one_w32_display_info, owner);
       Lisp_Object frame, help;
 
-      /* No help echo on owner-draw menu items.  */
-      if (flags & MF_OWNERDRAW || flags & MF_POPUP)
+      /* No help echo on owner-draw menu items, or when the keyboard is used
+        to navigate the menus, since tooltips are distracting if they pop
+        up elsewhere.  */
+      if (flags & MF_OWNERDRAW || flags & MF_POPUP
+         || !(flags & MF_MOUSESELECT))
        help = Qnil;
       else
        {