Make "xfree (NULL)" a no-op; remove useless if-before-xfree.
[bpt/emacs.git] / src / w32fns.c
index 491cced..e83acf0 100644 (file)
@@ -1,13 +1,14 @@
 /* Graphical user interface functions for the Microsoft W32 API.
    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-                 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+                 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,9 +16,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 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., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* Added by Kevin Gallo */
 
@@ -30,22 +29,23 @@ Boston, MA 02110-1301, USA.  */
 #include <math.h>
 
 #include "lisp.h"
-#include "charset.h"
-#include "dispextern.h"
 #include "w32term.h"
-#include "keyboard.h"
 #include "frame.h"
 #include "window.h"
 #include "buffer.h"
-#include "fontset.h"
 #include "intervals.h"
+#include "dispextern.h"
+#include "keyboard.h"
 #include "blockinput.h"
 #include "epaths.h"
-#include "w32heap.h"
-#include "termhooks.h"
+#include "character.h"
+#include "charset.h"
 #include "coding.h"
 #include "ccl.h"
+#include "fontset.h"
 #include "systime.h"
+#include "termhooks.h"
+#include "w32heap.h"
 
 #include "bitmaps/gray.xbm"
 
@@ -57,8 +57,12 @@ Boston, MA 02110-1301, USA.  */
 #include <objbase.h>
 
 #include <dlgs.h>
+#include <imm.h>
 #define FILE_NAME_TEXT_FIELD edt1
 
+#include "font.h"
+#include "w32font.h"
+
 void syms_of_w32fns ();
 void globals_of_w32fns ();
 
@@ -67,7 +71,9 @@ 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));
+#if OLD_FONT
 extern XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, int));
+#endif
 
 extern int quit_char;
 
@@ -147,6 +153,11 @@ Lisp_Object Vx_no_window_manager;
 
 int display_hourglass_p;
 
+/* If non-zero, a w32 timer that, when it expires, displays an
+   hourglass cursor on all frames.  */
+static unsigned hourglass_timer = 0;
+static HWND hourglass_hwnd = NULL;
+
 /* The background and shape of the mouse pointer, and shape when not
    over text or in the modeline.  */
 
@@ -254,13 +265,42 @@ static unsigned mouse_move_timer = 0;
 /* Window that is tracking the mouse.  */
 static HWND track_mouse_window;
 
+/* Multi-monitor API definitions that are not pulled from the headers
+   since we are compiling for NT 4.  */
+#ifndef MONITOR_DEFAULT_TO_NEAREST
+#define MONITOR_DEFAULT_TO_NEAREST 2
+#endif
+/* MinGW headers define MONITORINFO unconditionally, but MSVC ones don't.
+   To avoid a compile error on one or the other, redefine with a new name.  */
+struct MONITOR_INFO
+{
+    DWORD   cbSize;
+    RECT    rcMonitor;
+    RECT    rcWork;
+    DWORD   dwFlags;
+};
+
 typedef BOOL (WINAPI * TrackMouseEvent_Proc)
   (IN OUT LPTRACKMOUSEEVENT lpEventTrack);
+typedef LONG (WINAPI * ImmGetCompositionString_Proc)
+  (IN HIMC context, IN DWORD index, OUT LPVOID buffer, IN DWORD bufLen);
+typedef HIMC (WINAPI * ImmGetContext_Proc) (IN HWND window);
+typedef HMONITOR (WINAPI * MonitorFromPoint_Proc) (IN POINT pt, IN DWORD flags);
+typedef BOOL (WINAPI * GetMonitorInfo_Proc)
+  (IN HMONITOR monitor, OUT struct MONITOR_INFO* info);
 
 TrackMouseEvent_Proc track_mouse_event_fn = NULL;
 ClipboardSequence_Proc clipboard_sequence_fn = NULL;
+ImmGetCompositionString_Proc get_composition_string_fn = NULL;
+ImmGetContext_Proc get_ime_context_fn = NULL;
+MonitorFromPoint_Proc monitor_from_point_fn = NULL;
+GetMonitorInfo_Proc get_monitor_info_fn = NULL;
+
 extern AppendMenuW_Proc unicode_append_menu;
 
+/* Flag to selectively ignore WM_IME_CHAR messages.  */
+static int ignore_ime_char = 0;
+
 /* W95 mousewheel handler */
 unsigned int msh_mousewheel = 0;
 
@@ -268,6 +308,7 @@ unsigned int msh_mousewheel = 0;
 #define MOUSE_BUTTON_ID        1
 #define MOUSE_MOVE_ID  2
 #define MENU_FREE_ID 3
+#define HOURGLASS_ID 4
 /* The delay (milliseconds) before a menu is freed after WM_EXITMENULOOP
    is received.  */
 #define MENU_FREE_DELAY 1000
@@ -299,6 +340,15 @@ static HWND w32_visible_system_caret_hwnd;
 extern HMENU current_popup_menu;
 static int menubar_in_use = 0;
 
+/* From w32uniscribe.c  */
+extern void syms_of_w32uniscribe ();
+extern int uniscribe_available;
+
+/* Function prototypes for hourglass support.  */
+static void show_hourglass P_ ((struct frame *));
+static void hide_hourglass P_ ((void));
+
+
 \f
 /* Error if we are not connected to MS-Windows.  */
 void
@@ -379,16 +429,14 @@ x_window_to_frame (dpyinfo, wdesc)
   Lisp_Object tail, frame;
   struct frame *f;
 
-  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
+  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
     {
       frame = XCAR (tail);
-      if (!GC_FRAMEP (frame))
+      if (!FRAMEP (frame))
         continue;
       f = XFRAME (frame);
       if (!FRAME_W32_P (f) || FRAME_W32_DISPLAY_INFO (f) != dpyinfo)
        continue;
-      if (f->output_data.w32->hourglass_window == wdesc)
-        return f;
 
       if (FRAME_W32_WINDOW (f) == wdesc)
         return f;
@@ -454,7 +502,7 @@ x_real_positions (f, xptr, yptr)
 
 DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color,
        Sw32_define_rgb_color, 4, 4, 0,
-       doc: /* Convert RGB numbers to a windows color reference and associate with NAME.
+       doc: /* Convert RGB numbers to a Windows color reference and associate with NAME.
 This adds or updates a named color to `w32-color-map', making it
 available for use.  The original entry's RGB ref is returned, or nil
 if the entry is new.  */)
@@ -2449,8 +2497,8 @@ register_hot_keys (hwnd)
 {
   Lisp_Object keylist;
 
-  /* Use GC_CONSP, since we are called asynchronously.  */
-  for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
+  /* Use CONSP, since we are called asynchronously.  */
+  for (keylist = w32_grabbed_keys; CONSP (keylist); keylist = XCDR (keylist))
     {
       Lisp_Object key = XCAR (keylist);
 
@@ -2469,8 +2517,7 @@ unregister_hot_keys (hwnd)
 {
   Lisp_Object keylist;
 
-  /* Use GC_CONSP, since we are called asynchronously.  */
-  for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
+  for (keylist = w32_grabbed_keys; CONSP (keylist); keylist = XCDR (keylist))
     {
       Lisp_Object key = XCAR (keylist);
 
@@ -2577,8 +2624,12 @@ w32_msg_pump (deferred_msg * msg_buf)
                  abort ();
              }
              break;
+#ifdef MSG_DEBUG
+              /* Broadcast messages make it here, so you need to be looking
+                 for something in particular for this to be useful.  */
            default:
              DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message));
+#endif
            }
        }
       else
@@ -2705,7 +2756,7 @@ w32_msg_worker (void *arg)
   dummy_buf.w32msg.msg.hwnd = NULL;
   dummy_buf.w32msg.msg.message = WM_NULL;
 
-  /* This is the inital message loop which should only exit when the
+  /* This is the initial message loop which should only exit when the
      application quits.  */
   w32_msg_pump (&dummy_buf);
 
@@ -2957,7 +3008,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
             they don't produce WM_CHAR messages).  This ensures that
             indicator lights are toggled promptly on Windows 9x, for
             example.  */
