* xselect.c (x_own_selection, x_handle_selection_clear)
[bpt/emacs.git] / src / w32fns.c
index c665bba..41a1994 100644 (file)
@@ -1,12 +1,12 @@
 /* Graphical user interface functions for the Microsoft W32 API.
    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-                 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+                 2001, 2002, 2003, 2004, 2005, 2006, 2007 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,
@@ -48,10 +48,12 @@ Boston, MA 02110-1301, USA.  */
 
 #include "bitmaps/gray.xbm"
 
+#include <commctrl.h>
 #include <commdlg.h>
 #include <shellapi.h>
 #include <ctype.h>
 #include <winspool.h>
+#include <objbase.h>
 
 #include <dlgs.h>
 #define FILE_NAME_TEXT_FIELD edt1
@@ -297,6 +299,10 @@ extern int w32_use_visible_system_caret;
 
 static HWND w32_visible_system_caret_hwnd;
 
+/* From w32menu.c  */
+extern HMENU current_popup_menu;
+static int menubar_in_use = 0;
+
 \f
 /* Error if we are not connected to MS-Windows.  */
 void
@@ -431,20 +437,21 @@ x_real_positions (f, xptr, yptr)
   POINT pt;
   RECT rect;
 
-  GetClientRect(FRAME_W32_WINDOW(f), &rect);
-  AdjustWindowRect(&rect, f->output_data.w32->dwStyle, FRAME_EXTERNAL_MENU_BAR(f));
+  /* Get the bounds of the WM window.  */
+  GetWindowRect (FRAME_W32_WINDOW (f), &rect);
 
-  pt.x = rect.left;
-  pt.y = rect.top;
+  pt.x = 0;
+  pt.y = 0;
 
-  ClientToScreen (FRAME_W32_WINDOW(f), &pt);
+  /* Convert (0, 0) in the client area to screen co-ordinates.  */
+  ClientToScreen (FRAME_W32_WINDOW (f), &pt);
 
   /* Remember x_pixels_diff and y_pixels_diff.  */
   f->x_pixels_diff = pt.x - rect.left;
   f->y_pixels_diff = pt.y - rect.top;
 
-  *xptr = pt.x;
-  *yptr = pt.y;
+  *xptr = rect.left;
+  *yptr = rect.top;
 }
 
 \f
@@ -838,11 +845,11 @@ w32_color_map_lookup (colorname)
 
   BLOCK_INPUT;
 
-  for (tail = Vw32_color_map; !NILP (tail); tail = Fcdr (tail))
+  for (tail = Vw32_color_map; CONSP (tail); tail = XCDR (tail))
     {
       register Lisp_Object elt, tem;
 
-      elt = Fcar (tail);
+      elt = XCAR (tail);
       if (!CONSP (elt)) continue;
 
       tem = Fcar (elt);
@@ -1683,7 +1690,7 @@ x_set_icon_name (f, arg, oldval)
       if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
        return;
     }
-  else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
+  else if (!NILP (arg) || NILP (oldval))
     return;
 
   f->icon_name = arg;
