better not use @LaTeX{}, I guess.
[bpt/emacs.git] / src / w32fns.c
index b57e31b..4f07817 100644 (file)
@@ -1,6 +1,6 @@
 /* Graphical user interface functions for the Microsoft W32 API.
-   Copyright (C) 1989, 92, 93, 94, 95, 1996, 1997, 1998, 1999, 2000, 2001
-     Free Software Foundation, Inc.
+   Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+                 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -16,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.  */
 
 /* Added by Kevin Gallo */
 
@@ -64,6 +64,7 @@ extern double atof ();
 extern int w32_console_toggle_lock_key P_ ((int, Lisp_Object));
 extern void w32_menu_display_help P_ ((HWND, HMENU, UINT, UINT));
 extern void w32_free_menu_strings P_ ((HWND));
+extern XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, int));
 
 extern int quit_char;
 
@@ -88,7 +89,7 @@ Lisp_Object Vw32_pass_alt_to_system;
 Lisp_Object Vw32_alt_is_meta;
 
 /* If non-zero, the windows virtual key code for an alternative quit key. */
-Lisp_Object Vw32_quit_key;
+int w32_quit_key;
 
 /* Non nil if left window key events are passed on to Windows (this only
    affects whether "tapping" the key opens the Start menu).  */
@@ -132,11 +133,11 @@ Lisp_Object Vw32_enable_palette;
 
 /* Control how close left/right button down events must be to
    be converted to a middle button down event. */
-Lisp_Object Vw32_mouse_button_tolerance;
+int w32_mouse_button_tolerance;
 
 /* Minimum interval between mouse movement (and scroll bar drag)
    events that are passed on to the event loop. */
-Lisp_Object Vw32_mouse_move_interval;
+int w32_mouse_move_interval;
 
 /* Flag to indicate if XBUTTON events should be passed on to Windows.  */
 int w32_pass_extra_mouse_buttons_to_system;
@@ -152,7 +153,7 @@ int display_hourglass_p;
    over text or in the modeline.  */
 
 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
-Lisp_Object Vx_hourglass_pointer_shape, Vx_window_horizontal_drag_shape, Vx_hand_shape;
+Lisp_Object Vx_hourglass_pointer_shape, Vx_window_horizontal_drag_shape;
 
 /* The shape when over mouse-sensitive text.  */
 
@@ -235,7 +236,7 @@ Lisp_Object Qw32_charset_unicode;
 #endif
 
 /* The ANSI codepage.  */
-Lisp_Object Vw32_ansi_code_page;
+int w32_ansi_code_page;
 
 /* Prefix for system colors.  */
 #define SYSTEM_COLOR_PREFIX "System"
@@ -260,6 +261,7 @@ typedef BOOL (WINAPI * TrackMouseEvent_Proc)
 
 TrackMouseEvent_Proc track_mouse_event_fn = NULL;
 ClipboardSequence_Proc clipboard_sequence_fn = NULL;
+extern AppendMenuW_Proc unicode_append_menu;
 
 /* W95 mousewheel handler */
 unsigned int msh_mousewheel = 0;
@@ -283,7 +285,7 @@ int image_cache_refcount, dpyinfo_refcount;
 
 
 /* From w32term.c. */
-extern Lisp_Object Vw32_num_mouse_buttons;
+extern int w32_num_mouse_buttons;
 extern Lisp_Object Vw32_recognize_altgr;
 
 extern HWND w32_system_caret_hwnd;
@@ -327,7 +329,7 @@ check_x_frame (frame)
   CHECK_LIVE_FRAME (frame);
   f = XFRAME (frame);
   if (! FRAME_W32_P (f))
-    error ("non-w32 frame used");
+    error ("Non-W32 frame used");
   return f;
 }
 
@@ -357,7 +359,7 @@ check_x_display_info (frame)
       CHECK_LIVE_FRAME (frame);
       f = XFRAME (frame);
       if (! FRAME_W32_P (f))
-       error ("non-w32 frame used");
+       error ("Non-W32 frame used");
       return FRAME_W32_DISPLAY_INFO (f);
     }
 }
@@ -393,10 +395,10 @@ x_window_to_frame (dpyinfo, wdesc)
 }
 
 \f
-BOOL my_show_window P_ ((struct frame *, HWND, int));
-void my_set_window_pos P_ ((HWND, HWND, int, int, int, int, UINT));
 static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
 static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
+static void my_create_window P_ ((struct frame *));
+static void my_create_tip_window P_ ((struct frame *));
 
 /* TODO: Native Input Method support; see x_create_im.  */
 void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
@@ -465,7 +467,7 @@ if the entry is new.  */)
   CHECK_NUMBER (blue);
   CHECK_STRING (name);
 
-  XSET (rgb, Lisp_Int, RGB(XUINT (red), XUINT (green), XUINT (blue)));
+  XSETINT (rgb, RGB(XUINT (red), XUINT (green), XUINT (blue)));
 
   BLOCK_INPUT;
 
@@ -828,7 +830,7 @@ w32_to_x_color (rgb)
     return Qnil;
 }
 
-COLORREF
+static Lisp_Object
 w32_color_map_lookup (colorname)
      char *colorname;
 {
@@ -847,7 +849,7 @@ w32_color_map_lookup (colorname)
 
       if (lstrcmpi (SDATA (tem), colorname) == 0)
        {
-         ret = XUINT (Fcdr (elt));
+         ret = Fcdr (elt);
          break;
        }
 
@@ -910,7 +912,7 @@ add_system_logical_colors_to_map (system_colors)
 }
 
 
-COLORREF
+static Lisp_Object
 x_to_w32_color (colorname)
      char * colorname;
 {
@@ -970,7 +972,8 @@ x_to_w32_color (colorname)
              if (i == 2)
                {
                  UNBLOCK_INPUT;
-                 return (colorval);
+                 XSETINT (ret, colorval);
+                 return ret;
                }
              color = end;
            }
@@ -1023,7 +1026,8 @@ x_to_w32_color (colorname)
              if (*end != '\0')
                break;
              UNBLOCK_INPUT;
-             return (colorval);
+             XSETINT (ret, colorval);
+             return ret;
            }
          if (*end != '/')
            break;
@@ -1064,7 +1068,8 @@ x_to_w32_color (colorname)
              if (*end != '\0')
                break;
              UNBLOCK_INPUT;
-             return (colorval);
+             XSETINT (ret, colorval);
+             return ret;
            }
          if (*end != '/')
            break;
@@ -1678,7 +1683,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;
@@ -2061,6 +2066,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);
@@ -2073,15 +2080,48 @@ w32_createwindow (f)
 
   if (!hprevinst)
     {
+      Lisp_Object ifa;
+
       w32_init_class (hinst);
+
+      /* Handle the -geometry command line option and the geometry
+        settings in the registry.  They are decoded and put into
+        initial-frame-alist by w32-win.el:x-handle-geometry.  */
+      ifa = Fsymbol_value (intern ("initial-frame-alist"));
+      if (CONSP (ifa))
+       {
+         Lisp_Object lt = Fassq (Qleft, ifa);
+         Lisp_Object tp = Fassq (Qtop,  ifa);
+
+         if (!NILP (lt))
+           {
+             lt = XCDR (lt);
+             if (INTEGERP (lt))
+               left = lt;
+           }
+         if (!NILP (tp))
+           {
+             tp = XCDR (tp);
+             if (INTEGERP (tp))
+               top = tp;
+           }
+       }
+    }
+
+  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,
@@ -2102,6 +2142,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;
     }
 }
 