-         if (lispy_function_keys[wParam] != 0)
+         if (wParam < 256 && lispy_function_keys[wParam])
            {
              windows_translate = 1;
              goto translate;
@@ -3079,7 +3130,7 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
          break;
        default:
          /* If not defined as a function key, change it to a WM_CHAR message. */
-         if (lispy_function_keys[wParam] == 0)
+         if (wParam > 255 || !lispy_function_keys[wParam])
            {
              DWORD modifiers = construct_console_modifiers ();
 
@@ -3130,7 +3181,8 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
                        {
                          /* Forward asciified character sequence.  */
                          post_character_message
-                           (hwnd, WM_CHAR, key.uChar.AsciiChar, lParam,
+                           (hwnd, WM_CHAR,
+                             (unsigned char) key.uChar.AsciiChar, lParam,
                             w32_get_key_modifiers (wParam, lParam));
                          w32_kbd_patch_key (&key);
                        }
@@ -3149,7 +3201,6 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
       if (windows_translate)
        {
          MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} };
-
          windows_msg.time = GetMessageTime ();
          TranslateMessage (&windows_msg);
          goto dflt;
@@ -3163,6 +3214,64 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
                              w32_get_key_modifiers (wParam, lParam));
       break;
 
+    case WM_UNICHAR:
+      /* WM_UNICHAR looks promising from the docs, but the exact
+         circumstances in which TranslateMessage sends it is one of those
+         Microsoft secret API things that EU and US courts are supposed
+         to have put a stop to already. Spy++ shows it being sent to Notepad
+         and other MS apps, but never to Emacs.
+
+         Some third party IMEs send it in accordance with the official
+         documentation though, so handle it here.
+
+         UNICODE_NOCHAR is used to test for support for this message.
+         TRUE indicates that the message is supported.  */
+      if (wParam == UNICODE_NOCHAR)
+        return TRUE;
+
+      {
+        W32Msg wmsg;
+        wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam);
+        signal_user_input ();
+        my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+      }
+      break;
+
+    case WM_IME_CHAR:
+      /* If we can't get the IME result as unicode, use default processing,
+         which will at least allow characters decodable in the system locale
+         get through.  */
+      if (!get_composition_string_fn)
+        goto dflt;
+
+      else if (!ignore_ime_char)
+        {
+          wchar_t * buffer;
+          int size, i;
+          W32Msg wmsg;
+          HIMC context = get_ime_context_fn (hwnd);
+          wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam);
+          /* Get buffer size.  */
+          size = get_composition_string_fn (context, GCS_RESULTSTR, buffer, 0);
+          buffer = alloca(size);
+          size = get_composition_string_fn (context, GCS_RESULTSTR,
+                                            buffer, size);
+          signal_user_input ();
+          for (i = 0; i < size / sizeof (wchar_t); i++)
+            {
+              my_post_msg (&wmsg, hwnd, WM_UNICHAR, (WPARAM) buffer[i],
+                           lParam);
+            }
+          /* We output the whole string above, so ignore following ones
+             until we are notified of the end of composition.  */
+          ignore_ime_char = 1;
+        }
+      break;
+
+    case WM_IME_ENDCOMPOSITION:
+      ignore_ime_char = 0;
+      goto dflt;
+
       /* Simulate middle mouse button events when left and right buttons
         are used together, but only if user has two button mouse. */
     case WM_LBUTTONDOWN:
@@ -3428,6 +3537,12 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
               menubar_in_use = 0;
            }
        }
+      else if (wParam == hourglass_timer)
+       {
+         KillTimer (hwnd, hourglass_timer);
+         hourglass_timer = 0;
+         show_hourglass (x_window_to_frame (dpyinfo, hwnd));
+       }
       return 0;
 
     case WM_NCACTIVATE:
@@ -3493,6 +3608,11 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
       */
       if (f && menubar_in_use && current_popup_menu == NULL)
        menu_free_timer = SetTimer (hwnd, MENU_FREE_ID, MENU_FREE_DELAY, NULL);
+
+      /* If hourglass cursor should be displayed, display it now.  */
+      if (f && f->output_data.w32->hourglass_p)
+       SetCursor (f->output_data.w32->hourglass_cursor);
+
       goto dflt;
 
     case WM_MENUSELECT:
@@ -3761,15 +3881,27 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
 
     case WM_SETCURSOR:
       if (LOWORD (lParam) == HTCLIENT)
-       return 0;
-
+       {
+         f = x_window_to_frame (dpyinfo, hwnd);
+         if (f->output_data.w32->hourglass_p && !menubar_in_use
+             && !current_popup_menu)
+           SetCursor (f->output_data.w32->hourglass_cursor);
+         else
+           SetCursor (f->output_data.w32->current_cursor);
+         return 0;
+       }
       goto dflt;
 
     case WM_EMACS_SETCURSOR:
       {
        Cursor cursor = (Cursor) wParam;
-       if (cursor)
-         SetCursor (cursor);
+       f = x_window_to_frame (dpyinfo, hwnd);
+       if (f && cursor)
+         {
+           f->output_data.w32->current_cursor = cursor;
+           if (!f->output_data.w32->hourglass_p)
+             SetCursor (cursor);
+         }
        return 0;
       }
 
@@ -4135,6 +4267,36 @@ unwind_create_frame (frame)
   return Qnil;
 }
 
+static void
+x_default_font_parameter (f, parms)
+     struct frame *f;
+     Lisp_Object parms;
+{
+  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+  Lisp_Object font = x_get_arg (dpyinfo, parms, Qfont, "font", "Font",
+                                RES_TYPE_STRING);
+
+  if (!STRINGP (font))
+    {
+      int i;
+      static char *names[]
+        = { "Courier New-10",
+            "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1",
+            "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1",
+            "Fixedsys",
+            NULL };
+
+      for (i = 0; names[i]; i++)
+        {
+          font = font_open_by_name (f, names[i]);
+          if (! NILP (font))
+            break;
+        }
+      if (NILP (font))
+        error ("No suitable font was found");
+    }
+  x_default_parameter (f, parms, Qfont, font, "font", "Font", RES_TYPE_STRING);
+}
 
 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
        1, 1, 0,
@@ -4165,6 +4327,10 @@ This function is an internal primitive--use `make-frame' instead.  */)
 
   check_w32 ();
 
+  /* Make copy of frame parameters because the original is in pure
+     storage now. */
+  parameters = Fcopy_alist (parameters);
+
   /* Use this general default value to start with
      until we know if this frame has a specified name.  */
   Vx_resource_name = Vinvocation_name;
@@ -4270,39 +4436,18 @@ This function is an internal primitive--use `make-frame' instead.  */)
       specbind (Qx_resource_name, name);
     }
 