@@ -1812,10 +1819,8 @@ x_set_tool_bar_lines (f, value, oldval)
      below the menu bar.  */
   if (FRAME_W32_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
     {
-      updating_frame = f;
-      clear_frame ();
+      clear_frame (f);
       clear_current_matrices (f);
-      updating_frame = NULL;
     }
 
   /* If the tool bar gets smaller, the internal border below it
@@ -1930,15 +1935,7 @@ x_implicitly_set_name (f, arg, oldval)
 }
 \f
 /* Change the title of frame F to NAME.
-   If NAME is nil, use the frame name as the title.
-
-   If EXPLICIT is non-zero, that indicates that lisp code is setting the
-       name; if NAME is a string, set F's name to NAME and set
-       F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
-
-   If EXPLICIT is zero, that indicates that Emacs redisplay code is
-       suggesting a new name, which lisp code should override; if
-       F->explicit_name is set, ignore the new name; otherwise, set it.  */
+   If NAME is nil, use the frame name as the title.  */
 
 void
 x_set_title (f, name, old_name)
@@ -2066,6 +2063,8 @@ w32_createwindow (f)
 {
   HWND hwnd;
   RECT rect;
+  Lisp_Object top = Qunbound;
+  Lisp_Object left = Qunbound;
 
   rect.left = rect.top = 0;
   rect.right = FRAME_PIXEL_WIDTH (f);
@@ -2081,12 +2080,25 @@ w32_createwindow (f)
       w32_init_class (hinst);
     }
 
+  if (f->size_hint_flags & USPosition || f->size_hint_flags & PPosition)
+    {
+      XSETINT (left, f->left_pos);
+      XSETINT (top, f->top_pos);
+    }
+  else if (EQ (left, Qunbound) && EQ (top, Qunbound))
+    {
+      /* When called with RES_TYPE_NUMBER, w32_get_arg will return zero
+        for anything that is not a number and is not Qunbound.  */
+      left = w32_get_arg (Qnil, Qleft, "left", "Left", RES_TYPE_NUMBER);
+      top = w32_get_arg (Qnil, Qtop, "top", "Top", RES_TYPE_NUMBER);
+    }
+
   FRAME_W32_WINDOW (f) = hwnd
     = CreateWindow (EMACS_CLASS,
                    f->namebuf,
                    f->output_data.w32->dwStyle | WS_CLIPCHILDREN,
-                   f->left_pos,
-                   f->top_pos,
+                   EQ (left, Qunbound) ? CW_USEDEFAULT : XINT (left),
+                   EQ (top, Qunbound) ? CW_USEDEFAULT : XINT (top),
                    rect.right - rect.left,
                    rect.bottom - rect.top,
                    NULL,
@@ -2107,6 +2119,11 @@ w32_createwindow (f)
 
       /* Do this to discard the default setting specified by our parent. */
       ShowWindow (hwnd, SW_HIDE);
+
+      /* Update frame positions. */
+      GetWindowRect (hwnd, &rect);
+      f->left_pos = rect.left;
+      f->top_pos = rect.top;
     }
 }
 
@@ -2490,6 +2507,13 @@ w32_msg_pump (deferred_msg * msg_buf)
              /* Produced by complete_deferred_msg; just ignore.  */
              break;
            case WM_EMACS_CREATEWINDOW:
+              /* Initialize COM for this window. Even though we don't use it,
+                 some third party shell extensions can cause it to be used in
+                 system dialogs, which causes a crash if it is not initialized.
+                 This is a known bug in Windows, which was fixed long ago, but
+                 the patch for XP is not publically available until XP SP3,
+                 and older versions will never be patched.  */
+              CoInitialize (NULL);
              w32_createwindow ((struct frame *) msg.wParam);
              if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
                abort ();
@@ -2669,9 +2693,8 @@ cancel_all_deferred_msgs ()
   PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
 }
 
-DWORD
-w32_msg_worker (dw)
-     DWORD dw;
+DWORD WINAPI
+w32_msg_worker (void *arg)
 {
   MSG msg;
   deferred_msg dummy_buf;
@@ -3190,6 +3213,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
              }
            wmsg.dwModifiers = w32_get_modifiers ();
            my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+           signal_user_input ();
 
            /* Clear message buffer. */
            saved_mouse_button_msg.msg.hwnd = 0;
@@ -3247,6 +3271,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
          }
        wmsg.dwModifiers = w32_get_modifiers ();
        my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+       signal_user_input ();
 
        /* Always clear message buffer and cancel timer. */
        saved_mouse_button_msg.msg.hwnd = 0;
@@ -3297,6 +3322,14 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
       return (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONUP);
 
     case WM_MOUSEMOVE:
+      /* Ignore mouse movements as long as the menu is active.  These
+        movements are processed by the window manager anyway, and
+        it's wrong to handle them as if they happened on the
+        underlying frame.  */
+      f = x_window_to_frame (dpyinfo, hwnd);
+      if (f && f->output_data.w32->menubar_active)
+       return 0;
+
       /* If the mouse has just moved into the frame, start tracking
         it, so we will be notified when it leaves the frame.  Mouse
         tracking only works under W98 and NT4 and later. On earlier
@@ -3343,16 +3376,20 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
       return 0;
 
     case WM_MOUSEWHEEL:
+    case WM_DROPFILES:
       wmsg.dwModifiers = w32_get_modifiers ();
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
       signal_user_input ();
       return 0;
 
-    case WM_DROPFILES:
+    case WM_MOUSEHWHEEL:
       wmsg.dwModifiers = w32_get_modifiers ();
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
       signal_user_input ();
-      return 0;
+      /* Non-zero must be returned when WM_MOUSEHWHEEL messages are
+         handled, to prevent the system trying to handle it by faking
+         scroll bar events.  */
+      return 1;
 
     case WM_TIMER:
       /* Flush out saved messages if necessary. */