@@ -2418,6 +2463,10 @@ Lisp_Object w32_grabbed_keys;
 #define HOTKEY_VK_CODE(k)     (XFASTINT (k) & 255)
 #define HOTKEY_MODIFIERS(k)   (XFASTINT (k) >> 8)
 
+#define RAW_HOTKEY_ID(k)        ((k) & 0xbfff)
+#define RAW_HOTKEY_VK_CODE(k)   ((k) & 255)
+#define RAW_HOTKEY_MODIFIERS(k) ((k) >> 8)
+
 /* Register hot-keys for reserved key combinations when Emacs has
    keyboard focus, since this is the only way Emacs can receive key
    combinations like Alt-Tab which are used by the system.  */
@@ -2499,20 +2548,20 @@ w32_msg_pump (deferred_msg * msg_buf)
              focus_window = GetFocus ();
              if (focus_window != NULL)
                RegisterHotKey (focus_window,
-                               HOTKEY_ID (msg.wParam),
-                               HOTKEY_MODIFIERS (msg.wParam),
-                               HOTKEY_VK_CODE (msg.wParam));
+                               RAW_HOTKEY_ID (msg.wParam),
+                               RAW_HOTKEY_MODIFIERS (msg.wParam),
+                               RAW_HOTKEY_VK_CODE (msg.wParam));
              /* Reply is not expected.  */
              break;
            case WM_EMACS_UNREGISTER_HOT_KEY:
              focus_window = GetFocus ();
              if (focus_window != NULL)
-               UnregisterHotKey (focus_window, HOTKEY_ID (msg.wParam));
+               UnregisterHotKey (focus_window, RAW_HOTKEY_ID (msg.wParam));
              /* Mark item as erased.  NB: this code must be
                  thread-safe.  The next line is okay because the cons
                  cell is never made into garbage and is not relocated by
                  GC.  */
-             XSETCAR ((Lisp_Object) msg.lParam, Qnil);
+             XSETCAR ((Lisp_Object) ((EMACS_INT) msg.lParam), Qnil);
              if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
                abort ();
              break;
@@ -2520,7 +2569,7 @@ w32_msg_pump (deferred_msg * msg_buf)
              {
                int vk_code = (int) msg.wParam;
                int cur_state = (GetKeyState (vk_code) & 1);
-               Lisp_Object new_state = (Lisp_Object) msg.lParam;
+               Lisp_Object new_state = (Lisp_Object) ((EMACS_INT) msg.lParam);
 
                /* NB: This code must be thread-safe.  It is safe to
                    call NILP because symbols are not relocated by GC,
@@ -2685,6 +2734,24 @@ w32_msg_worker (dw)
   return 0;
 }
 
+static void
+signal_user_input ()
+{
+  /* Interrupt any lisp that wants to be interrupted by input.  */
+  if (!NILP (Vthrow_on_input))
+    {
+      Vquit_flag = Vthrow_on_input;
+      /* If we're inside a function that wants immediate quits,
+        do it now.  */
+      if (immediate_quit && NILP (Vinhibit_quit))
+       {
+         immediate_quit = 0;
+         QUIT;
+       }
+    }
+}
+
+
 static void
 post_character_message (hwnd, msg, wParam, lParam, modifiers)
      HWND hwnd;
@@ -2710,7 +2777,7 @@ post_character_message (hwnd, msg, wParam, lParam, modifiers)
       c = make_ctrl_char (c) & 0377;
     if (c == quit_char
        || (wmsg.dwModifiers == 0 &&
-           XFASTINT (Vw32_quit_key) && wParam == XFASTINT (Vw32_quit_key)))
+           w32_quit_key && wParam == w32_quit_key))
       {
        Vquit_flag = Qt;
 
@@ -2742,6 +2809,8 @@ post_character_message (hwnd, msg, wParam, lParam, modifiers)
           to receive C-g to interrupt the lisp thread.  */
        cancel_all_deferred_msgs ();
       }
+    else
+      signal_user_input ();
   }
 
   my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
@@ -3120,7 +3189,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
         are used together, but only if user has two button mouse. */
     case WM_LBUTTONDOWN:
     case WM_RBUTTONDOWN:
-      if (XINT (Vw32_num_mouse_buttons) > 2)
+      if (w32_num_mouse_buttons > 2)
        goto handle_plain_button;
 
       {
@@ -3161,6 +3230,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;
@@ -3170,7 +3240,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
            /* Hold onto message for now. */
            mouse_button_timer =
              SetTimer (hwnd, MOUSE_BUTTON_ID,
-                       XINT (Vw32_mouse_button_tolerance), NULL);
+                       w32_mouse_button_tolerance, NULL);
            saved_mouse_button_msg.msg.hwnd = hwnd;
            saved_mouse_button_msg.msg.message = msg;
            saved_mouse_button_msg.msg.wParam = wParam;
@@ -3183,7 +3253,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
 
     case WM_LBUTTONUP:
     case WM_RBUTTONUP:
-      if (XINT (Vw32_num_mouse_buttons) > 2)
+      if (w32_num_mouse_buttons > 2)
        goto handle_plain_button;
 
       {
@@ -3218,6 +3288,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;
@@ -3241,6 +3312,11 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
        BOOL up;
        int button;
 
+       /* Ignore middle and extra buttons as long as the menu is active.  */
+       f = x_window_to_frame (dpyinfo, hwnd);
+       if (f && f->output_data.w32->menubar_active)
+         return 0;
+
        if (parse_button (msg, HIWORD (wParam), &button, &up))
          {
            if (up) ReleaseCapture ();
@@ -3256,12 +3332,21 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
 
       wmsg.dwModifiers = w32_get_modifiers ();
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+      signal_user_input ();
 
       /* Need to return true for XBUTTON messages, false for others,
          to indicate that we processed the message.  */
       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
@@ -3279,7 +3364,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
          track_mouse_window = hwnd;
        }
     case WM_VSCROLL:
-      if (XINT (Vw32_mouse_move_interval) <= 0
+      if (w32_mouse_move_interval <= 0
          || (msg == WM_MOUSEMOVE && button_state == 0))
        {
          wmsg.dwModifiers = w32_get_modifiers ();
@@ -3295,7 +3380,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
       if (saved_mouse_move_msg.msg.hwnd == 0)
        mouse_move_timer =
          SetTimer (hwnd, MOUSE_MOVE_ID,
-                   XINT (Vw32_mouse_move_interval), NULL);
+                   w32_mouse_move_interval, NULL);
 
       /* Hold onto message for now. */
       saved_mouse_move_msg.msg.hwnd = hwnd;
@@ -3310,11 +3395,13 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
     case WM_MOUSEWHEEL:
       wmsg.dwModifiers = w32_get_modifiers ();
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+      signal_user_input ();
       return 0;
 
     case WM_DROPFILES:
       wmsg.dwModifiers = w32_get_modifiers ();
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+      signal_user_input ();
       return 0;
 
     case WM_TIMER:
@@ -3324,6 +3411,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
          if (saved_mouse_button_msg.msg.hwnd)
            {
              post_msg (&saved_mouse_button_msg);
+             signal_user_input ();
              saved_mouse_button_msg.msg.hwnd = 0;
            }
          KillTimer (hwnd, mouse_button_timer);
@@ -3450,7 +3538,13 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
               pMis->itemHeight = GetSystemMetrics (SM_CYMENUSIZE);
               if (title)
                 {
-                  GetTextExtentPoint32 (hdc, title, strlen (title), &size);
+                 if (unicode_append_menu)
+                   GetTextExtentPoint32W (hdc, (WCHAR *) title,
+                                          wcslen ((WCHAR *) title),
+                                          &size);
+                 else
+                   GetTextExtentPoint32 (hdc, title, strlen (title), &size);
+
                   pMis->itemWidth = size.cx;
                   if (pMis->itemHeight < size.cy)
                     pMis->itemHeight = size.cy;
@@ -3488,13 +3582,22 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
                   menu_font = CreateFontIndirect (&menu_logfont);
                   old_font = SelectObject (hdc, menu_font);
 
-                  /* Always draw title as if not selected.  */
-                  ExtTextOut (hdc,
-                              pDis->rcItem.left
-                              + GetSystemMetrics (SM_CXMENUCHECK),
-                              pDis->rcItem.top,
-                              ETO_OPAQUE, &pDis->rcItem,
-                              title, strlen (title), NULL);
+                 /* Always draw title as if not selected.  */
+                 if (unicode_append_menu)
+                   ExtTextOutW (hdc,
+                                pDis->rcItem.left
+                                + GetSystemMetrics (SM_CXMENUCHECK),
+                                pDis->rcItem.top,
+                                ETO_OPAQUE, &pDis->rcItem,
+                                (WCHAR *) title,
+                                wcslen ((WCHAR *) title), NULL);
+                 else
+                   ExtTextOut (hdc,
+                               pDis->rcItem.left
+                               + GetSystemMetrics (SM_CXMENUCHECK),
+                               pDis->rcItem.top,
+                               ETO_OPAQUE, &pDis->rcItem,
+                               title, strlen (title), NULL);
 
                   SelectObject (hdc, old_font);
                   DeleteObject (menu_font);
@@ -3811,6 +3914,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
        {
          wmsg.dwModifiers = w32_get_modifiers ();
          my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+         signal_user_input ();
          return 0;
        }
 
@@ -3823,7 +3927,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
   return 0;
 }
 
-void
+static void
 my_create_window (f)
      struct frame * f;
 {
@@ -3839,7 +3943,7 @@ my_create_window (f)
    indirectly via the Window thread, as we do not need to process Window
    messages for the tooltip.  Creating tooltips indirectly also creates
    deadlocks when tooltips are created for menu items.  */
-void
+static void
 my_create_tip_window (f)
      struct frame *f;
 {
@@ -4038,15 +4142,15 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
        1, 1, 0,
        doc: /* Make a new window, which is called a \"frame\" in Emacs terms.
 Returns an Emacs frame object.
-ALIST is an alist of frame parameters.
+PARAMETERS is an alist of frame parameters.
 If the parameters specify that the frame should not have a minibuffer,
 and do not specify a specific minibuffer window to use,
 then `default-minibuffer-frame' must be a frame whose minibuffer can
 be shared by the new frame.
 
 This function is an internal primitive--use `make-frame' instead.  */)
-  (parms)
-     Lisp_Object parms;
+  (parameters)
+     Lisp_Object parameters;
 {
   struct frame *f;
   Lisp_Object frame, tem;
@@ -4067,7 +4171,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
      until we know if this frame has a specified name.  */
   Vx_resource_name = Vinvocation_name;
 
-  display = w32_get_arg (parms, Qdisplay, 0, 0, RES_TYPE_STRING);
+  display = w32_get_arg (parameters, Qdisplay, 0, 0, RES_TYPE_STRING);
   if (EQ (display, Qunbound))
     display = Qnil;
   dpyinfo = check_x_display_info (display);
@@ -4077,7 +4181,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
   kb = &the_only_kboard;
 #endif
 
-  name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
+  name = w32_get_arg (parameters, Qname, "name", "Name", RES_TYPE_STRING);
   if (!STRINGP (name)
       && ! EQ (name, Qunbound)
       && ! NILP (name))
@@ -4087,7 +4191,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
     Vx_resource_name = name;
 
   /* See if parent window is specified.  */
-  parent = w32_get_arg (parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
+  parent = w32_get_arg (parameters, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
   if (EQ (parent, Qunbound))
     parent = Qnil;
   if (! NILP (parent))
@@ -4097,8 +4201,8 @@ This function is an internal primitive--use `make-frame' instead.  */)
   /* No need to protect DISPLAY because that's not used after passing
      it to make_frame_without_minibuffer.  */
   frame = Qnil;
-  GCPRO4 (parms, parent, name, frame);
-  tem = w32_get_arg (parms, Qminibuffer, "minibuffer", "Minibuffer",
+  GCPRO4 (parameters, parent, name, frame);
+  tem = w32_get_arg (parameters, Qminibuffer, "minibuffer", "Minibuffer",
                      RES_TYPE_SYMBOL);
   if (EQ (tem, Qnone) || NILP (tem))
     f = make_frame_without_minibuffer (Qnil, kb, display);
@@ -4128,7 +4232,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
   record_unwind_protect (unwind_create_frame, frame);
 
   f->icon_name
-    = w32_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
+    = w32_get_arg (parameters, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
   if (! STRINGP (f->icon_name))
     f->icon_name = Qnil;
 
@@ -4170,7 +4274,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
   {
     Lisp_Object font;
 
-    font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
+    font = w32_get_arg (parameters, Qfont, "font", "Font", RES_TYPE_STRING);
 
     BLOCK_INPUT;
     /* First, try whatever font the caller has specified.  */
@@ -4194,49 +4298,49 @@ This function is an internal primitive--use `make-frame' instead.  */)
     if (! STRINGP (font))
       font = build_string ("Fixedsys");
 
-    x_default_parameter (f, parms, Qfont, font,
+    x_default_parameter (f, parameters, Qfont, font,
                         "font", "Font", RES_TYPE_STRING);
   }
 
-  x_default_parameter (f, parms, Qborder_width, make_number (2),
+  x_default_parameter (f, parameters, Qborder_width, make_number (2),
                       "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
   /* This defaults to 2 in order to match xterm.  We recognize either
      internalBorderWidth or internalBorder (which is what xterm calls
      it).  */
-  if (NILP (Fassq (Qinternal_border_width, parms)))
+  if (NILP (Fassq (Qinternal_border_width, parameters)))
     {
       Lisp_Object value;
 
-      value = w32_get_arg (parms, Qinternal_border_width,
-                        "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
+      value = w32_get_arg (parameters, Qinternal_border_width,
+                           "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
       if (! EQ (value, Qunbound))
-       parms = Fcons (Fcons (Qinternal_border_width, value),
-                      parms);
+       parameters = Fcons (Fcons (Qinternal_border_width, value),
+                            parameters);
     }
   /* Default internalBorderWidth to 0 on Windows to match other programs.  */
-  x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
+  x_default_parameter (f, parameters, Qinternal_border_width, make_number (0),
                       "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER);
-  x_default_parameter (f, parms, Qvertical_scroll_bars, Qright,
+  x_default_parameter (f, parameters, Qvertical_scroll_bars, Qright,
                       "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
 
   /* Also do the stuff which must be set before the window exists.  */
-  x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
+  x_default_parameter (f, parameters, Qforeground_color, build_string ("black"),
                       "foreground", "Foreground", RES_TYPE_STRING);
-  x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
+  x_default_parameter (f, parameters, Qbackground_color, build_string ("white"),
                       "background", "Background", RES_TYPE_STRING);
-  x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
+  x_default_parameter (f, parameters, Qmouse_color, build_string ("black"),
                       "pointerColor", "Foreground", RES_TYPE_STRING);
-  x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
+  x_default_parameter (f, parameters, Qcursor_color, build_string ("black"),
                       "cursorColor", "Foreground", RES_TYPE_STRING);
-  x_default_parameter (f, parms, Qborder_color, build_string ("black"),
+  x_default_parameter (f, parameters, Qborder_color, build_string ("black"),
                       "borderColor", "BorderColor", RES_TYPE_STRING);
-  x_default_parameter (f, parms, Qscreen_gamma, Qnil,
+  x_default_parameter (f, parameters, Qscreen_gamma, Qnil,
                       "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
-  x_default_parameter (f, parms, Qline_spacing, Qnil,
+  x_default_parameter (f, parameters, Qline_spacing, Qnil,
                       "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
-  x_default_parameter (f, parms, Qleft_fringe, Qnil,
+  x_default_parameter (f, parameters, Qleft_fringe, Qnil,
                       "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
-  x_default_parameter (f, parms, Qright_fringe, Qnil,
+  x_default_parameter (f, parameters, Qright_fringe, Qnil,
                       "rightFringe", "RightFringe", RES_TYPE_NUMBER);
 
 
@@ -4248,16 +4352,16 @@ This function is an internal primitive--use `make-frame' instead.  */)
      happen.  */
   init_frame_faces (f);
 
-  x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
+  x_default_parameter (f, parameters, Qmenu_bar_lines, make_number (1),
                       "menuBar", "MenuBar", RES_TYPE_NUMBER);
-  x_default_parameter (f, parms, Qtool_bar_lines, make_number (1),
+  x_default_parameter (f, parameters, Qtool_bar_lines, make_number (1),
                        "toolBar", "ToolBar", RES_TYPE_NUMBER);
 
-  x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
+  x_default_parameter (f, parameters, Qbuffer_predicate, Qnil,
                       "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
-  x_default_parameter (f, parms, Qtitle, Qnil,
+  x_default_parameter (f, parameters, Qtitle, Qnil,
                       "title", "Title", RES_TYPE_STRING);
-  x_default_parameter (f, parms, Qfullscreen, Qnil,
+  x_default_parameter (f, parameters, Qfullscreen, Qnil,
                        "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
 
   f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
@@ -4270,13 +4374,13 @@ This function is an internal primitive--use `make-frame' instead.  */)
   f->output_data.w32->hourglass_cursor = w32_load_cursor (IDC_WAIT);
   f->output_data.w32->horizontal_drag_cursor = w32_load_cursor (IDC_SIZEWE);
 
-  window_prompting = x_figure_window_size (f, parms, 1);
+  window_prompting = x_figure_window_size (f, parameters, 1);
 
-  tem = w32_get_arg (parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
+  tem = w32_get_arg (parameters, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
   f->no_split = minibuffer_only || EQ (tem, Qt);
 
   w32_window (f, window_prompting, minibuffer_only);
-  x_icon (f, parms);
+  x_icon (f, parameters);
 
   x_make_gc (f);
 
@@ -4286,16 +4390,16 @@ This function is an internal primitive--use `make-frame' instead.  */)
 
   /* We need to do this after creating the window, so that the
      icon-creation functions can say whose icon they're describing.  */
-  x_default_parameter (f, parms, Qicon_type, Qnil,
+  x_default_parameter (f, parameters, Qicon_type, Qnil,
                       "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
 
-  x_default_parameter (f, parms, Qauto_raise, Qnil,
+  x_default_parameter (f, parameters, Qauto_raise, Qnil,
                       "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
-  x_default_parameter (f, parms, Qauto_lower, Qnil,
+  x_default_parameter (f, parameters, Qauto_lower, Qnil,
                       "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
-  x_default_parameter (f, parms, Qcursor_type, Qbox,
+  x_default_parameter (f, parameters, Qcursor_type, Qbox,
                       "cursorType", "CursorType", RES_TYPE_SYMBOL);
-  x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
+  x_default_parameter (f, parameters, Qscroll_bar_width, Qnil,
                       "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
 
   /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
@@ -4315,17 +4419,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.  */
@@ -4333,7 +4426,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
     {
       Lisp_Object visibility;
 
-      visibility = w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
+      visibility = w32_get_arg (parameters, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
       if (EQ (visibility, Qunbound))
        visibility = Qt;
 
@@ -4521,7 +4614,7 @@ w32_load_system_font (f,fontname,size)
         /* Fill out details in lf according to the font that was
            actually loaded.  */
         lf.lfHeight = font->tm.tmInternalLeading - font->tm.tmHeight;
-        lf.lfWidth = font->tm.tmAveCharWidth;
+        lf.lfWidth = font->tm.tmMaxCharWidth;
         lf.lfWeight = font->tm.tmWeight;
         lf.lfItalic = font->tm.tmItalic;
         lf.lfCharSet = font->tm.tmCharSet;
@@ -4569,6 +4662,24 @@ w32_load_system_font (f,fontname,size)
     fontp->name = (char *) xmalloc (strlen (fontname) + 1);
     bcopy (fontname, fontp->name, strlen (fontname) + 1);
 
+    if (lf.lfPitchAndFamily == FIXED_PITCH)
+      {
+       /* Fixed width font.  */
+       fontp->average_width = fontp->space_width = FONT_WIDTH (font);
+      }
+    else
+      {
+       wchar_t space = 32;
+       XCharStruct* pcm;
+       pcm = w32_per_char_metric (font, &space, ANSI_FONT);
+       if (pcm)
+         fontp->space_width = pcm->width;
+       else
+         fontp->space_width = FONT_WIDTH (font);
+
+       fontp->average_width = font->tm.tmAveCharWidth;
+      }
+
     charset = xlfd_charset_of_font (fontname);
 
   /* Cache the W32 codepage for a font.  This makes w32_encode_char
@@ -4635,6 +4746,7 @@ int size;
 {
   Lisp_Object bdf_fonts;
   struct font_info *retval = NULL;
+  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
 
   bdf_fonts = w32_list_bdf_fonts (build_string (fontname), 1);
 
@@ -4642,11 +4754,22 @@ int size;
     {
       char *bdf_name, *bdf_file;
       Lisp_Object bdf_pair;
+      int i;
 
       bdf_name = SDATA (XCAR (bdf_fonts));
       bdf_pair = Fassoc (XCAR (bdf_fonts), Vw32_bdf_filename_alist);
       bdf_file = SDATA (XCDR (bdf_pair));
 
+      // If the font is already loaded, do not load it again.
+      for (i = 0; i < dpyinfo->n_fonts; i++)
+       {
+         if ((dpyinfo->font_table[i].name
+              && !strcmp (dpyinfo->font_table[i].name, bdf_name))
+             || (dpyinfo->font_table[i].full_name
+                 && !strcmp (dpyinfo->font_table[i].full_name, bdf_name)))
+           return dpyinfo->font_table + i;
+       }
+
       retval = w32_load_bdf_font (f, bdf_name, size, bdf_file);
 
       bdf_fonts = XCDR (bdf_fonts);
@@ -4772,46 +4895,46 @@ x_to_w32_charset (lpcs)
   w32_charset = Fcar (Fcdr (this_entry));
 
   /* Translate Lisp symbol to number.  */
-  if (w32_charset == Qw32_charset_ansi)
+  if (EQ (w32_charset, Qw32_charset_ansi))
     return ANSI_CHARSET;
-  if (w32_charset == Qw32_charset_symbol)
+  if (EQ (w32_charset, Qw32_charset_symbol))
     return SYMBOL_CHARSET;
-  if (w32_charset == Qw32_charset_shiftjis)
+  if (EQ (w32_charset, Qw32_charset_shiftjis))
     return SHIFTJIS_CHARSET;
-  if (w32_charset == Qw32_charset_hangeul)
+  if (EQ (w32_charset, Qw32_charset_hangeul))
     return HANGEUL_CHARSET;
-  if (w32_charset == Qw32_charset_chinesebig5)
+  if (EQ (w32_charset, Qw32_charset_chinesebig5))
     return CHINESEBIG5_CHARSET;
-  if (w32_charset == Qw32_charset_gb2312)
+  if (EQ (w32_charset, Qw32_charset_gb2312))
     return GB2312_CHARSET;
-  if (w32_charset == Qw32_charset_oem)
+  if (EQ (w32_charset, Qw32_charset_oem))
     return OEM_CHARSET;
 #ifdef JOHAB_CHARSET
-  if (w32_charset == Qw32_charset_johab)
+  if (EQ (w32_charset, Qw32_charset_johab))
     return JOHAB_CHARSET;
-  if (w32_charset == Qw32_charset_easteurope)
+  if (EQ (w32_charset, Qw32_charset_easteurope))
     return EASTEUROPE_CHARSET;
-  if (w32_charset == Qw32_charset_turkish)
+  if (EQ (w32_charset, Qw32_charset_turkish))
     return TURKISH_CHARSET;
-  if (w32_charset == Qw32_charset_baltic)
+  if (EQ (w32_charset, Qw32_charset_baltic))
     return BALTIC_CHARSET;
-  if (w32_charset == Qw32_charset_russian)
+  if (EQ (w32_charset, Qw32_charset_russian))
     return RUSSIAN_CHARSET;
-  if (w32_charset == Qw32_charset_arabic)
+  if (EQ (w32_charset, Qw32_charset_arabic))
     return ARABIC_CHARSET;
-  if (w32_charset == Qw32_charset_greek)
+  if (EQ (w32_charset, Qw32_charset_greek))
     return GREEK_CHARSET;
-  if (w32_charset == Qw32_charset_hebrew)
+  if (EQ (w32_charset, Qw32_charset_hebrew))
     return HEBREW_CHARSET;
-  if (w32_charset == Qw32_charset_vietnamese)
+  if (EQ (w32_charset, Qw32_charset_vietnamese))
     return VIETNAMESE_CHARSET;
-  if (w32_charset == Qw32_charset_thai)
+  if (EQ (w32_charset, Qw32_charset_thai))
     return THAI_CHARSET;
-  if (w32_charset == Qw32_charset_mac)
+  if (EQ (w32_charset, Qw32_charset_mac))
     return MAC_CHARSET;
 #endif /* JOHAB_CHARSET */
 #ifdef UNICODE_CHARSET
-  if (w32_charset == Qw32_charset_unicode)
+  if (EQ (w32_charset, Qw32_charset_unicode))
     return UNICODE_CHARSET;
 #endif
 
@@ -4937,8 +5060,8 @@ w32_to_x_charset (fncharset)
 
         /* Look for Same charset and a valid codepage (or non-int
            which means ignore).  */
-        if (w32_charset == charset_type
-            && (!INTEGERP (codepage) || codepage == CP_DEFAULT
+        if (EQ (w32_charset, charset_type)
+            && (!INTEGERP (codepage) || XINT (codepage) == CP_DEFAULT
                 || IsValidCodePage (XINT (codepage))))
           {
             /* If we don't have a match already, then this is the
@@ -5095,8 +5218,8 @@ w32_to_all_x_charsets (fncharset)
 
         /* Look for Same charset and a valid codepage (or non-int
            which means ignore).  */
-        if (w32_charset == charset_type
-            && (!INTEGERP (codepage) || codepage == CP_DEFAULT
+        if (EQ (w32_charset, charset_type)
+            && (!INTEGERP (codepage) || XINT (codepage) == CP_DEFAULT
                 || IsValidCodePage (XINT (codepage))))
           {
            retval = Fcons (x_charset, retval);
@@ -5230,9 +5353,13 @@ w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
       strcpy (height_pixels, "*");
       strcpy (height_dpi, "*");
     }
+
+#if 0 /* Never put the width in the xfld. It fails on fonts with
+        double-width characters.  */
   if (lplogfont->lfWidth)
     sprintf (width_pixels, "%u", lplogfont->lfWidth * 10);
   else
+#endif
     strcpy (width_pixels, "*");
 
   _snprintf (lpxstr, len - 1,
@@ -5335,7 +5462,7 @@ x_to_w32_font (lpxstr, lplogfont)
           setup_coding_system
             (Fcheck_coding_system (Vlocale_coding_system), &coding);
          coding.src_multibyte = 1;
-         coding.dst_multibyte = 1;
+         coding.dst_multibyte = 0;
          /* Need to set COMPOSITION_DISABLED, otherwise Emacs crashes in
             encode_coding_iso2022 trying to dereference a null pointer.  */
          coding.composing = COMPOSITION_DISABLED;
@@ -5572,11 +5699,11 @@ w32_font_match (fontname, pattern)
     char * fontname;
     char * pattern;
 {
-  char *regex = alloca (strlen (pattern) * 2 + 3);
-  char *font_name_copy = alloca (strlen (fontname) + 1);
   char *ptr;
+  char *font_name_copy;
+  char *regex = alloca (strlen (pattern) * 2 + 3);
 
-  /* Copy fontname so we can modify it during comparison.  */
+  font_name_copy = alloca (strlen (fontname) + 1);
   strcpy (font_name_copy, fontname);
 
   ptr = regex;
@@ -5615,8 +5742,8 @@ w32_font_match (fontname, pattern)
       return FALSE;
   }
 
-  return (fast_c_string_match_ignore_case (build_string (regex),
-                                           font_name_copy) >= 0);
+  return (fast_string_match_ignore_case (build_string (regex),
+                                         build_string(font_name_copy)) >= 0);
 }
 
 /* Callback functions, and a structure holding info they need, for
@@ -6109,7 +6236,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;
@@ -6145,6 +6272,9 @@ w32_find_ccl_program (fontp)
     }
 }
 
+/* directory-files from dired.c.  */
+Lisp_Object Fdirectory_files P_((Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object));
+
 \f
 /* Find BDF files in a specified directory.  (use GCPRO when calling,
    as this calls lisp to get a directory listing).  */
@@ -6158,7 +6288,7 @@ w32_find_bdf_fonts_in_dir (Lisp_Object directory)
     return Qnil;
 
   filelist = Fdirectory_files (directory, Qt,
-                              build_string (".*\\.[bB][dD][fF]"), Qt);
+                              build_string (".*\\.[bB][dD][fF]"), Qt);
 
   for ( ; CONSP(filelist); filelist = XCDR (filelist))
     {
@@ -6171,10 +6301,10 @@ w32_find_bdf_fonts_in_dir (Lisp_Object directory)
 
 DEFUN ("w32-find-bdf-fonts", Fw32_find_bdf_fonts, Sw32_find_bdf_fonts,
        1, 1, 0,
-       doc: /* Return a list of BDF fonts in DIR.
-The list is suitable for appending to w32-bdf-filename-alist.  Fonts
-which do not contain an xlfd description will not be included in the
-list. DIR may be a list of directories.  */)
+       doc: /* Return a list of BDF fonts in DIRECTORY.
+The list is suitable for appending to `w32-bdf-filename-alist'.
+Fonts which do not contain an xlfd description will not be included
+in the list.  DIRECTORY may be a list of directories.  */)
      (directory)
      Lisp_Object directory;
 {
@@ -6225,17 +6355,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;
 }
@@ -6255,7 +6380,7 @@ DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
 
 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
        Sx_display_grayscale_p, 0, 1, 0,
-       doc: /* Return t if the X display supports shades of gray.
+       doc: /* Return t if DISPLAY supports shades of gray.
 Note that color displays do support shades of gray.
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
@@ -6328,9 +6453,9 @@ If omitted or nil, that stands for the selected frame's display.  */)
 
   hdc = GetDC (dpyinfo->root_window);
   if (dpyinfo->has_palette)
-    cap = GetDeviceCaps (hdc,SIZEPALETTE);
+    cap = GetDeviceCaps (hdc, SIZEPALETTE);
   else
-    cap = GetDeviceCaps (hdc,NUMCOLORS);
+    cap = GetDeviceCaps (hdc, NUMCOLORS);
 
   /* We force 24+ bit depths to 24-bit, both to prevent an overflow
      and because probably is more meaningful on Windows anyway */
@@ -6358,7 +6483,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 }
 
 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
-       doc: /* Returns the vendor ID string of the W32 system (Microsoft).
+       doc: /* Returns the "vendor ID" string of the W32 system (Microsoft).
 The optional argument DISPLAY specifies which display to ask about.
 DISPLAY should be either a frame or a display name (a string).
 If omitted or nil, that stands for the selected frame's display.  */)
@@ -6371,7 +6496,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
        doc: /* Returns the version numbers of the server of DISPLAY.
 The value is a list of three integers: the major and minor
-version numbers, and the vendor-specific release
+version numbers of the X Protocol in use, and the distributor-specific release
 number.  See also the function `x-server-vendor'.
 
 The optional argument DISPLAY specifies which display to ask about.
@@ -7115,6 +7240,8 @@ x_create_tip_frame (dpyinfo, parms, text)
   old_buffer = current_buffer;
   set_buffer_internal_1 (XBUFFER (buffer));
   current_buffer->truncate_lines = Qnil;
+  specbind (Qinhibit_read_only, Qt);
+  specbind (Qinhibit_modification_hooks, Qt);
   Ferase_buffer ();
   Finsert (1, &text);
   set_buffer_internal_1 (old_buffer);
@@ -7348,16 +7475,22 @@ compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
 
   if (INTEGERP (top))
     *root_y = XINT (top);
-  else if (*root_y + XINT (dy) - height < 0)
-    *root_y -= XINT (dy);
-  else
-    {
-      *root_y -= height;
+  else if (*root_y + XINT (dy) <= 0)
+    *root_y = 0; /* Can happen for negative dy */
+  else if (*root_y + XINT (dy) + height <= FRAME_W32_DISPLAY_INFO (f)->height)
+    /* It fits below the pointer */
       *root_y += XINT (dy);
-    }
+  else if (height + XINT (dy) <= *root_y)
+    /* It fits above the pointer.  */
+    *root_y -= height + XINT (dy);
+  else
+    /* Put it on the top.  */
+    *root_y = 0;
 
   if (INTEGERP (left))
     *root_x = XINT (left);
+  else if (*root_x + XINT (dx) <= 0)
+    *root_x = 0; /* Can happen for negative dx */
   else if (*root_x + XINT (dx) + width <= FRAME_W32_DISPLAY_INFO (f)->width)
     /* It fits to the right of the pointer.  */
     *root_x += XINT (dx);
@@ -7382,7 +7515,7 @@ used to change the tooltip's appearance.
 Automatically hide the tooltip after TIMEOUT seconds.  TIMEOUT nil
 means use the default timeout of 5 seconds.
 
-If the list of frame parameters PARAMS contains a `left' parameter,
+If the list of frame parameters PARMS contains a `left' parameter,
 the tooltip is displayed at that x-position.  Otherwise it is
 displayed at the mouse position, with offset DX added (default is 5 if
 DX isn't specified).  Likewise for the y-position; if a `top' frame
@@ -7527,7 +7660,7 @@ Text larger than the specified size is clipped.  */)
   clear_glyph_matrix (w->desired_matrix);
   clear_glyph_matrix (w->current_matrix);
   SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
-  try_window (FRAME_ROOT_WINDOW (f), pos);
+  try_window (FRAME_ROOT_WINDOW (f), pos, 0);
 
   /* Compute width and height of the tooltip.  */
   width = height = 0;
@@ -7580,9 +7713,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).  */
@@ -7674,7 +7810,8 @@ file_dialog_callback (hwnd, msg, wParam, lParam)
     {
       OFNOTIFY * notify = (OFNOTIFY *)lParam;
       /* Detect when the Filter dropdown is changed.  */
-      if (notify->hdr.code == CDN_TYPECHANGE)
+      if (notify->hdr.code == CDN_TYPECHANGE
+         || notify->hdr.code == CDN_INITDONE)
        {
          HWND dialog = GetParent (hwnd);
          HWND edit_control = GetDlgItem (dialog, FILE_NAME_TEXT_FIELD);
@@ -7688,8 +7825,10 @@ file_dialog_callback (hwnd, msg, wParam, lParam)
            }
          else
            {
-             CommDlg_OpenSave_SetControlText (dialog, FILE_NAME_TEXT_FIELD,
-                                              "");
+             /* Don't override default filename on init done.  */
+             if (notify->hdr.code == CDN_TYPECHANGE)
+               CommDlg_OpenSave_SetControlText (dialog,
+                                                FILE_NAME_TEXT_FIELD, "");
              EnableWindow (edit_control, TRUE);
            }
        }
@@ -7697,36 +7836,51 @@ file_dialog_callback (hwnd, msg, wParam, lParam)
   return 0;
 }
 
-DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
+/* Since we compile with _WIN32_WINNT set to 0x0400 (for NT4 compatibility)
+   we end up with the old file dialogs. Define a big enough struct for the
+   new dialog to trick GetOpenFileName into giving us the new dialogs on
+   Windows 2000 and XP.  */
+typedef struct
+{
+  OPENFILENAME real_details;
+  void * pReserved;
+  DWORD dwReserved;
+  DWORD FlagsEx;
+} NEWOPENFILENAME;
+
+
+DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
        doc: /* Read file name, prompting with PROMPT in directory DIR.
 Use a file selection dialog.
 Select DEFAULT-FILENAME in the dialog's file selection box, if
-specified.  Ensure that file exists if MUSTMATCH is non-nil.  */)
-  (prompt, dir, default_filename, mustmatch)
-     Lisp_Object prompt, dir, default_filename, mustmatch;
+specified.  Ensure that file exists if MUSTMATCH is non-nil.
+If ONLY-DIR-P is non-nil, the user can only select directories.  */)
+  (prompt, dir, default_filename, mustmatch, only_dir_p)
+     Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
 {
   struct frame *f = SELECTED_FRAME ();
   Lisp_Object file = Qnil;
   int count = SPECPDL_INDEX ();
-  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
   char filename[MAX_PATH + 1];
   char init_dir[MAX_PATH + 1];
+  int default_filter_index = 1; /* 1: All Files, 2: Directories only  */
 
-  GCPRO5 (prompt, dir, default_filename, mustmatch, file);
+  GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
   CHECK_STRING (prompt);
   CHECK_STRING (dir);
 
   /* Create the dialog with PROMPT as title, using DIR as initial
      directory and using "*" as pattern.  */
   dir = Fexpand_file_name (dir, Qnil);
-  strncpy (init_dir, SDATA (dir), MAX_PATH);
+  strncpy (init_dir, SDATA (ENCODE_FILE (dir)), MAX_PATH);
   init_dir[MAX_PATH] = '\0';
   unixtodos_filename (init_dir);
 
   if (STRINGP (default_filename))
     {
       char *file_name_only;
-      char *full_path_name = SDATA (default_filename);
+      char *full_path_name = SDATA (ENCODE_FILE (default_filename));
 
       unixtodos_filename (full_path_name);
 
@@ -7734,9 +7888,7 @@ specified.  Ensure that file exists if MUSTMATCH is non-nil.  */)
       if (!file_name_only)
         file_name_only = full_path_name;
       else
-        {
-          file_name_only++;
-        }
+       file_name_only++;
 
       strncpy (filename, file_name_only, MAX_PATH);
       filename[MAX_PATH] = '\0';
@@ -7745,35 +7897,60 @@ specified.  Ensure that file exists if MUSTMATCH is non-nil.  */)
     filename[0] = '\0';
 
   {
-    OPENFILENAME file_details;
+    NEWOPENFILENAME new_file_details;
+    BOOL file_opened = FALSE;
+    OPENFILENAME * file_details = &new_file_details.real_details;
 
     /* Prevent redisplay.  */
     specbind (Qinhibit_redisplay, Qt);
     BLOCK_INPUT;
 
-    bzero (&file_details, sizeof (file_details));
-    file_details.lStructSize = sizeof (file_details);
-    file_details.hwndOwner = FRAME_W32_WINDOW (f);
+    bzero (&new_file_details, sizeof (new_file_details));
+    /* 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);
+    else
+      file_details->lStructSize = sizeof (file_details);
+
+    file_details->hwndOwner = FRAME_W32_WINDOW (f);
     /* Undocumented Bug in Common File Dialog:
        If a filter is not specified, shell links are not resolved.  */
-    file_details.lpstrFilter = "All Files (*.*)\0*.*\0Directories\0*|*\0\0";
-    file_details.lpstrFile = filename;
-    file_details.nMaxFile = sizeof (filename);
-    file_details.lpstrInitialDir = init_dir;
-    file_details.lpstrTitle = SDATA (prompt);
-    file_details.Flags = (OFN_HIDEREADONLY | OFN_NOCHANGEDIR
+    file_details->lpstrFilter = "All Files (*.*)\0*.*\0Directories\0*|*\0\0";
+    file_details->lpstrFile = filename;
+    file_details->nMaxFile = sizeof (filename);
+    file_details->lpstrInitialDir = init_dir;
+    file_details->lpstrTitle = SDATA (prompt);
+
+    if (! NILP (only_dir_p))
+      default_filter_index = 2;
+
+    file_details->nFilterIndex = default_filter_index;
+
+    file_details->Flags = (OFN_HIDEREADONLY | OFN_NOCHANGEDIR
                          | OFN_EXPLORER | OFN_ENABLEHOOK);
     if (!NILP (mustmatch))
-      file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
+      {
+       /* Require that the path to the parent directory exists.  */
+       file_details->Flags |= OFN_PATHMUSTEXIST;
+       /* If we are looking for a file, require that it exists.  */
+       if (NILP (only_dir_p))
+         file_details->Flags |= OFN_FILEMUSTEXIST;
+      }
 
-    file_details.lpfnHook = (LPOFNHOOKPROC) file_dialog_callback;
+    file_details->lpfnHook = (LPOFNHOOKPROC) file_dialog_callback;
 
-    if (GetOpenFileName (&file_details))
+    file_opened = GetOpenFileName (file_details);
+
+    UNBLOCK_INPUT;
+
+    if (file_opened)
       {
        dostounix_filename (filename);
-       if (file_details.nFilterIndex == 2)
+
+       if (file_details->nFilterIndex == 2)
          {
-           /* "Folder Only" selected - strip dummy file name.  */
+           /* "Directories" selected - strip dummy file name.  */
            char * last = strrchr (filename, '/');
            *last = '\0';
          }
@@ -7789,7 +7966,6 @@ specified.  Ensure that file exists if MUSTMATCH is non-nil.  */)
                               dir, mustmatch, dir, Qfile_name_history,
                               default_filename, Qnil);
 
-    UNBLOCK_INPUT;
     file = unbind_to (count, file);
   }
 
@@ -7809,8 +7985,12 @@ specified.  Ensure that file exists if MUSTMATCH is non-nil.  */)
  ***********************************************************************/
 
 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;
 {
@@ -7863,7 +8043,7 @@ Returns an X font string corresponding to the selection.  */)
 DEFUN ("w32-send-sys-command", Fw32_send_sys_command,
        Sw32_send_sys_command, 1, 2, 0,
        doc: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
-Some useful values for command are #xf030 to maximise frame (#xf020
+Some useful values for COMMAND are #xf030 to maximize frame (#xf020
 to minimize), #xf120 to restore frame to original size, and #xf100
 to activate the menubar for keyboard access.  #xf140 activates the
 screen saver if defined.
@@ -7943,7 +8123,7 @@ lookup_vk_code (char *key)
 
 /* Convert a one-element vector style key sequence to a hot key
    definition.  */
-static int
+static Lisp_Object
 w32_parse_hot_key (key)
      Lisp_Object key;
 {
@@ -7975,7 +8155,7 @@ w32_parse_hot_key (key)
   if (SYMBOLP (c))
     {
       c = parse_modifiers (c);
-      lisp_modifiers = Fcar (Fcdr (c));
+      lisp_modifiers = XINT (Fcar (Fcdr (c)));
       c = Fcar (c);
       if (!SYMBOLP (c))
        abort ();
@@ -8044,8 +8224,13 @@ The return value is the hotkey-id if registered, otherwise nil.  */)
 
       /* Notify input thread about new hot-key definition, so that it
         takes effect without needing to switch focus.  */
+#ifdef USE_LISP_UNION_TYPE
+      PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY,
+                        (WPARAM) key.i, 0);
+#else
       PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY,
                         (WPARAM) key, 0);
+#endif
     }
 
   return key;
@@ -8053,7 +8238,7 @@ The return value is the hotkey-id if registered, otherwise nil.  */)
 
 DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key,
        Sw32_unregister_hot_key, 1, 1, 0,
-       doc: /* Unregister HOTKEY as a hot-key combination.  */)
+       doc: /* Unregister KEY as a hot-key combination.  */)
   (key)
      Lisp_Object key;
 {
@@ -8068,8 +8253,14 @@ DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key,
     {
       /* Notify input thread about hot-key definition being removed, so
         that it takes effect without needing focus switch.  */
+#ifdef USE_LISP_UNION_TYPE
+      if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_UNREGISTER_HOT_KEY,
+                            (WPARAM) XINT (XCAR (item)), (LPARAM) item.i))
+#else
       if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_UNREGISTER_HOT_KEY,
                             (WPARAM) XINT (XCAR (item)), (LPARAM) item))
+
+#endif
        {
          MSG msg;
          GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
@@ -8089,7 +8280,8 @@ DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys,
 
 DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key,
        Sw32_reconstruct_hot_key, 1, 1, 0,
-       doc: /* Convert hot-key ID to a lisp key combination.  */)
+       doc: /* Convert hot-key ID to a lisp key combination.
+usage: (w32-reconstruct-hot-key ID)  */)
   (hotkeyid)
      Lisp_Object hotkeyid;
 {
@@ -8142,8 +8334,13 @@ is set to off if the low bit of NEW-STATE is zero, otherwise on.  */)
   if (!dwWindowsThreadId)
     return make_number (w32_console_toggle_lock_key (vk_code, new_state));
 
+#ifdef USE_LISP_UNION_TYPE
+  if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_TOGGLE_LOCK_KEY,
+                        (WPARAM) vk_code, (LPARAM) new_state.i))
+#else
   if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_TOGGLE_LOCK_KEY,
                         (WPARAM) vk_code, (LPARAM) new_state))
+#endif
     {
       MSG msg;
       GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
@@ -8323,7 +8520,7 @@ DEFUN ("default-printer-name", Fdefault_printer_name, Sdefault_printer_name,
                            Initialization
  ***********************************************************************/
 
-/* Keep this list in the same order as frame_parms in frame.c. 
+/* Keep this list in the same order as frame_parms in frame.c.
    Use 0 for unsupported frame parameters.  */
 
 frame_parm_handler w32_frame_parm_handlers[] =
@@ -8408,39 +8605,58 @@ syms_of_w32fns ()
   w32_grabbed_keys = Qnil;
 
   DEFVAR_LISP ("w32-color-map", &Vw32_color_map,
-              doc: /* An array of color name mappings for windows.  */);
+              doc: /* An array of color name mappings for Windows.  */);
   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", &Vw32_quit_key,
-             doc: /* If non-zero, the virtual key code for an alternative quit key.  */);
-  XSETINT (Vw32_quit_key, 0);
+  DEFVAR_INT ("w32-quit-key", &w32_quit_key,
+              doc: /* If non-zero, the virtual key code for an alternative quit key.  */);
+  w32_quit_key = 0;
 
   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_INT ("w32-phantom-key-code",
+  DEFVAR_LISP ("w32-phantom-key-code",
               &Vw32_phantom_key_code,
-             doc: /* Virtual key code used to generate \"phantom\" key presses.
+              doc: /* Virtual key code used to generate \"phantom\" key presses.
 Value is a number between 0 and 255.
 
 Phantom key presses are generated in order to stop the system from
@@ -8448,33 +8664,33 @@ acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
 `w32-pass-rwindow-to-system' is nil.  */);
   /* Although 255 is technically not a valid key code, it works and
      means that this hack won't interfere with any real key code.  */
-  Vw32_phantom_key_code = 255;
+  XSETINT (Vw32_phantom_key_code, 255);
 
   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;
 
@@ -8482,7 +8698,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;
 
@@ -8490,7 +8706,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;
 
@@ -8503,25 +8719,25 @@ Any other value will cause the key to be ignored.  */);
   Vw32_enable_palette = Qt;
 
   DEFVAR_INT ("w32-mouse-button-tolerance",
-             &Vw32_mouse_button_tolerance,
+             &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.  */);
-  XSETINT (Vw32_mouse_button_tolerance, GetDoubleClickTime () / 2);
+  w32_mouse_button_tolerance = GetDoubleClickTime () / 2;
 
   DEFVAR_INT ("w32-mouse-move-interval",
-             &Vw32_mouse_move_interval,
+             &w32_mouse_move_interval,
              doc: /* Minimum interval between mouse move events.
 The value is the minimum time in milliseconds that must elapse between
 successive mouse move (or scroll bar drag) events before they are
 reported as lisp events.  */);
-  XSETINT (Vw32_mouse_move_interval, 0);
+  w32_mouse_move_interval = 0;
 
   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.
@@ -8613,7 +8829,7 @@ fontsets are automatically created.  */);
   DEFVAR_BOOL ("w32-strict-painting",
                &w32_strict_painting,
               doc: /* Non-nil means use strict rules for repainting frames.
-Set this to nil to get the old behaviour for repainting; this should
+Set this to nil to get the old behavior for repainting; this should
 only be necessary if the default setting causes problems.  */);
   w32_strict_painting = 1;
 