-  /* Extract the window parameters from the supplied values
-     that are needed to determine window geometry.  */
-  {
-    Lisp_Object font;
-
-    font = w32_get_arg (parameters, Qfont, "font", "Font", RES_TYPE_STRING);
-
-    BLOCK_INPUT;
-    /* First, try whatever font the caller has specified.  */
-    if (STRINGP (font))
-      {
-        tem = Fquery_fontset (font, Qnil);
-        if (STRINGP (tem))
-          font = x_new_fontset (f, SDATA (tem));
-        else
-          font = x_new_font (f, SDATA (font));
-      }
-    /* Try out a font which we hope has bold and italic variations.  */
-    if (!STRINGP (font))
-      font = x_new_font (f, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
-    if (! STRINGP (font))
-      font = x_new_font (f, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
-    /* If those didn't work, look for something which will at least work.  */
-    if (! STRINGP (font))
-      font = x_new_font (f, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
-    UNBLOCK_INPUT;
-    if (! STRINGP (font))
-      font = build_string ("Fixedsys");
+  f->resx = dpyinfo->resx;
+  f->resy = dpyinfo->resy;
 
-    x_default_parameter (f, parameters, Qfont, font,
-                        "font", "Font", RES_TYPE_STRING);
-  }
+  if (uniscribe_available)
+    register_font_driver (&uniscribe_font_driver, f);
+  register_font_driver (&w32font_driver, f);
 
+  x_default_parameter (f, parameters, Qfont_backend, Qnil,
+                      "fontBackend", "FontBackend", RES_TYPE_STRING);
+  /* Extract the window parameters from the supplied values
+     that are needed to determine window geometry.  */
+  x_default_font_parameter (f, parameters);
   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
@@ -4375,6 +4520,8 @@ 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);
 
+  f->output_data.w32->current_cursor = f->output_data.w32->nontext_cursor;
+
   window_prompting = x_figure_window_size (f, parameters, 1);
 
   tem = w32_get_arg (parameters, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
@@ -4488,6 +4635,8 @@ DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
 }
 
 \f
+#if OLD_FONT
+
 /* Return the charset portion of a font name.  */
 char *
 xlfd_charset_of_font (char * fontname)
@@ -4678,10 +4827,10 @@ 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)
+    if ((lf.lfPitchAndFamily & 0x03) == FIXED_PITCH)
       {
        /* Fixed width font.  */
-       fontp->average_width = fontp->space_width = FONT_WIDTH (font);
+       fontp->average_width = fontp->space_width = FONT_AVG_WIDTH (font);
       }
     else
       {
@@ -4691,11 +4840,12 @@ w32_load_system_font (f, fontname, size)
        if (pcm)
          fontp->space_width = pcm->width;
        else
-         fontp->space_width = FONT_WIDTH (font);
+         fontp->space_width = FONT_AVG_WIDTH (font);
 
        fontp->average_width = font->tm.tmAveCharWidth;
       }
 
+    fontp->charset = -1;
     charset = xlfd_charset_of_font (fontname);
 
   /* Cache the W32 codepage for a font.  This makes w32_encode_char
@@ -4722,7 +4872,7 @@ w32_load_system_font (f, fontname, size)
        (0:0x20..0x7F, 1:0xA0..0xFF,
        (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
        2:0xA020..0xFF7F).  For the moment, we don't know which charset
-       uses this font.  So, we set information in fontp->encoding[1]
+       uses this font.  So, we set information in fontp->encoding_type
        which is never used by any charset.  If mapping can't be
        decided, set FONT_ENCODING_NOT_DECIDED.  */
 
@@ -4730,9 +4880,9 @@ w32_load_system_font (f, fontname, size)
        type FONT_ENCODING_NOT_DECIDED.  */
     encoding = strrchr (fontp->name, '-');
     if (encoding && strnicmp (encoding+1, "sjis", 4) == 0)
-      fontp->encoding[1] = 4;
+      fontp->encoding_type = 4;
     else
-      fontp->encoding[1] = FONT_ENCODING_NOT_DECIDED;
+      fontp->encoding_type = FONT_ENCODING_NOT_DECIDED;
 
     /* The following three values are set to 0 under W32, which is
        what they get set to if XGetFontProperty fails under X.  */
@@ -4776,7 +4926,7 @@ w32_load_font (f, fontname, size)
       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.
+      /* 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
@@ -4805,13 +4955,14 @@ w32_unload_font (dpyinfo, font)
 {
   if (font)
     {
-      if (font->per_char) xfree (font->per_char);
+      xfree (font->per_char);
       if (font->bdf) w32_free_bdf_font (font->bdf);
 
       if (font->hfont) DeleteObject (font->hfont);
       xfree (font);
     }
 }
+#endif /* OLD_FONT */
 
 /* The font conversion stuff between x and w32 */
 
@@ -4842,16 +4993,16 @@ x_to_w32_weight (lpw)
 {
   if (!lpw) return (FW_DONTCARE);
 
-  if (stricmp (lpw, "heavy") == 0)             return FW_HEAVY;
-  else if (stricmp (lpw, "extrabold") == 0)    return FW_EXTRABOLD;
-  else if (stricmp (lpw, "bold") == 0)         return FW_BOLD;
-  else if (stricmp (lpw, "demibold") == 0)     return FW_SEMIBOLD;
-  else if (stricmp (lpw, "semibold") == 0)     return FW_SEMIBOLD;
-  else if (stricmp (lpw, "medium") == 0)       return FW_MEDIUM;
-  else if (stricmp (lpw, "normal") == 0)       return FW_NORMAL;
-  else if (stricmp (lpw, "light") == 0)        return FW_LIGHT;
-  else if (stricmp (lpw, "extralight") == 0)   return FW_EXTRALIGHT;
-  else if (stricmp (lpw, "thin") == 0)         return FW_THIN;
+  if (xstrcasecmp (lpw, "heavy") == 0)             return FW_HEAVY;
+  else if (xstrcasecmp (lpw, "extrabold") == 0)    return FW_EXTRABOLD;
+  else if (xstrcasecmp (lpw, "bold") == 0)         return FW_BOLD;
+  else if (xstrcasecmp (lpw, "demibold") == 0)     return FW_SEMIBOLD;
+  else if (xstrcasecmp (lpw, "semibold") == 0)     return FW_SEMIBOLD;
+  else if (xstrcasecmp (lpw, "medium") == 0)       return FW_MEDIUM;
+  else if (xstrcasecmp (lpw, "normal") == 0)       return FW_NORMAL;
+  else if (xstrcasecmp (lpw, "light") == 0)        return FW_LIGHT;
+  else if (xstrcasecmp (lpw, "extralight") == 0)   return FW_EXTRALIGHT;
+  else if (xstrcasecmp (lpw, "thin") == 0)         return FW_THIN;
   else
     return FW_DONTCARE;
 }
@@ -4874,7 +5025,7 @@ w32_to_x_weight (fnweight)
     return "*";
 }
 
-static LONG
+LONG
 x_to_w32_charset (lpcs)
     char * lpcs;
 {
@@ -4886,12 +5037,16 @@ x_to_w32_charset (lpcs)
   if (strncmp (lpcs, "*-#", 3) == 0)
     return atoi (lpcs + 3);
 
+  /* All Windows fonts qualify as unicode.  */
+  if (!strncmp (lpcs, "iso10646", 8))
+    return DEFAULT_CHARSET;
+
   /* Handle wildcards by ignoring them; eg. treat "big5*-*" as "big5".  */
   charset = alloca (len + 1);
   strcpy (charset, lpcs);
   lpcs = strchr (charset, '*');
   if (lpcs)
-    *lpcs = 0;
+    *lpcs = '\0';
 
   /* Look through w32-charset-info-alist for the character set.
      Format of each entry is
@@ -4902,7 +5057,7 @@ x_to_w32_charset (lpcs)
   if (NILP (this_entry))
     {
       /* At startup, we want iso8859-1 fonts to come up properly. */
-      if (stricmp (charset, "iso8859-1") == 0)
+      if (xstrcasecmp (charset, "iso8859-1") == 0)
         return ANSI_CHARSET;
       else
         return DEFAULT_CHARSET;
@@ -4958,12 +5113,27 @@ x_to_w32_charset (lpcs)
 }
 
 
-static char *
-w32_to_x_charset (fncharset)
+char *
+w32_to_x_charset (fncharset, matching)
     int fncharset;