@@ -3382,11 +3419,14 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
          KillTimer (hwnd, menu_free_timer);
          menu_free_timer = 0;
          f = x_window_to_frame (dpyinfo, hwnd);
-         if (!f->output_data.w32->menu_command_in_progress)
+          /* If a popup menu is active, don't wipe its strings.  */
+         if (menubar_in_use
+              && current_popup_menu == NULL)
            {
              /* Free memory used by owner-drawn and help-echo strings.  */
              w32_free_menu_strings (hwnd);
              f->output_data.w32->menubar_active = 0;
+              menubar_in_use = 0;
            }
        }
       return 0;
@@ -3438,16 +3478,21 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
        if (find_deferred_msg (hwnd, msg) != NULL)
          abort ();
 
+        menubar_in_use = 1;
+
        return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam);
       }
 
     case WM_EXITMENULOOP:
       f = x_window_to_frame (dpyinfo, hwnd);
 
-      /* If a menu command is not already in progress, check again
-        after a short delay, since Windows often (always?) sends the
-        WM_EXITMENULOOP before the corresponding WM_COMMAND message.  */
-      if (f && !f->output_data.w32->menu_command_in_progress)
+      /* If a menu is still active, check again after a short delay,
+        since Windows often (always?) sends the WM_EXITMENULOOP
+        before the corresponding WM_COMMAND message.
+         Don't do this if a popup menu is active, since it is only
+         menubar menus that require cleaning up in this way.
+      */
+      if (f && menubar_in_use && current_popup_menu == NULL)
        menu_free_timer = SetTimer (hwnd, MENU_FREE_ID, MENU_FREE_DELAY, NULL);
       goto dflt;
 
@@ -3602,10 +3647,10 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
        }
       goto command;
     case WM_COMMAND:
+      menubar_in_use = 0;
       f = x_window_to_frame (dpyinfo, hwnd);
       if (f && HIWORD (wParam) == 0)
        {
-         f->output_data.w32->menu_command_in_progress = 1;
          if (menu_free_timer)
            {
              KillTimer (hwnd, menu_free_timer);
@@ -3619,6 +3664,10 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
       goto dflt;
 
+    case WM_DESTROY:
+      CoUninitialize ();
+      return 0;
+
     case WM_CLOSE:
       wmsg.dwModifiers = w32_get_modifiers ();
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
@@ -3677,8 +3726,11 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
                   However for top/left sizing we will need to fix the X
                   and Y positions as well.  */
 
-               lppos->cx -= wdiff;
-               lppos->cy -= hdiff;
+               int cx_mintrack = GetSystemMetrics (SM_CXMINTRACK);
+               int cy_mintrack = GetSystemMetrics (SM_CYMINTRACK);
+
+               lppos->cx = max (lppos->cx - wdiff, cx_mintrack);
+               lppos->cy = max (lppos->cy - hdiff, cy_mintrack);
 
                if (wp.showCmd != SW_SHOWMAXIMIZED
                    && (lppos->flags & SWP_NOMOVE) == 0)
@@ -3702,9 +3754,6 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
       goto dflt;
 
     case WM_GETMINMAXINFO:
-      /* Hack to correct bug that allows Emacs frames to be resized
-        below the Minimum Tracking Size.  */
-      ((LPMINMAXINFO) lParam)->ptMinTrackSize.y++;
       /* Hack to allow resizing the Emacs frame above the screen size.
         Note that Windows 9x limits coordinates to 16-bits.  */
       ((LPMINMAXINFO) lParam)->ptMaxTrackSize.x = 32767;
@@ -4126,7 +4175,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
     display = Qnil;
   dpyinfo = check_x_display_info (display);
 #ifdef MULTI_KBOARD
-  kb = dpyinfo->kboard;
+  kb = dpyinfo->terminal->kboard;
 #else
   kb = &the_only_kboard;
 #endif
@@ -4174,6 +4223,9 @@ This function is an internal primitive--use `make-frame' instead.  */)
   /* By default, make scrollbars the system standard width. */
   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
 
+  f->terminal = dpyinfo->terminal;
+  f->terminal->reference_count++;
+
   f->output_method = output_w32;
   f->output_data.w32 =
     (struct w32_output *) xmalloc (sizeof (struct w32_output));
@@ -4369,17 +4421,6 @@ This function is an internal primitive--use `make-frame' instead.  */)
   x_wm_set_size_hint (f, window_prompting, 0);
   UNBLOCK_INPUT;
 
-  /* Avoid a bug that causes the new frame to never become visible if
-     an echo area message is displayed during the following call1.  */
-  specbind(Qredisplay_dont_pause, Qt);
-
-  /* Set up faces after all frame parameters are known.  This call
-     also merges in face attributes specified for new frames.  If we
-     don't do this, the `menu' face for instance won't have the right
-     colors, and the menu bar won't appear in the specified colors for
-     new frames.  */
-  call1 (Qface_set_after_frame_default, frame);
-
   /* Make the window appear on the frame and enable display, unless
      the caller says not to.  However, with explicit parent, Emacs
      cannot control visibility, so don't try.  */
@@ -4399,6 +4440,22 @@ This function is an internal primitive--use `make-frame' instead.  */)
        /* Must have been Qnil.  */
        ;
     }
+
+  /* Initialize `default-minibuffer-frame' in case this is the first
+     frame on this terminal.  */
+  if (FRAME_HAS_MINIBUF_P (f)
+      && (!FRAMEP (kb->Vdefault_minibuffer_frame)
+          || !FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame))))
+    kb->Vdefault_minibuffer_frame = frame;
+
+  /* All remaining specified parameters, which have not been "used"
+     by x_get_arg and friends, now go in the misc. alist of the frame.  */
+  for (tem = parameters; CONSP (tem); tem = XCDR (tem))
+    if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
+      f->param_alist = Fcons (XCAR (tem), f->param_alist);
+
+  store_frame_param (f, Qwindow_system, Qw32);
+  
   UNGCPRO;
 
   /* Make sure windows on this frame appear in calls to next-window
@@ -4424,7 +4481,7 @@ x_get_focus_frame (frame)
   return xfocus;
 }
 
-DEFUN ("w32-focus-frame", Fw32_focus_frame, Sw32_focus_frame, 1, 1, 0,
+DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
        doc: /* Give FRAME input focus, raising to foreground if necessary.  */)
   (frame)
      Lisp_Object frame;
@@ -5305,9 +5362,9 @@ w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
 
   if (lplogfont->lfHeight)
     {
-      sprintf (height_pixels, "%u", abs (lplogfont->lfHeight));
+      sprintf (height_pixels, "%u", eabs (lplogfont->lfHeight));
       sprintf (height_dpi, "%u",
-              abs (lplogfont->lfHeight) * 720 / display_resy);
+              eabs (lplogfont->lfHeight) * 720 / display_resy);
     }
   else
     {
@@ -5529,7 +5586,7 @@ x_to_w32_font (lpxstr, lplogfont)
     }
 
   /* This makes TrueType fonts work better. */
-  lplogfont->lfHeight = - abs (lplogfont->lfHeight);
+  lplogfont->lfHeight = - eabs (lplogfont->lfHeight);
 
   return (TRUE);
 }
@@ -6197,7 +6254,7 @@ w32_query_font (struct frame *f, char *fontname)
 
   for (i = 0; i < one_w32_display_info.n_fonts ;i++, pfi++)
     {
-      if (strcmp(pfi->name, fontname) == 0) return pfi;
+      if (stricmp(pfi->name, fontname) == 0) return pfi;
     }
 
   return NULL;
@@ -6316,17 +6373,12 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
   CHECK_STRING (color);
 
   if (w32_defined_color (f, SDATA (color), &foo, 0))
