]> code.delx.au - gnu-emacs/blobdiff - src/w32fns.c
(find_field): Fix comment.
[gnu-emacs] / src / w32fns.c
index f56ecc35cc6c8d2b146476a082b18752c1f6c66b..093739d1603d1509212e74666f68288fcde6adb9 100644 (file)
@@ -1,6 +1,6 @@
 /* Graphical user interface functions for the Microsoft W32 API.
-   Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 98, 1999, 2000, 01, 2004
-     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;
 
@@ -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.  */
 
@@ -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;
@@ -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));
@@ -2692,6 +2694,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;
@@ -2749,6 +2769,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);
@@ -3248,6 +3270,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 ();
@@ -3263,12 +3290,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
@@ -3317,11 +3353,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:
@@ -3331,6 +3369,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);
@@ -3457,7 +3496,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;
@@ -3495,13 +3540,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);
@@ -3818,6 +3872,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;
        }
 
@@ -3830,7 +3885,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
   return 0;
 }
 
-void
+static void
 my_create_window (f)
      struct frame * f;
 {
@@ -3846,7 +3901,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;
 {
@@ -4045,15 +4100,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;
@@ -4074,7 +4129,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);
@@ -4084,7 +4139,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))
@@ -4094,7 +4149,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))
@@ -4104,8 +4159,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);
@@ -4135,7 +4190,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;
 
@@ -4177,7 +4232,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.  */
@@ -4201,49 +4256,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);
 
 
@@ -4255,16 +4310,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;
@@ -4277,13 +4332,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);
 
@@ -4293,16 +4348,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.
@@ -4322,17 +4377,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.  */
@@ -4340,7 +4384,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;
 
@@ -4528,7 +4572,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;
@@ -4576,6 +4620,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
@@ -4642,6 +4704,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);
 
@@ -4649,11 +4712,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);
@@ -5237,9 +5311,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,
@@ -5342,7 +5420,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;
@@ -5579,11 +5657,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;
@@ -5622,8 +5700,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
@@ -6181,10 +6259,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;
 {
@@ -6265,7 +6343,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).
@@ -6338,9 +6416,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 */
@@ -6368,7 +6446,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.  */)
@@ -6381,7 +6459,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.
@@ -7360,16 +7438,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);
@@ -7394,7 +7478,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
@@ -7539,7 +7623,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;
@@ -7592,9 +7676,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).  */
@@ -7686,7 +7773,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);
@@ -7700,8 +7788,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);
            }
        }
@@ -7709,36 +7799,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);
 
@@ -7746,9 +7851,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';
@@ -7757,35 +7860,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;
+    file_opened = GetOpenFileName (file_details);
 
-    if (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';
          }
@@ -7801,7 +7929,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);
   }
 
@@ -7821,8 +7948,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;
 {
@@ -7875,7 +8006,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.
@@ -8070,7 +8201,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;
 {
@@ -8090,7 +8221,7 @@ DEFUN ("w32-unregister-hot-key", Fw32_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.i))
+                            (WPARAM) XINT (XCAR (item)), (LPARAM) item))
 
 #endif
        {
@@ -8112,7 +8243,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;
 {
@@ -8170,7 +8302,7 @@ is set to off if the low bit of NEW-STATE is zero, otherwise on.  */)
                         (WPARAM) vk_code, (LPARAM) new_state.i))
 #else
   if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_TOGGLE_LOCK_KEY,
-                        (WPARAM) vk_code, (LPARAM) new_state.i))
+                        (WPARAM) vk_code, (LPARAM) new_state))
 #endif
     {
       MSG msg;
@@ -8351,7 +8483,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[] =
@@ -8436,7 +8568,7 @@ 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,
@@ -8641,7 +8773,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;
 
@@ -8672,6 +8804,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");
@@ -8833,24 +8967,29 @@ void globals_of_w32fns ()
 
 #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;