+    char *matching;
 {
   static char buf[32];
   Lisp_Object charset_type;
+  int match_len = 0;
+
+  if (matching)
+    {
+      /* If fully specified, accept it as it is.  Otherwise use a
+        substring match. */
+      char *wildcard = strchr (matching, '*');
+      if (wildcard)
+       *wildcard = '\0';
+      else if (strchr (matching, '-'))
+       return matching;
+
+      match_len = strlen (matching);
+    }
 
   switch (fncharset)
     {
@@ -5048,6 +5218,7 @@ w32_to_x_charset (fncharset)
   {
     Lisp_Object rest;
     char * best_match = NULL;
+    int matching_found = 0;
 
     /* Look through w32-charset-info-alist for the character set.
        Prefer ISO codepages, and prefer lower numbers in the ISO
@@ -5083,12 +5254,34 @@ w32_to_x_charset (fncharset)
             /* If we don't have a match already, then this is the
                best.  */
             if (!best_match)
-              best_match = x_charset;
-            /* If this is an ISO codepage, and the best so far isn't,
-               then this is better.  */
-            else if (strnicmp (best_match, "iso", 3) != 0
-                     && strnicmp (x_charset, "iso", 3) == 0)
-              best_match = x_charset;
+             {
+               best_match = x_charset;
+               if (matching && !strnicmp (x_charset, matching, match_len))
+                 matching_found = 1;
+             }
+           /* If we already found a match for MATCHING, then
+              only consider other matches.  */
+           else if (matching_found
+                    && strnicmp (x_charset, matching, match_len))
+             continue;
+           /* If this matches what we want, and the best so far doesn't,
+              then this is better.  */
+           else if (!matching_found && matching
+                    && !strnicmp (x_charset, matching, match_len))
+             {
+               best_match = x_charset;
+               matching_found = 1;
+             }
+           /* If this is fully specified, and the best so far isn't,
+              then this is better.  */
+           else if ((!strchr (best_match, '-') && strchr (x_charset, '-'))
+           /* If this is an ISO codepage, and the best so far isn't,
+              then this is better, but only if it fully specifies the
+              encoding.  */
+               || (strnicmp (best_match, "iso", 3) != 0
+                   && strnicmp (x_charset, "iso", 3) == 0
+                   && strchr (x_charset, '-')))
+               best_match = x_charset;
             /* If both are ISO8859 codepages, choose the one with the
                lowest number in the encoding field.  */
             else if (strnicmp (best_match, "iso8859-", 8) == 0
@@ -5110,6 +5303,17 @@ w32_to_x_charset (fncharset)
       }
 
     strncpy (buf, best_match, 31);
+    /* If the charset is not fully specified, put -0 on the end.  */
+    if (!strchr (best_match, '-'))
+      {
+       int pos = strlen (best_match);
+       /* Charset specifiers shouldn't be very long.  If it is a made
+          up one, truncating it should not do any harm since it isn't
+          recognized anyway.  */
+       if (pos > 29)
+         pos = 29;
+       strcpy (buf + pos, "-0");
+      }
     buf[31] = '\0';
     return buf;
   }
@@ -5209,7 +5413,8 @@ w32_to_all_x_charsets (fncharset)
   {
     Lisp_Object rest;
     /* Look through w32-charset-info-alist for the character set.
-       Only return charsets for codepages which are installed.
+       Only return fully specified charsets for codepages which are
+       installed.
 
        Format of each entry in Vw32_charset_info_alist is
          (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
@@ -5232,6 +5437,9 @@ w32_to_all_x_charsets (fncharset)
         w32_charset = XCAR (XCDR (this_entry));
         codepage = XCDR (XCDR (this_entry));
 
+       if (!strchr (SDATA (x_charset), '-'))
+         continue;
+
         /* Look for Same charset and a valid codepage (or non-int
            which means ignore).  */
         if (EQ (w32_charset, charset_type)
@@ -5253,6 +5461,8 @@ w32_to_all_x_charsets (fncharset)
   }
 }
 
+#if OLD_FONT
+
 /* Get the Windows codepage corresponding to the specified font.  The
    charset info in the font name is used to look up
    w32-charset-to-codepage-alist.  */
@@ -5262,9 +5472,6 @@ w32_codepage_for_font (char *fontname)
   Lisp_Object codepage, entry;
   char *charset_str, *charset, *end;
 
-  if (NILP (Vw32_charset_info_alist))
-    return CP_DEFAULT;
-
   /* Extract charset part of font string.  */
   charset = xlfd_charset_of_font (fontname);
 
@@ -5290,7 +5497,13 @@ w32_codepage_for_font (char *fontname)
         *end = '\0';
       }
 
-  entry = Fassoc (build_string (charset), Vw32_charset_info_alist);
+  if (!strcmp (charset, "iso10646"))
+    return CP_UNICODE;
+
+  if (NILP (Vw32_charset_info_alist))
+    return CP_DEFAULT;
+
+  entry = Fassoc (build_string(charset), Vw32_charset_info_alist);
   if (NILP (entry))
     return CP_UNKNOWN;
 
@@ -5305,7 +5518,7 @@ w32_codepage_for_font (char *fontname)
   else
     return CP_UNKNOWN;
 }
-
+#endif /* OLD_FONT */
 
 static BOOL
 w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
@@ -5322,7 +5535,6 @@ w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
   char *fontname_dash;
   int display_resy = (int) one_w32_display_info.resy;
   int display_resx = (int) one_w32_display_info.resx;
-  int bufsz;
   struct coding_system coding;
 
   if (!lpxstr) abort ();
@@ -5344,12 +5556,14 @@ w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
   coding.mode |= CODING_MODE_LAST_BLOCK;
   /* We explicitely disable composition handling because selection
      data should not contain any composition sequence.  */
-  coding.composing = COMPOSITION_DISABLED;
-  bufsz = decoding_buffer_size (&coding, LF_FACESIZE);
+  coding.common_flags &= ~CODING_ANNOTATION_MASK;
+
+  coding.dst_bytes = LF_FACESIZE * 2;
+  coding.destination = (unsigned char *) xmalloc (coding.dst_bytes + 1);
+  decode_coding_c_string (&coding, lplogfont->lfFaceName,
+                         strlen(lplogfont->lfFaceName), Qnil);
+  fontname = coding.destination;
 
-  fontname = alloca (sizeof (*fontname) * bufsz);
-  decode_coding (&coding, lplogfont->lfFaceName, fontname,
-                 strlen (lplogfont->lfFaceName), bufsz - 1);
   *(fontname + coding.produced) = '\0';
 
   /* Replace dashes with underscores so the dashes are not
@@ -5370,7 +5584,7 @@ w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
       strcpy (height_dpi, "*");
     }
 
-#if 0 /* Never put the width in the xfld. It fails on fonts with
+#if 0 /* Never put the width in the xlfd. It fails on fonts with
         double-width characters.  */
   if (lplogfont->lfWidth)
     sprintf (width_pixels, "%u", lplogfont->lfWidth * 10);
@@ -5393,8 +5607,7 @@ w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
             ((lplogfont->lfPitchAndFamily & 0x3) == VARIABLE_PITCH)
              ? 'p' : 'c',                            /* spacing */
             width_pixels,                           /* avg width */
-            specific_charset ? specific_charset
-             : w32_to_x_charset (lplogfont->lfCharSet)
+             w32_to_x_charset (lplogfont->lfCharSet, specific_charset)
              /* charset registry and encoding */
             );
 