-    {
-      Lisp_Object rgb[3];
-
-      rgb[0] = make_number ((GetRValue (foo.pixel) << 8)
-                            | GetRValue (foo.pixel));
-      rgb[1] = make_number ((GetGValue (foo.pixel) << 8)
-                            | GetGValue (foo.pixel));
-      rgb[2] = make_number ((GetBValue (foo.pixel) << 8)
-                            | GetBValue (foo.pixel));
-      return Flist (3, rgb);
-    }
+    return list3 (make_number ((GetRValue (foo.pixel) << 8)
+                              | GetRValue (foo.pixel)),
+                 make_number ((GetGValue (foo.pixel) << 8)
+                              | GetGValue (foo.pixel)),
+                 make_number ((GetBValue (foo.pixel) << 8)
+                              | GetBValue (foo.pixel)));
   else
     return Qnil;
 }
@@ -6678,8 +6730,10 @@ terminate Emacs if we can't open the connection.  */)
   if (! NILP (xrm_string))
     CHECK_STRING (xrm_string);
 
+#if 0
   if (! EQ (Vwindow_system, intern ("w32")))
     error ("Not using Microsoft Windows");
+#endif
 
   /* Allow color mapping to be defined externally; first look in user's
      HOME directory, then in Emacs etc dir for a file called rgb.txt. */
@@ -6784,7 +6838,7 @@ DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
   Lisp_Object tail, result;
 
   result = Qnil;
-  for (tail = w32_display_name_list; ! NILP (tail); tail = XCDR (tail))
+  for (tail = w32_display_name_list; CONSP (tail); tail = XCDR (tail))
     result = Fcons (XCAR (XCAR (tail)), result);
 
   return result;
@@ -7181,7 +7235,7 @@ x_create_tip_frame (dpyinfo, parms, text)
   Vx_resource_name = Vinvocation_name;
 
 #ifdef MULTI_KBOARD
-  kb = dpyinfo->kboard;
+  kb = dpyinfo->terminal->kboard;
 #else
   kb = &the_only_kboard;
 #endif
@@ -7219,6 +7273,8 @@ x_create_tip_frame (dpyinfo, parms, text)
      the frame is live, as per FRAME_LIVE_P.  If we get a signal
      from this point on, x_destroy_window might screw up reference
      counts etc.  */
+  f->terminal = dpyinfo->terminal;
+  f->terminal->reference_count++;
   f->output_method = output_w32;
   f->output_data.w32 =
     (struct w32_output *) xmalloc (sizeof (struct w32_output));
@@ -7382,6 +7438,8 @@ x_create_tip_frame (dpyinfo, parms, text)
                                              Qnil));
   }
 
+  Fmodify_frame_parameters (frame, Fcons (Fcons (Qwindow_system, Qw32), Qnil));
+
   f->no_split = 1;
 
   UNGCPRO;
@@ -7473,6 +7531,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
        doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
 A tooltip window is a small window displaying a string.
 