@@ -8644,6 +8860,8 @@ versions of Windows) characters.  */);
   staticpro (&Qw32_charset_ansi);
   Qw32_charset_ansi = intern ("w32-charset-ansi");
   staticpro (&Qw32_charset_symbol);
+  Qw32_charset_default = intern ("w32-charset-default");
+  staticpro (&Qw32_charset_default);
   Qw32_charset_symbol = intern ("w32-charset-symbol");
   staticpro (&Qw32_charset_shiftjis);
   Qw32_charset_shiftjis = intern ("w32-charset-shiftjis");
@@ -8798,31 +9016,36 @@ void globals_of_w32fns ()
     GetProcAddress (user32_lib, "GetClipboardSequenceNumber");
 
   DEFVAR_INT ("w32-ansi-code-page",
-             &Vw32_ansi_code_page,
+             &w32_ansi_code_page,
              doc: /* The ANSI code page used by the system.  */);
-  XSETINT (Vw32_ansi_code_page, GetACP ());
+  w32_ansi_code_page = GetACP ();
 }
 
 #undef abort
 
+void w32_abort (void) NO_RETURN;
+
 void
 w32_abort()
 {
   int button;
   button = MessageBox (NULL,
                       "A fatal error has occurred!\n\n"
-                      "Select Abort to exit, Retry to debug, Ignore to continue",
-                      "Emacs Abort Dialog",
+                      "Would you like to attach a debugger?\n\n"
+                      "Select YES to debug, NO to abort Emacs"
+#if __GNUC__
+                      "\n\n(type \"gdb -p <emacs-PID>\" and\n"
+                      "\"continue\" inside GDB before clicking YES.)"
+#endif
+                      , "Emacs Abort Dialog",
                       MB_ICONEXCLAMATION | MB_TASKMODAL
-                      | MB_SETFOREGROUND | MB_ABORTRETRYIGNORE);
+                      | MB_SETFOREGROUND | MB_YESNO);
   switch (button)
     {
-    case IDRETRY:
+    case IDYES:
       DebugBreak ();
-      break;
-    case IDIGNORE:
-      break;
-    case IDABORT:
+      exit (2);        /* tell the compiler we will never return */
+    case IDNO:
     default:
       abort ();
       break;