@@ -5472,26 +5685,24 @@ x_to_w32_font (lpxstr, lplogfont)
 
       if (fields > 0 && name[0] != '*')
         {
-         int bufsize;
-         unsigned char *buf;
-
+         Lisp_Object string = build_string (name);
           setup_coding_system
             (Fcheck_coding_system (Vlocale_coding_system), &coding);
-         coding.src_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;
-         if (coding.type == coding_type_iso2022)
-           coding.flags |= CODING_FLAG_ISO_SAFE;
-         bufsize = encoding_buffer_size (&coding, strlen (name));
-         buf = (unsigned char *) alloca (bufsize);
-          coding.mode |= CODING_MODE_LAST_BLOCK;
-          encode_coding (&coding, name, buf, strlen (name), bufsize);
+          coding.mode |= (CODING_MODE_SAFE_ENCODING | CODING_MODE_LAST_BLOCK);
+         /* Disable composition/charset annotation.   */
+         coding.common_flags &= ~CODING_ANNOTATION_MASK;
+         coding.dst_bytes = SCHARS (string) * 2;
+
+         coding.destination = (unsigned char *) xmalloc (coding.dst_bytes);
+          encode_coding_object (&coding, string, 0, 0,
+                               SCHARS (string), SBYTES (string), Qnil);
          if (coding.produced >= LF_FACESIZE)
            coding.produced = LF_FACESIZE - 1;
-         buf[coding.produced] = 0;
-         strcpy (lplogfont->lfFaceName, buf);
+
+         coding.destination[coding.produced] = '\0';
+
+         strcpy (lplogfont->lfFaceName, coding.destination);
+         xfree (coding.destination);
        }
       else
         {
@@ -5523,8 +5734,12 @@ x_to_w32_font (lpxstr, lplogfont)
        lplogfont->lfHeight = atoi (height) * dpi / 720;
 
       if (fields > 0)
-      lplogfont->lfPitchAndFamily =
-       (fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
+        {
+          if (pitch == 'p')
+            lplogfont->lfPitchAndFamily = VARIABLE_PITCH | FF_DONTCARE;
+          else if (pitch == 'c')
+            lplogfont->lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
+        }
 
       fields--;
 
@@ -5589,6 +5804,8 @@ x_to_w32_font (lpxstr, lplogfont)
   return (TRUE);
 }
 
+#if OLD_FONT
+
 /* Strip the pixel height and point height from the given xlfd, and
    return the pixel height. If no pixel height is specified, calculate
    one from the point height, or if that isn't defined either, return
@@ -5869,14 +6086,23 @@ enum_font_cb2 (lplf, lptm, FontType, lpef)
        if (charset
            && strncmp (charset, "*-*", 3) != 0
            && lpef->logfont.lfCharSet == DEFAULT_CHARSET
-           && strcmp (charset, w32_to_x_charset (DEFAULT_CHARSET)) != 0)
+           && strcmp (charset, w32_to_x_charset (DEFAULT_CHARSET, NULL)) != 0)
          return 1;
+
+        /* Reject raster fonts if we are looking for a unicode font.  */
+        if (charset
+            && FontType == RASTER_FONTTYPE
+            && strncmp (charset, "iso10646", 8) == 0)
+          return 1;
       }
 
     if (charset)
       charset_list = Fcons (build_string (charset), Qnil);
     else
-      charset_list = w32_to_all_x_charsets (lplf->elfLogFont.lfCharSet);
+      /* Always prefer unicode.  */
+      charset_list
+       = Fcons (build_string ("iso10646-1"),
+                w32_to_all_x_charsets (lplf->elfLogFont.lfCharSet));
 
     /* Loop through the charsets.  */
     for ( ; CONSP (charset_list); charset_list = Fcdr (charset_list))
@@ -5884,14 +6110,21 @@ enum_font_cb2 (lplf, lptm, FontType, lpef)
        Lisp_Object this_charset = Fcar (charset_list);
        charset = SDATA (this_charset);
 
+       /* Don't list  raster fonts as unicode.  */
+       if (charset
+           && FontType == RASTER_FONTTYPE
+           && strncmp (charset, "iso10646", 8) == 0)
+         continue;
+
+       enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
+                                    charset, width);
+
        /* List bold and italic variations if w32-enable-synthesized-fonts
           is non-nil and this is a plain font.  */
        if (w32_enable_synthesized_fonts
            && lplf->elfLogFont.lfWeight == FW_NORMAL
            && lplf->elfLogFont.lfItalic == FALSE)
          {
-           enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
-                                        charset, width);
            /* bold.  */
            lplf->elfLogFont.lfWeight = FW_BOLD;
            enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
@@ -5905,9 +6138,6 @@ enum_font_cb2 (lplf, lptm, FontType, lpef)
            enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
                                         charset, width);
          }
-       else
-         enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
-                                      charset, width);
       }
   }
 
@@ -6172,7 +6402,7 @@ w32_list_fonts (f, pattern, size, maxnames)
               hdc = GetDC (dpyinfo->root_window);
               oldobj = SelectObject (hdc, thisinfo.hfont);
               if (GetTextMetrics (hdc, &thisinfo.tm))
-                XSETCDR (tem, make_number (FONT_WIDTH (&thisinfo)));
+                XSETCDR (tem, make_number (FONT_AVG_WIDTH (&thisinfo)));
               else
                 XSETCDR (tem, make_number (0));
               SelectObject (hdc, oldobj);
@@ -6253,7 +6483,7 @@ w32_query_font (struct frame *f, char *fontname)
 
   for (i = 0; i < one_w32_display_info.n_fonts ;i++, pfi++)
     {
-      if (stricmp (pfi->name, fontname) == 0) return pfi;
+      if (xstrcasecmp (pfi->name, fontname) == 0) return pfi;
     }
 
   return NULL;
@@ -6289,10 +6519,14 @@ w32_find_ccl_program (fontp)
     }
 }
 
+#endif /* OLD_FONT */
+
 /* directory-files from dired.c.  */
 Lisp_Object Fdirectory_files P_ ((Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object));
 
 \f
+#if OLD_FONT
+
 /* Find BDF files in a specified directory.  (use GCPRO when calling,
    as this calls lisp to get a directory listing).  */
 static Lisp_Object
@@ -6343,6 +6577,7 @@ in the list.  DIRECTORY may be a list of directories.  */)
     }
   return list;
 }
+#endif /* OLD_FONT */
 
 \f
 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
@@ -6813,6 +7048,7 @@ If DISPLAY is nil, that stands for the selected frame's display.  */)
     error ("Display still has frames on it");
 
   BLOCK_INPUT;
+#if OLD_FONT
   /* Free the fonts in the font table.  */
   for (i = 0; i < dpyinfo->n_fonts; i++)
     if (dpyinfo->font_table[i].name)
@@ -6822,6 +7058,7 @@ If DISPLAY is nil, that stands for the selected frame's display.  */)
         xfree (dpyinfo->font_table[i].name);
         w32_unload_font (dpyinfo, dpyinfo->font_table[i].font);
       }
+#endif
   x_destroy_all_bitmaps (dpyinfo);
 
   x_delete_display (dpyinfo);
@@ -6987,11 +7224,6 @@ value.  */)
                                Busy cursor
  ***********************************************************************/
 
-/* If non-null, an asynchronous timer that, when it expires, displays
-   an hourglass cursor on all frames.  */
-
-static struct atimer *hourglass_atimer;
-
 /* Non-zero means an hourglass cursor is currently shown.  */
 
 static int hourglass_shown_p;
@@ -7005,20 +7237,26 @@ static Lisp_Object Vhourglass_delay;
 
 #define DEFAULT_HOURGLASS_DELAY 1
 
-/* Function prototypes.  */
-
-static void show_hourglass P_ ((struct atimer *));
-static void hide_hourglass P_ ((void));
+/* Return non-zero if houglass timer has been started or hourglass is shown.  */
 
+int
+hourglass_started ()
+{
+  return hourglass_shown_p || hourglass_timer;
+}
 
 /* Cancel a currently active hourglass timer, and start a new one.  */
 
 void
 start_hourglass ()
 {
-#if 0 /* TODO: cursor shape changes.  */
-  EMACS_TIME delay;
-  int secs, usecs = 0;
+  DWORD delay;
+  int secs, msecs = 0;
+  struct frame * f = SELECTED_FRAME ();
+
+  /* No cursors on non GUI frames.  */
+  if (!FRAME_W32_P (f))
+    return;
 
   cancel_hourglass ();
 
@@ -7031,15 +7269,14 @@ start_hourglass ()
       Lisp_Object tem;
       tem = Ftruncate (Vhourglass_delay, Qnil);
       secs = XFASTINT (tem);
-      usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
+      msecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000;
     }
   else
     secs = DEFAULT_HOURGLASS_DELAY;
 
-  EMACS_SET_SECS_USECS (delay, secs, usecs);
-  hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
-                                  show_hourglass, NULL);
-#endif
+  delay = secs * 1000 + msecs;
+  hourglass_hwnd = FRAME_W32_WINDOW (f);
+  hourglass_timer = SetTimer (hourglass_hwnd, HOURGLASS_ID, delay, NULL);
 }
 
 
@@ -7049,10 +7286,10 @@ start_hourglass ()
 void
 cancel_hourglass ()
 {
-  if (hourglass_atimer)
+  if (hourglass_timer)
     {
-      cancel_atimer (hourglass_atimer);
-      hourglass_atimer = NULL;
+      KillTimer (hourglass_hwnd, hourglass_timer);
+      hourglass_timer = 0;
     }
 
   if (hourglass_shown_p)
@@ -7060,62 +7297,22 @@ cancel_hourglass ()
 }
 
 