+This is an internal function; Lisp code should call `tooltip-show'.
+
 FRAME nil or omitted means use the selected frame.
 
 PARMS is an optional list of frame parameters which can be
@@ -7679,9 +7739,12 @@ Text larger than the specified size is clipped.  */)
     AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
                      FRAME_EXTERNAL_MENU_BAR (f));
 
-    /* Position and size tooltip, and put it in the topmost group.  */
+    /* Position and size tooltip, and put it in the topmost group.
+       The add-on of 3 to the 5th argument is a kludge: without it,
+       some fonts cause the last character of the tip to be truncated,
+       for some obscure reason.  */
     SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
-                 root_x, root_y, rect.right - rect.left,
+                 root_x, root_y, rect.right - rect.left + 3,
                  rect.bottom - rect.top, SWP_NOACTIVATE);
 
     /* Ensure tooltip is on top of other topmost windows (eg menus).  */
@@ -7872,9 +7935,9 @@ If ONLY-DIR-P is non-nil, the user can only select directories.  */)
     /* Apparently NT4 crashes if you give it an unexpected size.
        I'm not sure about Windows 9x, so play it safe.  */
     if (w32_major_version > 4 && w32_major_version < 95)
-      file_details->lStructSize = sizeof (new_file_details);
+      file_details->lStructSize = sizeof (NEWOPENFILENAME);
     else
-      file_details->lStructSize = sizeof (file_details);
+      file_details->lStructSize = sizeof (OPENFILENAME);
 
     file_details->hwndOwner = FRAME_W32_WINDOW (f);
     /* Undocumented Bug in Common File Dialog:
@@ -7948,8 +8011,12 @@ If ONLY-DIR-P is non-nil, the user can only select directories.  */)
  ***********************************************************************/
 
 DEFUN ("w32-select-font", Fw32_select_font, Sw32_select_font, 0, 2, 0,
-       doc: /* Select a font using the W32 font dialog.
-Returns an X font string corresponding to the selection.  */)
+       doc: /* Select a font for the named FRAME using the W32 font dialog.
+Returns an X-style font string corresponding to the selection.
+
+If FRAME is omitted or nil, it defaults to the selected frame.
+If INCLUDE-PROPORTIONAL is non-nil, include proportional fonts
+in the font selection dialog. */)
   (frame, include_proportional)
      Lisp_Object frame, include_proportional;
 {
@@ -8024,17 +8091,39 @@ DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
        doc: /* Get Windows to perform OPERATION on DOCUMENT.
 This is a wrapper around the ShellExecute system function, which
 invokes the application registered to handle OPERATION for DOCUMENT.
-OPERATION is typically \"open\", \"print\" or \"explore\" (but can be
-nil for the default action), and DOCUMENT is typically the name of a
-document file or URL, but can also be a program executable to run or
-a directory to open in the Windows Explorer.
-
-If DOCUMENT is a program executable, PARAMETERS can be a string
-containing command line parameters, but otherwise should be nil.
 
-SHOW-FLAG can be used to control whether the invoked application is hidden
-or minimized.  If SHOW-FLAG is nil, the application is displayed normally,
-otherwise it is an integer representing a ShowWindow flag:
+OPERATION is either nil or a string that names a supported operation.
+What operations can be used depends on the particular DOCUMENT and its
+handler application, but typically it is one of the following common
+operations:
+
+ \"open\"    - open DOCUMENT, which could be a file, a directory, or an
+               executable program.  If it is an application, that
+               application is launched in the current buffer's default
+               directory.  Otherwise, the application associated with
+               DOCUMENT is launched in the buffer's default directory.
+ \"print\"   - print DOCUMENT, which must be a file
+ \"explore\" - start the Windows Explorer on DOCUMENT
+ \"edit\"    - launch an editor and open DOCUMENT for editing; which
+               editor is launched depends on the association for the
+               specified DOCUMENT
+ \"find\"    - initiate search starting from DOCUMENT which must specify
+               a directory
+ nil       - invoke the default OPERATION, or \"open\" if default is
+               not defined or unavailable
+
+DOCUMENT is typically the name of a document file or a URL, but can
+also be a program executable to run, or a directory to open in the
+Windows Explorer.
+
+If DOCUMENT is a program executable, the optional arg PARAMETERS can
+be a string containing command line parameters that will be passed to
+the program; otherwise, PARAMETERS should be nil or unspecified.
+
+Second optional argument SHOW-FLAG can be used to control how the
+application will be displayed when it is invoked.  If SHOW-FLAG is nil
+or unspceified, the application is displayed normally, otherwise it is
+an integer representing a ShowWindow flag:
 
   0 - start hidden
   1 - start normally
@@ -8307,6 +8396,30 @@ is set to off if the low bit of NEW-STATE is zero, otherwise on.  */)
     }
   return Qnil;
 }
+
+DEFUN ("w32-window-exists-p", Fw32_window_exists_p, Sw32_window_exists_p,
+       2, 2, 0,
+       doc: /* Return non-nil if a window exists with the specified CLASS and NAME.
+
+This is a direct interface to the Windows API FindWindow function.  */)
+  (class, name)
+Lisp_Object class, name;
+{
+  HWND hnd;
+
+  if (!NILP (class))
+    CHECK_STRING (class);
+  if (!NILP (name))
+    CHECK_STRING (name);
+
+  hnd = FindWindow (STRINGP (class) ? ((LPCTSTR) SDATA (class)) : NULL,
+                   STRINGP (name)  ? ((LPCTSTR) SDATA (name))  : NULL);
+  if (!hnd)
+    return Qnil;
+  return Qt;
+}
+
+
 \f
 DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
        doc: /* Return storage information about the file system FILENAME is on.
@@ -8568,14 +8681,15 @@ syms_of_w32fns ()
   Vw32_color_map = Qnil;
 
   DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system,
-              doc: /* Non-nil if alt key presses are passed on to Windows.
-When non-nil, for example, alt pressed and released and then space will
-open the System menu.  When nil, Emacs silently swallows alt key events.  */);
+              doc: /* Non-nil if Alt key presses are passed on to Windows.
+When non-nil, for example, Alt pressed and released and then space will
+open the System menu.  When nil, Emacs processes the Alt key events, and
+then silently swallows them.  */);
   Vw32_pass_alt_to_system = Qnil;
 
   DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta,
-              doc: /* Non-nil if the alt key is to be considered the same as the meta key.
-When nil, Emacs will translate the alt key to the Alt modifier, and not Meta.  */);
+              doc: /* Non-nil if the Alt key is to be considered the same as the META key.
+When nil, Emacs will translate the Alt key to the ALT modifier, not to META.  */);
   Vw32_alt_is_meta = Qt;
 
   DEFVAR_INT ("w32-quit-key", &w32_quit_key,
@@ -8584,14 +8698,32 @@ When nil, Emacs will translate the alt key to the Alt modifier, and not Meta.  *
 
   DEFVAR_LISP ("w32-pass-lwindow-to-system",
               &Vw32_pass_lwindow_to_system,
-              doc: /* Non-nil if the left \"Windows\" key is passed on to Windows.
-When non-nil, the Start menu is opened by tapping the key.  */);
+              doc: /* If non-nil, the left \"Windows\" key is passed on to Windows.
+
+When non-nil, the Start menu is opened by tapping the key.
+If you set this to nil, the left \"Windows\" key is processed by Emacs
+according to the value of `w32-lwindow-modifier', which see.
+
+Note that some combinations of the left \"Windows\" key with other keys are
+caught by Windows at low level, and so binding them in Emacs will have no
+effect.  For example, <lwindow>-r always pops up the Windows Run dialog,
+<lwindow>-<Pause> pops up the "System Properties" dialog, etc.  However, see
+the doc string of `w32-phantom-key-code'.  */);
   Vw32_pass_lwindow_to_system = Qt;
 
   DEFVAR_LISP ("w32-pass-rwindow-to-system",
               &Vw32_pass_rwindow_to_system,
-              doc: /* Non-nil if the right \"Windows\" key is passed on to Windows.
-When non-nil, the Start menu is opened by tapping the key.  */);
+              doc: /* If non-nil, the right \"Windows\" key is passed on to Windows.
+
+When non-nil, the Start menu is opened by tapping the key.
+If you set this to nil, the right \"Windows\" key is processed by Emacs
+according to the value of `w32-rwindow-modifier', which see.
+
+Note that some combinations of the right \"Windows\" key with other keys are
+caught by Windows at low level, and so binding them in Emacs will have no
+effect.  For example, <rwindow>-r always pops up the Windows Run dialog,
+<rwindow>-<Pause> pops up the "System Properties" dialog, etc.  However, see
+the doc string of `w32-phantom-key-code'.  */);
   Vw32_pass_rwindow_to_system = Qt;
 
   DEFVAR_LISP ("w32-phantom-key-code",
@@ -8608,29 +8740,29 @@ acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
 
   DEFVAR_LISP ("w32-enable-num-lock",
               &Vw32_enable_num_lock,
-              doc: /* Non-nil if Num Lock should act normally.
-Set to nil to see Num Lock as the key `kp-numlock'.  */);
+              doc: /* If non-nil, the Num Lock key acts normally.
+Set to nil to handle Num Lock as the `kp-numlock' key.  */);
   Vw32_enable_num_lock = Qt;
 
   DEFVAR_LISP ("w32-enable-caps-lock",
               &Vw32_enable_caps_lock,
-              doc: /* Non-nil if Caps Lock should act normally.
-Set to nil to see Caps Lock as the key `capslock'.  */);
+              doc: /* If non-nil, the Caps Lock key acts normally.
+Set to nil to handle Caps Lock as the `capslock' key.  */);
   Vw32_enable_caps_lock = Qt;
 
   DEFVAR_LISP ("w32-scroll-lock-modifier",
               &Vw32_scroll_lock_modifier,
-              doc: /* Modifier to use for the Scroll Lock on state.
+              doc: /* Modifier to use for the Scroll Lock ON state.
 The value can be hyper, super, meta, alt, control or shift for the
-respective modifier, or nil to see Scroll Lock as the key `scroll'.
-Any other value will cause the key to be ignored.  */);
+respective modifier, or nil to handle Scroll Lock as the `scroll' key.
+Any other value will cause the Scroll Lock key to be ignored.  */);
   Vw32_scroll_lock_modifier = Qt;
 
   DEFVAR_LISP ("w32-lwindow-modifier",
               &Vw32_lwindow_modifier,
               doc: /* Modifier to use for the left \"Windows\" key.
 The value can be hyper, super, meta, alt, control or shift for the
-respective modifier, or nil to appear as the key `lwindow'.
+respective modifier, or nil to appear as the `lwindow' key.
 Any other value will cause the key to be ignored.  */);
   Vw32_lwindow_modifier = Qnil;
 
@@ -8638,7 +8770,7 @@ Any other value will cause the key to be ignored.  */);
               &Vw32_rwindow_modifier,
               doc: /* Modifier to use for the right \"Windows\" key.
 The value can be hyper, super, meta, alt, control or shift for the
-respective modifier, or nil to appear as the key `rwindow'.
+respective modifier, or nil to appear as the `rwindow' key.
 Any other value will cause the key to be ignored.  */);
   Vw32_rwindow_modifier = Qnil;
 
@@ -8646,7 +8778,7 @@ Any other value will cause the key to be ignored.  */);
               &Vw32_apps_modifier,
               doc: /* Modifier to use for the \"Apps\" key.
 The value can be hyper, super, meta, alt, control or shift for the
-respective modifier, or nil to appear as the key `apps'.
+respective modifier, or nil to appear as the `apps' key.
 Any other value will cause the key to be ignored.  */);
   Vw32_apps_modifier = Qnil;
 
@@ -8662,7 +8794,7 @@ Any other value will cause the key to be ignored.  */);
              &w32_mouse_button_tolerance,
              doc: /* Analogue of double click interval for faking middle mouse events.
 The value is the minimum time in milliseconds that must elapse between
-left/right button down events before they are considered distinct events.
+left and right button down events before they are considered distinct events.
 If both mouse buttons are depressed within this interval, a middle mouse
 button down event is generated instead.  */);
   w32_mouse_button_tolerance = GetDoubleClickTime () / 2;
@@ -8677,7 +8809,7 @@ reported as lisp events.  */);
 
   DEFVAR_BOOL ("w32-pass-extra-mouse-buttons-to-system",
               &w32_pass_extra_mouse_buttons_to_system,
-              doc: /* Non-nil if the fourth and fifth mouse buttons are passed to Windows.
+              doc: /* If non-nil, the fourth and fifth mouse buttons are passed to Windows.
 Recent versions of Windows support mice with up to five buttons.
 Since most applications don't support these extra buttons, most mouse
 drivers will allow you to map them to functions at the system level.
@@ -8854,6 +8986,7 @@ versions of Windows) characters.  */);
 
     staticpro (&Qw32_charset_unicode);
     Qw32_charset_unicode = intern ("w32-charset-unicode");
+  }
 #endif
 
 #if 0 /* TODO: Port to W32 */
@@ -8883,10 +9016,10 @@ versions of Windows) characters.  */);
   defsubr (&Sx_close_connection);
   defsubr (&Sx_display_list);
   defsubr (&Sx_synchronize);
+  defsubr (&Sx_focus_frame);
 
   /* W32 specific functions */
 
-  defsubr (&Sw32_focus_frame);
   defsubr (&Sw32_select_font);
   defsubr (&Sw32_define_rgb_color);
   defsubr (&Sw32_default_color_map);
@@ -8898,6 +9031,7 @@ versions of Windows) characters.  */);
   defsubr (&Sw32_registered_hot_keys);
   defsubr (&Sw32_reconstruct_hot_key);
   defsubr (&Sw32_toggle_lock_key);
+  defsubr (&Sw32_window_exists_p);
   defsubr (&Sw32_find_bdf_fonts);
 
   defsubr (&Sfile_system_info);
@@ -8959,6 +9093,9 @@ void globals_of_w32fns ()
              &w32_ansi_code_page,
              doc: /* The ANSI code page used by the system.  */);
   w32_ansi_code_page = GetACP ();
+
+  /* MessageBox does not work without this when linked to comctl32.dll 6.0.  */
+  InitCommonControls ();
 }
 
 #undef abort