-/* Timer function of hourglass_atimer.  TIMER is equal to
-   hourglass_atimer.
+/* Timer function of hourglass_timer.
 
-   Display an hourglass cursor on all frames by mapping the frames'
-   hourglass_window.  Set the hourglass_p flag in the frames'
-   output_data.x structure to indicate that an hourglass cursor is
-   shown on the frames.  */
+   Display an hourglass cursor.  Set the hourglass_p flag in display info
+   to indicate that an hourglass cursor is shown.  */
 
 static void
-show_hourglass (timer)
-     struct atimer *timer;
+show_hourglass (f)
+     struct frame *f;
 {
-#if 0  /* TODO: cursor shape changes.  */
-  /* The timer implementation will cancel this timer automatically
-     after this function has run.  Set hourglass_atimer to null
-     so that we know the timer doesn't have to be canceled.  */
-  hourglass_atimer = NULL;
-
   if (!hourglass_shown_p)
     {
-      Lisp_Object rest, frame;
-
-      BLOCK_INPUT;
-
-      FOR_EACH_FRAME (rest, frame)
-       if (FRAME_W32_P (XFRAME (frame)))
-         {
-           struct frame *f = XFRAME (frame);
-
-           f->output_data.w32->hourglass_p = 1;
-
-           if (!f->output_data.w32->hourglass_window)
-             {
-               unsigned long mask = CWCursor;
-               XSetWindowAttributes attrs;
-
-               attrs.cursor = f->output_data.w32->hourglass_cursor;
-
-               f->output_data.w32->hourglass_window
-                 = XCreateWindow (FRAME_X_DISPLAY (f),
-                                  FRAME_OUTER_WINDOW (f),
-                                  0, 0, 32000, 32000, 0, 0,
-                                  InputOnly,
-                                  CopyFromParent,
-                                  mask, &attrs);
-             }
-
-           XMapRaised (FRAME_X_DISPLAY (f),
-                       f->output_data.w32->hourglass_window);
-           XFlush (FRAME_X_DISPLAY (f));
-         }
-
+      f->output_data.w32->hourglass_p = 1;
+      if (!menubar_in_use && !current_popup_menu)
+       SetCursor (f->output_data.w32->hourglass_cursor);
       hourglass_shown_p = 1;
-      UNBLOCK_INPUT;
     }
-#endif
 }
 
 
@@ -7124,33 +7321,15 @@ show_hourglass (timer)
 static void
 hide_hourglass ()
 {
-#if 0 /* TODO: cursor shape changes.  */
   if (hourglass_shown_p)
     {
-      Lisp_Object rest, frame;
-
-      BLOCK_INPUT;
-      FOR_EACH_FRAME (rest, frame)
-       {
-         struct frame *f = XFRAME (frame);
-
-         if (FRAME_W32_P (f)
-             /* Watch out for newly created frames.  */
-             && f->output_data.x->hourglass_window)
-           {
-             XUnmapWindow (FRAME_X_DISPLAY (f),
-                           f->output_data.x->hourglass_window);
-             /* Sync here because XTread_socket looks at the
-                hourglass_p flag that is reset to zero below.  */
-             XSync (FRAME_X_DISPLAY (f), False);
-             f->output_data.x->hourglass_p = 0;
-           }
-       }
+      struct frame *f = x_window_to_frame (&one_w32_display_info,
+                                          hourglass_hwnd);
 
+      f->output_data.w32->hourglass_p = 0;
+      SetCursor (f->output_data.w32->current_cursor);
       hourglass_shown_p = 0;
-      UNBLOCK_INPUT;
     }
-#endif
 }
 
 
@@ -7283,7 +7462,7 @@ x_create_tip_frame (dpyinfo, parms, text)
   f->icon_name = Qnil;
 
 #if 0 /* GLYPH_DEBUG TODO: image support.  */
-  image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
+  image_cache_refcount = FRAME_IMAGE_CACHE (f)->refcount;
   dpyinfo_refcount = dpyinfo->reference_count;
 #endif /* GLYPH_DEBUG */
 #ifdef MULTI_KBOARD
@@ -7307,39 +7486,19 @@ x_create_tip_frame (dpyinfo, parms, text)
       specbind (Qx_resource_name, name);
     }
 
-  /* Extract the window parameters from the supplied values
-     that are needed to determine window geometry.  */
-  {
-    Lisp_Object font;
+  f->resx = dpyinfo->resx;
+  f->resy = dpyinfo->resy;
 
-    font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
+  /* Perhaps, we must allow frame parameter, say `font-backend',
+     to specify which font backends to use.  */
+  register_font_driver (&w32font_driver, f);
 
-    BLOCK_INPUT;
-    /* First, try whatever font the caller has specified.  */
-    if (STRINGP (font))
-      {
-       tem = Fquery_fontset (font, Qnil);
-       if (STRINGP (tem))
-         font = x_new_fontset (f, SDATA (tem));
-       else
-         font = x_new_font (f, SDATA (font));
-      }
-
-    /* Try out a font which we hope has bold and italic variations.  */
-    if (!STRINGP (font))
-      font = x_new_font (f, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
-    if (! STRINGP (font))
-      font = x_new_font (f, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
-    /* If those didn't work, look for something which will at least work.  */
-    if (! STRINGP (font))
-      font = x_new_font (f, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
-    UNBLOCK_INPUT;
-    if (! STRINGP (font))
-      font = build_string ("Fixedsys");
+  x_default_parameter (f, parms, Qfont_backend, Qnil,
+                      "fontBackend", "FontBackend", RES_TYPE_STRING);
 
-    x_default_parameter (f, parms, Qfont, font,
-                        "font", "Font", RES_TYPE_STRING);
-  }
+  /* Extract the window parameters from the supplied values
+     that are needed to determine window geometry.  */
+  x_default_font_parameter (f, parms);
 
   x_default_parameter (f, parms, Qborder_width, make_number (2),
                       "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
@@ -7476,6 +7635,7 @@ compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
      int *root_x, *root_y;
 {
   Lisp_Object left, top;
+  int min_x, min_y, max_x, max_y;
 
   /* User-specified position?  */
   left = Fcdr (Fassq (Qleft, parms));
@@ -7487,40 +7647,68 @@ compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
     {
       POINT pt;
 
+      /* Default min and max values.  */
+      min_x = 0;
+      min_y = 0;
+      max_x = FRAME_W32_DISPLAY_INFO (f)->width;
+      max_y = FRAME_W32_DISPLAY_INFO (f)->height;
+
       BLOCK_INPUT;
       GetCursorPos (&pt);
       *root_x = pt.x;
       *root_y = pt.y;
       UNBLOCK_INPUT;
+
+      /* If multiple monitor support is available, constrain the tip onto
+        the current monitor. This improves the above by allowing negative
+        co-ordinates if monitor positions are such that they are valid, and
+        snaps a tooltip onto a single monitor if we are close to the edge
+        where it would otherwise flow onto the other monitor (or into
+        nothingness if there is a gap in the overlap).  */
+      if (monitor_from_point_fn && get_monitor_info_fn)
+       {
+         struct MONITOR_INFO info;
+         HMONITOR monitor
+           = monitor_from_point_fn (pt, MONITOR_DEFAULT_TO_NEAREST);
+         info.cbSize = sizeof (info);
+
+         if (get_monitor_info_fn (monitor, &info))
+           {
+             min_x = info.rcWork.left;
+             min_y = info.rcWork.top;
+             max_x = info.rcWork.right;
+             max_y = info.rcWork.bottom;
+           }
+       }
     }
 
   if (INTEGERP (top))
     *root_y = XINT (top);
-  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)
+  else if (*root_y + XINT (dy) <= min_y)
+    *root_y = min_y; /* Can happen for negative dy */
+  else if (*root_y + XINT (dy) + height <= max_y)
     /* It fits below the pointer */
       *root_y += XINT (dy);
-  else if (height + XINT (dy) <= *root_y)
+  else if (height + XINT (dy) + min_y <= *root_y)
     /* It fits above the pointer.  */
     *root_y -= height + XINT (dy);
   else
     /* Put it on the top.  */
-    *root_y = 0;
+    *root_y = min_y;
 
   if (INTEGERP (left))
     *root_x = XINT (left);
-  else if (*root_x + XINT (dx) <= 0)
+  else if (*root_x + XINT (dx) <= min_x)
     *root_x = 0; /* Can happen for negative dx */
-  else if (*root_x + XINT (dx) + width <= FRAME_W32_DISPLAY_INFO (f)->width)
+  else if (*root_x + XINT (dx) + width <= max_x)
     /* It fits to the right of the pointer.  */
     *root_x += XINT (dx);
-  else if (width + XINT (dx) <= *root_x)
+  else if (width + XINT (dx) + min_x <= *root_x)
     /* It fits to the left of the pointer.  */
     *root_x -= width + XINT (dx);
   else
     /* Put it left justified on the screen -- it ought to fit that way.  */
-    *root_x = 0;
+    *root_x = min_x;
 }
 
 
@@ -8042,7 +8230,7 @@ in the font selection dialog. */)
   /* Initialize as much of the font details as we can from the current
      default font.  */
   hdc = GetDC (FRAME_W32_WINDOW (f));
-  oldobj = SelectObject (hdc, FRAME_FONT (f)->hfont);
+  oldobj = SelectObject (hdc, FONT_COMPAT (FRAME_FONT (f))->hfont);
   GetTextFace (hdc, LF_FACESIZE, lf.lfFaceName);
   if (GetTextMetrics (hdc, &tm))
     {
@@ -8133,9 +8321,12 @@ an integer representing a ShowWindow flag:
 
   CHECK_STRING (document);
 
-  /* Encode filename and current directory.  */
+  /* Encode filename, current directory and parameters.  */
   current_dir = ENCODE_FILE (current_buffer->directory);
   document = ENCODE_FILE (document);
+  if (STRINGP (parameters))
+    parameters = ENCODE_SYSTEM (parameters);
+
   if ((int) ShellExecute (NULL,
                          (STRINGP (operation) ?
                           SDATA (operation) : NULL),
@@ -8159,7 +8350,7 @@ lookup_vk_code (char *key)
   int i;
 
   for (i = 0; i < 256; i++)
-    if (lispy_function_keys[i] != 0
+    if (lispy_function_keys[i]
        && strcmp (lispy_function_keys[i], key) == 0)
       return i;
 
@@ -8337,7 +8528,7 @@ usage: (w32-reconstruct-hot-key ID)  */)
   vk_code = HOTKEY_VK_CODE (hotkeyid);
   w32_modifiers = HOTKEY_MODIFIERS (hotkeyid);
 
-  if (lispy_function_keys[vk_code])
+  if (vk_code < 256 && lispy_function_keys[vk_code])
     key = intern (lispy_function_keys[vk_code]);
   else
     key = make_number (vk_code);
@@ -8415,6 +8606,115 @@ Lisp_Object class, name;
   return Qt;
 }
 
+DEFUN ("w32-battery-status", Fw32_battery_status, Sw32_battery_status, 0, 0, 0,
+       doc: /* Get power status information from Windows system.
+
+The following %-sequences are provided:
+%L AC line status (verbose)
+%B Battery status (verbose)
+%b Battery status, empty means high, `-' means low,
+   `!' means critical, and `+' means charging
+%p Battery load percentage
+%s Remaining time (to charge or discharge) in seconds
+%m Remaining time (to charge or discharge) in minutes
+%h Remaining time (to charge or discharge) in hours
+%t Remaining time (to charge or discharge) in the form `h:min'  */)
+  ()
+{
+  Lisp_Object status = Qnil;
+
+  SYSTEM_POWER_STATUS system_status;
+  if (GetSystemPowerStatus (&system_status))
+    {
+      Lisp_Object line_status, battery_status, battery_status_symbol;
+      Lisp_Object load_percentage, seconds, minutes, hours, remain;
+      Lisp_Object sequences[8];
+
+      long seconds_left = (long) system_status.BatteryLifeTime;
+
+      if (system_status.ACLineStatus == 0)
+       line_status = build_string ("off-line");
+      else if (system_status.ACLineStatus == 1)
+       line_status = build_string ("on-line");
+      else
+       line_status = build_string ("N/A");
+
+      if (system_status.BatteryFlag & 128)
+       {
+         battery_status = build_string ("N/A");
+         battery_status_symbol = build_string ("");
+       }
+      else if (system_status.BatteryFlag & 8)
+       {
+         battery_status = build_string ("charging");
+         battery_status_symbol = build_string ("+");
+         if (system_status.BatteryFullLifeTime != -1L)
+           seconds_left = system_status.BatteryFullLifeTime - seconds_left;
+       }
+      else if (system_status.BatteryFlag & 4)
+       {
+         battery_status = build_string ("critical");
+         battery_status_symbol = build_string ("!");
+       }
+      else if (system_status.BatteryFlag & 2)
+       {
+         battery_status = build_string ("low");
+         battery_status_symbol = build_string ("-");
+       }
+      else if (system_status.BatteryFlag & 1)
+       {
+         battery_status = build_string ("high");
+         battery_status_symbol = build_string ("");
+       }
+      else
+       {
+         battery_status = build_string ("medium");
+         battery_status_symbol = build_string ("");
+       }
+
+      if (system_status.BatteryLifePercent > 100)
+       load_percentage = build_string ("N/A");
+      else
+       {
+         char buffer[16];
+         _snprintf (buffer, 16, "%d", system_status.BatteryLifePercent);
+         load_percentage = build_string (buffer);
+       }
+
+      if (seconds_left < 0)
+       seconds = minutes = hours = remain = build_string ("N/A");
+      else
+       {
+         long m;
+         float h;
+         char buffer[16];
+         _snprintf (buffer, 16, "%ld", seconds_left);
+         seconds = build_string (buffer);
+
+         m = seconds_left / 60;
+         _snprintf (buffer, 16, "%ld", m);
+         minutes = build_string (buffer);
+
+         h = seconds_left / 3600.0;
+         _snprintf (buffer, 16, "%3.1f", h);
+         hours = build_string (buffer);
+
+         _snprintf (buffer, 16, "%ld:%02ld", m / 60, m % 60);
+         remain = build_string (buffer);
+       }
+      sequences[0] = Fcons (make_number ('L'), line_status);
+      sequences[1] = Fcons (make_number ('B'), battery_status);
+      sequences[2] = Fcons (make_number ('b'), battery_status_symbol);
+      sequences[3] = Fcons (make_number ('p'), load_percentage);
+      sequences[4] = Fcons (make_number ('s'), seconds);
+      sequences[5] = Fcons (make_number ('m'), minutes);
+      sequences[6] = Fcons (make_number ('h'), hours);
+      sequences[7] = Fcons (make_number ('t'), remain);
+
+      status = Flist (8, sequences);
+    }
+  return status;
+}
 
 \f
 DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
@@ -8622,6 +8922,8 @@ frame_parm_handler w32_frame_parm_handlers[] =
   x_set_fringe_width,
   0, /* x_set_wait_for_wm, */
   x_set_fullscreen,
+  x_set_font_backend,
+  0 /* x_set_alpha, */
 };
 
 void
@@ -8634,29 +8936,17 @@ syms_of_w32fns ()
 
   w32_visible_system_caret_hwnd = NULL;
 
-  Qnone = intern ("none");
-  staticpro (&Qnone);
-  Qsuppress_icon = intern ("suppress-icon");
-  staticpro (&Qsuppress_icon);
-  Qundefined_color = intern ("undefined-color");
-  staticpro (&Qundefined_color);
-  Qcancel_timer = intern ("cancel-timer");
-  staticpro (&Qcancel_timer);
-
-  Qhyper = intern ("hyper");
-  staticpro (&Qhyper);
-  Qsuper = intern ("super");
-  staticpro (&Qsuper);
-  Qmeta = intern ("meta");
-  staticpro (&Qmeta);
-  Qalt = intern ("alt");
-  staticpro (&Qalt);
-  Qctrl = intern ("ctrl");
-  staticpro (&Qctrl);
-  Qcontrol = intern ("control");
-  staticpro (&Qcontrol);
-  Qshift = intern ("shift");
-  staticpro (&Qshift);
+  DEFSYM (Qnone, "none");
+  DEFSYM (Qsuppress_icon, "suppress-icon");
+  DEFSYM (Qundefined_color, "undefined-color");
+  DEFSYM (Qcancel_timer, "cancel-timer");
+  DEFSYM (Qhyper, "hyper");
+  DEFSYM (Qsuper, "super");
+  DEFSYM (Qmeta, "meta");
+  DEFSYM (Qalt, "alt");
+  DEFSYM (Qctrl, "ctrl");
+  DEFSYM (Qcontrol, "control");
+  DEFSYM (Qshift, "shift");
   /* This is the end of symbol initialization.  */
 
   /* Text property `display' should be nonsticky by default.  */
@@ -8946,24 +9236,16 @@ CODEPAGE should be an integer specifying the codepage that should be used
 to display the character set, t to do no translation and output as Unicode,
 or nil to do no translation and output as 8 bit (or multibyte on far-east
 versions of Windows) characters.  */);
-    Vw32_charset_info_alist = Qnil;
-
-  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");
-  staticpro (&Qw32_charset_hangeul);
-  Qw32_charset_hangeul = intern ("w32-charset-hangeul");
-  staticpro (&Qw32_charset_chinesebig5);
-  Qw32_charset_chinesebig5 = intern ("w32-charset-chinesebig5");
-  staticpro (&Qw32_charset_gb2312);
-  Qw32_charset_gb2312 = intern ("w32-charset-gb2312");
-  staticpro (&Qw32_charset_oem);
-  Qw32_charset_oem = intern ("w32-charset-oem");
+  Vw32_charset_info_alist = Qnil;
+
+  DEFSYM (Qw32_charset_ansi, "w32-charset-ansi");
+  DEFSYM (Qw32_charset_symbol, "w32-charset-symbol");
+  DEFSYM (Qw32_charset_default, "w32-charset-default");
+  DEFSYM (Qw32_charset_shiftjis, "w32-charset-shiftjis");
+  DEFSYM (Qw32_charset_hangeul, "w32-charset-hangeul");
+  DEFSYM (Qw32_charset_chinesebig5, "w32-charset-chinesebig5");
+  DEFSYM (Qw32_charset_gb2312, "w32-charset-gb2312");
+  DEFSYM (Qw32_charset_oem, "w32-charset-oem");
 
 #ifdef JOHAB_CHARSET
   {
@@ -8971,28 +9253,17 @@ versions of Windows) characters.  */);
     DEFVAR_BOOL ("w32-extra-charsets-defined", &w32_extra_charsets_defined,
                 doc: /* Internal variable.  */);
 
-    staticpro (&Qw32_charset_johab);
-    Qw32_charset_johab = intern ("w32-charset-johab");
-    staticpro (&Qw32_charset_easteurope);
-    Qw32_charset_easteurope = intern ("w32-charset-easteurope");
-    staticpro (&Qw32_charset_turkish);
-    Qw32_charset_turkish = intern ("w32-charset-turkish");
-    staticpro (&Qw32_charset_baltic);
-    Qw32_charset_baltic = intern ("w32-charset-baltic");
-    staticpro (&Qw32_charset_russian);
-    Qw32_charset_russian = intern ("w32-charset-russian");
-    staticpro (&Qw32_charset_arabic);
-    Qw32_charset_arabic = intern ("w32-charset-arabic");
-    staticpro (&Qw32_charset_greek);
-    Qw32_charset_greek = intern ("w32-charset-greek");
-    staticpro (&Qw32_charset_hebrew);
-    Qw32_charset_hebrew = intern ("w32-charset-hebrew");
-    staticpro (&Qw32_charset_vietnamese);
-    Qw32_charset_vietnamese = intern ("w32-charset-vietnamese");
-    staticpro (&Qw32_charset_thai);
-    Qw32_charset_thai = intern ("w32-charset-thai");
-    staticpro (&Qw32_charset_mac);
-    Qw32_charset_mac = intern ("w32-charset-mac");
+    DEFSYM (Qw32_charset_johab, "w32-charset-johab");
+    DEFSYM (Qw32_charset_easteurope, "w32-charset-easteurope");
+    DEFSYM (Qw32_charset_turkish, "w32-charset-turkish");
+    DEFSYM (Qw32_charset_baltic, "w32-charset-baltic");
+    DEFSYM (Qw32_charset_russian, "w32-charset-russian");
+    DEFSYM (Qw32_charset_arabic, "w32-charset-arabic");
+    DEFSYM (Qw32_charset_greek, "w32-charset-greek");
+    DEFSYM (Qw32_charset_hebrew, "w32-charset-hebrew");
+    DEFSYM (Qw32_charset_vietnamese, "w32-charset-vietnamese");
+    DEFSYM (Qw32_charset_thai, "w32-charset-thai");
+    DEFSYM (Qw32_charset_mac, "w32-charset-mac");
   }
 #endif
 
@@ -9002,9 +9273,7 @@ versions of Windows) characters.  */);
     DEFVAR_BOOL ("w32-unicode-charset-defined",
                  &w32_unicode_charset_defined,
                 doc: /* Internal variable.  */);
-
-    staticpro (&Qw32_charset_unicode);
-    Qw32_charset_unicode = intern ("w32-charset-unicode");
+    DEFSYM (Qw32_charset_unicode, "w32-charset-unicode");
   }
 #endif
 
@@ -9051,11 +9320,15 @@ versions of Windows) characters.  */);
   defsubr (&Sw32_reconstruct_hot_key);
   defsubr (&Sw32_toggle_lock_key);
   defsubr (&Sw32_window_exists_p);
+#if OLD_FONT
   defsubr (&Sw32_find_bdf_fonts);
+#endif
+  defsubr (&Sw32_battery_status);
 
   defsubr (&Sfile_system_info);
   defsubr (&Sdefault_printer_name);
 
+#if OLD_FONT
   /* Setting callback functions for fontset handler.  */
   get_font_info_func = w32_get_font_info;
 
@@ -9068,10 +9341,13 @@ versions of Windows) characters.  */);
   find_ccl_program_func = w32_find_ccl_program;
   query_font_func = w32_query_font;
   set_frame_fontset_func = x_set_font;
+  get_font_repertory_func = x_get_font_repertory;
+#endif
   check_window_system_func = check_w32;
 
 
-  hourglass_atimer = NULL;
+  hourglass_timer = 0;
+  hourglass_hwnd = NULL;
   hourglass_shown_p = 0;
   defsubr (&Sx_show_tip);
   defsubr (&Sx_hide_tip);
@@ -9109,6 +9385,18 @@ globals_of_w32fns ()
   clipboard_sequence_fn = (ClipboardSequence_Proc)
     GetProcAddress (user32_lib, "GetClipboardSequenceNumber");
 
+  monitor_from_point_fn = (MonitorFromPoint_Proc)
+    GetProcAddress (user32_lib, "MonitorFromPoint");
+  get_monitor_info_fn = (GetMonitorInfo_Proc)
+    GetProcAddress (user32_lib, "GetMonitorInfoA");
+
+  {
+    HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
+    get_composition_string_fn = (ImmGetCompositionString_Proc)
+      GetProcAddress (imm32_lib, "ImmGetCompositionStringW");
+    get_ime_context_fn = (ImmGetContext_Proc)
+      GetProcAddress (imm32_lib, "ImmGetContext");
+  }
   DEFVAR_INT ("w32-ansi-code-page",
              &w32_ansi_code_page,
              doc: /* The ANSI code page used by the system.  */);
@@ -9116,6 +9404,8 @@ globals_of_w32fns ()
 
   /* MessageBox does not work without this when linked to comctl32.dll 6.0.  */
   InitCommonControls ();
+
+  syms_of_w32uniscribe ();
 }
 
 #undef abort