]> code.delx.au - gnu-emacs/blobdiff - src/w32term.c
*** empty log message ***
[gnu-emacs] / src / w32term.c
index dec34ebfa6e70e75bfa72eeb26b8bf830aea5549..0d6f8c4bf20fc80a1428415aaf1570f1f5022086 100644 (file)
@@ -1,5 +1,5 @@
 /* Implementation of GUI terminal on the Microsoft W32 API.
-   Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
+   Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA.  */
 #include <setjmp.h>
 #include <sys/stat.h>
 
+#include "keyboard.h"
 #include "frame.h"
 #include "dispextern.h"
 #include "fontset.h"
@@ -51,15 +52,16 @@ Boston, MA 02111-1307, USA.  */
 #include "disptab.h"
 #include "buffer.h"
 #include "window.h"
-#include "keyboard.h"
 #include "intervals.h"
 #include "composite.h"
 #include "coding.h"
 
-#undef min
-#undef max
-#define min(x, y) (((x) < (y)) ? (x) : (y))
-#define max(x, y) (((x) > (y)) ? (x) : (y))
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
 
 #define abs(x) ((x) < 0 ? -(x) : (x))
 
@@ -79,14 +81,6 @@ enum bitmap_type
   ZV_LINE_BITMAP
 };
 
-enum w32_char_font_type
-{
-  UNKNOWN_FONT,
-  ANSI_FONT,
-  UNICODE_FONT,
-  BDF_FONT
-};
-
 /* Bitmaps are all unsigned short, as Windows requires bitmap data to
    be Word aligned.  For some reason they are horizontally reflected
    compared to how they appear on X, so changes in xterm.c should be
@@ -153,14 +147,17 @@ static HBITMAP ov_bmp;
 extern Lisp_Object Qhelp_echo;
 
 \f
-/* Non-zero means Emacs uses toolkit scroll bars.  */
+/* Non-nil means Emacs uses toolkit scroll bars.  */
 
-int x_toolkit_scroll_bars_p;
+Lisp_Object Vx_toolkit_scroll_bars;
 
 /* If a string, w32_read_socket generates an event to display that string.
    (The display is done in read_char.)  */
    
 static Lisp_Object help_echo;
+static Lisp_Object help_echo_window;
+static Lisp_Object help_echo_object;
+static int help_echo_pos;
 
 /* Temporary variable for w32_read_socket.  */
 
@@ -185,6 +182,8 @@ extern void w32_menu_display_help (HMENU menu, UINT menu_item, UINT flags);
 
 extern int w32_codepage_for_font (char *fontname);
 
+extern glyph_metric *w32_BDF_TextMetric(bdffont *fontp,
+                                       unsigned char *text, int dim);
 extern Lisp_Object Vwindow_system;
 
 #define x_any_window_to_frame x_window_to_frame
@@ -312,7 +311,9 @@ extern Lisp_Object Vcommand_line_args, Vsystem_name;
 
 extern Lisp_Object Qface, Qmouse_face;
 
+#ifndef USE_CRT_DLL
 extern int errno;
+#endif
 
 /* A mask of extra modifier bits to put into every keyboard char.  */
 
@@ -331,7 +332,7 @@ enum draw_glyphs_face
   DRAW_IMAGE_SUNKEN
 };
 
-static void x_update_window_end P_ ((struct window *, int));
+static void x_update_window_end P_ ((struct window *, int, int));
 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
 void w32_delete_display P_ ((struct w32_display_info *));
 static int fast_find_position P_ ((struct window *, int, int *, int *,
@@ -340,7 +341,6 @@ static void set_output_cursor P_ ((struct cursor_pos *));
 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
                                           int *, int *, int *));
 static void note_mode_line_highlight P_ ((struct window *, int, int));
-static void x_check_font P_ ((struct frame *, XFontStruct *));
 static void note_mouse_highlight P_ ((struct frame *, int, int));
 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
 static void w32_handle_tool_bar_click P_ ((struct frame *,
@@ -381,7 +381,6 @@ static void w32_frame_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct w32_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
-static int w32_intersect_rectangles P_ ((RECT *, RECT *, RECT *));
 static void expose_frame P_ ((struct frame *, int, int, int, int));
 static void expose_window_tree P_ ((struct window *, RECT *));
 static void expose_window P_ ((struct window *, RECT *));
@@ -397,11 +396,11 @@ void x_display_cursor P_ ((struct window *w, int, int, int, int, int));
 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
 static void w32_draw_bitmap P_ ((struct window *, HDC hdc, struct glyph_row *, 
                                  enum bitmap_type));
+static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
+                                 HDC, int));
 static int x_phys_cursor_in_rect_p P_ ((struct window *, RECT *));
 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
-static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
-                               HDC, int));
 
 static Lisp_Object Qvendor_specific_keysyms;
 
@@ -468,13 +467,6 @@ void XGetGCValues (void* ignore, XGCValues *gc,
   XChangeGC (ignore, xgcv, mask, gc);
 }
 
-void XTextExtents16 (XFontStruct *font, wchar_t *text, int nchars,
-                     int *direction,int *font_ascent,
-                     int *font_descent, XCharStruct *cs)
-{
-  /* NTEMACS_TODO: Use GetTextMetrics to do this and inline it below. */
-}
-
 static void
 w32_set_clip_rectangle (HDC hdc, RECT *rect)
 {
@@ -519,7 +511,6 @@ w32_fill_rect (f, hdc, pix, lprect)
      RECT * lprect;
 {
   HBRUSH hb;
-  RECT rect;
 
   hb = CreateSolidBrush (pix);
   FillRect (hdc, lprect, hb);
@@ -533,8 +524,15 @@ w32_clear_window (f)
   RECT rect;
   HDC hdc = get_frame_dc (f);
 
-  GetClientRect (FRAME_W32_WINDOW (f), &rect);
-  w32_clear_rect (f, hdc, &rect);
+  /* Under certain conditions, this can be called at startup with
+     a console frame pointer before the GUI frame is created. An HDC
+     of 0 indicates this. */
+  if (hdc)
+    {
+      GetClientRect (FRAME_W32_WINDOW (f), &rect);
+      w32_clear_rect (f, hdc, &rect);
+    }
+
   release_frame_dc (f, hdc);
 }
 
@@ -546,16 +544,24 @@ w32_clear_window (f)
 /* Start an update of frame F.  This function is installed as a hook
    for update_begin, i.e. it is called when update_begin is called.
    This function is called prior to calls to x_update_window_begin for
-   each window being updated.  Currently, there is nothing to do here
-   because all interesting stuff is done on a window basis.  */
+   each window being updated.  */
 
 static void
 x_update_begin (f)
      struct frame *f;
 {
-  /* Nothing to do.  We have to do something though, otherwise the
-     function gets optimized away and the hook is no longer valid. */
-  struct frame *cf = f;
+  struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
+
+  if (! FRAME_W32_P (f))
+    return;
+
+  /* Regenerate display palette before drawing if list of requested
+     colors has changed. */
+  if (display_info->regen_palette)
+  {
+    w32_regenerate_palette (f);
+    display_info->regen_palette = FALSE;
+  }
 }
 
 
@@ -575,14 +581,6 @@ x_update_window_begin (w)
 
   BLOCK_INPUT;
 
-  /* Regenerate display palette before drawing if list of requested
-     colors has changed. */
-  if (display_info->regen_palette)
-  {
-    w32_regenerate_palette (f);
-    display_info->regen_palette = FALSE;
-  }
-
   if (f == display_info->mouse_face_mouse_frame)
     {
       /* Don't do highlighting for mouse motion during the update.  */
@@ -593,6 +591,13 @@ x_update_window_begin (w)
       if (FRAME_GARBAGED_P (f))
        display_info->mouse_face_window = Qnil;
 
+#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
+        their mouse_face_p flag set, which means that they are always
+        unequal to rows in a desired matrix which never have that
+        flag set.  So, rows containing mouse-face glyphs are never
+        scrolled, and we don't have to switch the mouse highlight off
+        here to prevent it from being scrolled.  */
+      
       /* Can we tell that this update does not affect the window
         where the mouse highlight is?  If so, no need to turn off.
         Likewise, don't do anything if the frame is garbaged;
@@ -610,6 +615,7 @@ x_update_window_begin (w)
          if (i < w->desired_matrix->nrows)
            clear_mouse_face (display_info);
        }
+#endif /* 0 */
     }
 
   UNBLOCK_INPUT;
@@ -641,30 +647,51 @@ x_draw_vertical_border (w)
       r.bottom -= 1;
 
       hdc = get_frame_dc (f);
-      w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), r);
+      w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
       release_frame_dc (f, hdc);
     }
 }
 
    
-/* End update of window W (which is equal to updated_window).  Draw
-   vertical borders between horizontally adjacent windows, and display
-   W's cursor if CURSOR_ON_P is non-zero.  W may be a menu bar
-   pseudo-window in case we don't have X toolkit support.  Such
-   windows don't have a cursor, so don't display it here.  */
+/* End update of window W (which is equal to updated_window).
+
+   Draw vertical borders between horizontally adjacent windows, and
+   display W's cursor if CURSOR_ON_P is non-zero.
+
+   MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
+   glyphs in mouse-face were overwritten.  In that case we have to
+   make sure that the mouse-highlight is properly redrawn.
+
+   W may be a menu bar pseudo-window in case we don't have X toolkit
+   support. Such windows don't have a cursor, so don't display it
+   here. */
 
 static void
-x_update_window_end (w, cursor_on_p)
+x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
      struct window *w;
-     int cursor_on_p;
+     int cursor_on_p, mouse_face_overwritten_p;
 {
   if (!w->pseudo_window_p)
     {
+      struct w32_display_info *dpyinfo
+        = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
+
       BLOCK_INPUT;
+
+      /* If a row with mouse-face was overwritten, arrange for
+        XTframe_up_to_date to redisplay the mouse highlight.  */
+      if (mouse_face_overwritten_p)
+       {
+         dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
+         dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
+         dpyinfo->mouse_face_window = Qnil;
+       }
+
       if (cursor_on_p)
        x_display_and_set_cursor (w, 1, output_cursor.hpos,
                                  output_cursor.vpos,
                                  output_cursor.x, output_cursor.y);
+      
       x_draw_vertical_border (w);
       UNBLOCK_INPUT;
     }
@@ -680,6 +707,9 @@ static void
 x_update_end (f)
      struct frame *f;
 {
+  if (! FRAME_W32_P (f))
+    return;
+
   /* Mouse highlight may be displayed again.  */
   FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
 }
@@ -769,7 +799,6 @@ w32_draw_bitmap (w, hdc, row, which)
   HDC compat_hdc;
   int x, y, wd, h, dy;
   HBITMAP pixmap;
-  HBRUSH fg_brush, orig_brush;
   HANDLE horig_obj;
   struct face *face;
 
@@ -844,19 +873,14 @@ w32_draw_bitmap (w, hdc, row, which)
 
   compat_hdc = CreateCompatibleDC (hdc);
   SaveDC (hdc);
-  fg_brush = CreateSolidBrush (FRAME_FOREGROUND_PIXEL (f));
-  orig_brush = SelectObject (hdc, fg_brush);
+
   horig_obj = SelectObject (compat_hdc, pixmap);
-  SetTextColor (hdc, FRAME_BACKGROUND_PIXEL (f));
-  SetBkColor (hdc, FRAME_FOREGROUND_PIXEL (f));
-#if 0 /* From w32bdf.c (which is from Meadow).  */
+  SetTextColor (hdc, face->background);
+  SetBkColor (hdc, face->foreground);
+
   BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, SRCCOPY);
-#else
-  BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, 0xB8074A);
-#endif
+
   SelectObject (compat_hdc, horig_obj);
-  SelectObject (hdc, orig_brush);
-  DeleteObject (fg_brush);
   DeleteDC (compat_hdc);
   RestoreDC (hdc, -1);
 }
@@ -971,9 +995,20 @@ static void
 w32_reassert_line_highlight (new, vpos)
      int new, vpos;
 {
+  struct frame *f;
+
+  if (updating_frame)
+    f = updating_frame;
+  else
+    f = SELECTED_FRAME ();
+
+  if (! FRAME_W32_P (f))
+    return;
+
   abort ();
 }
 
+
 /* Call this when about to modify line at position VPOS and change
    whether it is highlighted. Not used for W32 frames.  Aborts when
    called.  */
@@ -982,9 +1017,20 @@ static void
 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
      int new_highlight, vpos, y, first_unused_hpos;
 {
+  struct frame *f;
+
+  if (updating_frame)
+    f = updating_frame;
+  else
+    f = SELECTED_FRAME ();
+
+  if (! FRAME_W32_P (f))
+    return;
+
   abort ();
 }
 
+
 /* This is called when starting Emacs and when restarting after
    suspend.  When starting Emacs, no window is mapped.  And nothing
    must be done to Emacs's own window if it is suspended (though that
@@ -1075,7 +1121,7 @@ static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
                                                        int *));
 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
                                                      int, wchar_t *, int));
-static XCharStruct *w32_per_char_metric P_ ((HDC hdc, XFontStruct *,
+static XCharStruct *w32_per_char_metric P_ ((XFontStruct *,
                                              wchar_t *,
                                              enum w32_char_font_type));
 static enum w32_char_font_type
@@ -1100,85 +1146,206 @@ static void x_produce_image_glyph P_ ((struct it *it));
  ((ch) & 0x00ff)
 
 
-/* NTEMACS_TODO: Add support for bdf fonts back in. */
-
 /* Get metrics of character CHAR2B in FONT.  Value is always non-null.
    If CHAR2B is not contained in FONT, the font's default character
    metric is returned. */
 
-static XCharStruct *
-w32_per_char_metric (hdc, font, char2b, font_type)
-     HDC hdc;
+static int
+w32_bdf_per_char_metric (font, char2b, dim, pcm)
      XFontStruct *font;
      wchar_t *char2b;
-     enum w32_char_font_type font_type;
+     int dim;
+     XCharStruct * pcm;
 {
-  /* The result metric information.  */
-  XCharStruct *pcm;
-  ABC char_widths;
-  SIZE sz;
-  BOOL retval;
+  glyph_metric * bdf_metric;
+  char buf[2];
 
-  xassert (font && char2b);
+  if (dim == 1)
+    buf[0] = (char)(*char2b);
+  else
+    {
+      buf[0] = BYTE1 (*char2b);
+      buf[1] = BYTE2 (*char2b);
+    }
+
+  bdf_metric = w32_BDF_TextMetric (font->bdf, buf, dim);
 
-  if (font_type == UNKNOWN_FONT)
+  if (bdf_metric)
     {
-      if (font->bdf)
-        font_type = BDF_FONT;
-      else if (!w32_enable_unicode_output)
-        font_type = ANSI_FONT;
-      else
-        font_type = UNICODE_FONT;  /* NTEMACS_TODO: Need encoding? */
+      pcm->width = bdf_metric->dwidth;
+      pcm->lbearing = bdf_metric->bbox;
+      pcm->rbearing = bdf_metric->dwidth
+                    - (bdf_metric->bbox + bdf_metric->bbw);
+      pcm->ascent = bdf_metric->bboy + bdf_metric->bbh;
+      pcm->descent = -bdf_metric->bboy;
+
+      return 1;
     }
+  return 0;
+}
 
-  pcm = (XCharStruct *) xmalloc (sizeof (XCharStruct));
 
-  if (font->hfont)
-    SelectObject (hdc, font->hfont);
+static int
+w32_native_per_char_metric (font, char2b, font_type, pcm)
+     XFontStruct *font;
+     wchar_t *char2b;
+     enum w32_char_font_type font_type;
+     XCharStruct * pcm;
+{
+  HDC hdc = GetDC (NULL);
+  HFONT old_font;
+  BOOL retval = FALSE;
+
+  xassert (font && char2b);
+  xassert (font->hfont);
+  xassert (font_type == UNICODE_FONT || font_type == ANSI_FONT);
 
-  if (font_type == UNICODE_FONT)
-    retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
-  else if (font_type == ANSI_FONT)
-    retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
+  old_font = SelectObject (hdc, font->hfont);
 
-  if (retval)
+  if ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
     {
-      pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
-      pcm->lbearing = char_widths.abcA;
-      pcm->rbearing = pcm->width - char_widths.abcC;
+      ABC char_widths;
+
+      if (font_type == UNICODE_FONT)
+       retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
+      else
+       retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
+
+      if (retval)
+       {
+         pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
+         pcm->lbearing = char_widths.abcA;
+         pcm->rbearing = pcm->width - char_widths.abcC;
+         pcm->ascent = FONT_BASE (font);
+         pcm->descent = FONT_DESCENT (font);
+       }
     }
-  else
+
+  if (!retval)
     {
-      /* Windows 9x does not implement GetCharABCWidthsW, so if that
-         failed, try GetTextExtentPoint32W, which is implemented and
-         at least gives us some of the info we are after (total
-         character width). */
+      /* Either font is not a True-type font, or GetCharABCWidthsW
+        failed (it is not supported on Windows 9x for instance), so we
+        can't determine the full info we would like.  All is not lost
+        though - we can call GetTextExtentPoint32 to get rbearing and
+        deduce width based on the font's per-string overhang.  lbearing
+        is assumed to be zero.  */
+
+      /* TODO: Some Thai characters (and other composites if Windows
+         supports them) do have lbearing, and report their total width
+         as zero. Need some way of handling them when
+         GetCharABCWidthsW fails. */
+      SIZE sz;
+
       if (font_type == UNICODE_FONT)
-          retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
+       retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
+      else
+       retval = GetTextExtentPoint32A (hdc, (char*)char2b, 1, &sz);
 
       if (retval)
-        {
-          pcm->width = sz.cx;
-          pcm->rbearing = sz.cx;
-          pcm->lbearing = 0;
-        }
-      else
-        {
-          xfree (pcm);
-          return NULL;
-        }
+       {
+         pcm->width = sz.cx - font->tm.tmOverhang;
+         pcm->rbearing = sz.cx;
+         pcm->lbearing = 0;
+         pcm->ascent = FONT_BASE (font);
+         pcm->descent = FONT_DESCENT (font);
+       }
     }
 
-  pcm->ascent = FONT_BASE (font);
-  pcm->descent = FONT_DESCENT (font);
 
   if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
     {
-      xfree (pcm);
-      pcm = NULL;
+      retval = FALSE;
+    }
+
+  SelectObject (hdc, old_font);
+  ReleaseDC (NULL, hdc);
+
+  return retval;
+}
+
+
+static XCharStruct *
+w32_per_char_metric (font, char2b, font_type)
+     XFontStruct *font;
+     wchar_t *char2b;
+     enum w32_char_font_type font_type;
+{
+  /* The result metric information.  */
+  XCharStruct *pcm;
+  BOOL retval;
+
+  xassert (font && char2b);
+  xassert (font_type != UNKNOWN_FONT);
+
+  /* Handle the common cases quickly.  */
+  if (!font->bdf && font->per_char == NULL)
+    /* TODO: determine whether char2b exists in font?  */
+    return &font->max_bounds;
+  else if (!font->bdf && *char2b < 128)
+    return &font->per_char[*char2b];
+
+  pcm = &font->scratch;
+
+  if (font_type == BDF_1D_FONT)
+    retval = w32_bdf_per_char_metric (font, char2b, 1, pcm);
+  else if (font_type == BDF_2D_FONT)
+    retval = w32_bdf_per_char_metric (font, char2b, 2, pcm);
+  else
+    retval = w32_native_per_char_metric (font, char2b, font_type, pcm);
+
+  if (retval)
+    return pcm;
+
+  return NULL;
+}
+
+void
+w32_cache_char_metrics (font)
+     XFontStruct *font;
+{
+  wchar_t char2b = L'x';
+
+  /* Cache char metrics for the common cases.  */
+  if (font->bdf)
+    {
+      /* TODO: determine whether font is fixed-pitch.  */
+      if (!w32_bdf_per_char_metric (font, &char2b, 1, &font->max_bounds))
+        {
+          /* Use the font width and height as max bounds, as not all BDF
+             fonts contain the letter 'x'. */
+          font->max_bounds.width = FONT_MAX_WIDTH (font);
+          font->max_bounds.lbearing = -font->bdf->llx;
+          font->max_bounds.rbearing = FONT_MAX_WIDTH (font) - font->bdf->urx;
+          font->max_bounds.ascent = FONT_BASE (font);
+          font->max_bounds.descent = FONT_DESCENT (font);
+        }
     }
+  else
+    {
+      if (((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH) != 0)
+          /* Some fonts (eg DBCS fonts) are marked as fixed width even
+             though they contain characters of different widths. */
+          || (font->tm.tmMaxCharWidth != font->tm.tmAveCharWidth))
+       {
+         /* Font is not fixed pitch, so cache per_char info for the
+             ASCII characters.  It would be much more work, and probably
+             not worth it, to cache other chars, since we may change
+             between using Unicode and ANSI text drawing functions at
+             run-time.  */
+         int i;
 
-  return pcm;
+         font->per_char = xmalloc (128 * sizeof(XCharStruct));
+         for (i = 0; i < 128; i++)
+           {
+             char2b = i;
+             w32_native_per_char_metric (font, &char2b, ANSI_FONT,
+                                         &font->per_char[i]);
+           }
+       }
+      else
+       w32_native_per_char_metric (font, &char2b, ANSI_FONT,
+                                   &font->max_bounds);
+    }
 }
 
 
@@ -1189,6 +1356,16 @@ int w32_font_is_double_byte (XFontStruct *font)
 }
 
 
+static BOOL 
+w32_use_unicode_for_codepage (codepage)
+     int codepage;
+{
+  /* If the current codepage is supported, use Unicode for output. */
+  return (w32_enable_unicode_output
+          && codepage != CP_8BIT
+          && (codepage == CP_UNICODE || IsValidCodePage (codepage)));
+}
+
 /* Encode CHAR2B using encoding information from FONT_INFO.  CHAR2B is
    the two-byte form of C.  Encoding is returned in *CHAR2B.  */
 
@@ -1205,7 +1382,7 @@ w32_encode_char (c, char2b, font_info, two_byte_p)
 
   XFontStruct *font = font_info->font;
 
-  xassert(two_byte_p);
+  xassert (two_byte_p);
 
   *two_byte_p = w32_font_is_double_byte (font);
 
@@ -1271,17 +1448,22 @@ w32_encode_char (c, char2b, font_info, two_byte_p)
       temp[0] = BYTE1 (*char2b);
       temp[1] = BYTE2 (*char2b);
       temp[2] = '\0';
-      if (temp[0])
-        MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
-      else
-        MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
+      if (codepage != CP_UNICODE)
+        {
+          if (temp[0])
+            MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
+          else
+            MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
+        }
       unicode_p = 1;
       *two_byte_p = 1;
     }
   if (!font)
     return UNKNOWN_FONT;
+  else if (font->bdf && CHARSET_DIMENSION (charset) == 1)
+    return BDF_1D_FONT;
   else if (font->bdf)
-    return BDF_FONT;
+    return BDF_2D_FONT;
   else if (unicode_p)
     return UNICODE_FONT;
   else
@@ -1428,24 +1610,21 @@ x_append_glyph (it)
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
     {
-      /* Play it safe.  If sub-structures of the glyph are not all the
-        same size, it otherwise be that some bits stay set.  This
-        would prevent a comparison with GLYPH_EQUAL_P.  */
-      glyph->u.val = 0;
-      
-      glyph->type = CHAR_GLYPH;
-      glyph->pixel_width = it->pixel_width;
-      glyph->u.ch = it->char_to_display;
-      glyph->face_id = it->face_id;
       glyph->charpos = CHARPOS (it->position);
       glyph->object = it->object;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
+      glyph->pixel_width = it->pixel_width;
       glyph->voffset = it->voffset;
+      glyph->type = CHAR_GLYPH;
       glyph->multibyte_p = it->multibyte_p;
+      glyph->left_box_line_p = it->start_of_box_run_p;
+      glyph->right_box_line_p = it->end_of_box_run_p;
       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
                                      || it->phys_descent > it->descent);
+      glyph->padding_p = 0;
       glyph->glyph_not_available_p = it->glyph_not_available_p;
+      glyph->face_id = it->face_id;
+      glyph->u.ch = it->char_to_display;
+      glyph->w32_font_type = UNKNOWN_FONT;
       ++it->glyph_row->used[area];
     }
 }
@@ -1465,23 +1644,21 @@ x_append_composite_glyph (it)
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
     {
-      /* Play it safe.  If sub-structures of the glyph are not all the
-        same size, it otherwise be that some bits stay set.  This
-        would prevent a comparison with GLYPH_EQUAL_P.  */
-      glyph->u.val = 0;
-      
-      glyph->type = COMPOSITE_GLYPH;
-      glyph->pixel_width = it->pixel_width;
-      glyph->u.cmp_id = it->cmp_id;
-      glyph->face_id = it->face_id;
       glyph->charpos = CHARPOS (it->position);
       glyph->object = it->object;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
+      glyph->pixel_width = it->pixel_width;
       glyph->voffset = it->voffset;
+      glyph->type = COMPOSITE_GLYPH;
       glyph->multibyte_p = it->multibyte_p;
+      glyph->left_box_line_p = it->start_of_box_run_p;
+      glyph->right_box_line_p = it->end_of_box_run_p;
       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
                                      || it->phys_descent > it->descent);
+      glyph->padding_p = 0;
+      glyph->glyph_not_available_p = 0;
+      glyph->face_id = it->face_id;
+      glyph->u.cmp_id = it->cmp_id;
+      glyph->w32_font_type = UNKNOWN_FONT;
       ++it->glyph_row->used[area];
     }
 }
@@ -1530,8 +1707,8 @@ x_produce_image_glyph (it)
   prepare_image_for_display (it->f, img);
 
   it->ascent = it->phys_ascent = image_ascent (img, face);
-  it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
-  it->pixel_width = img->width + 2 * img->margin;
+  it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
+  it->pixel_width = img->width + 2 * img->hmargin;
 
   it->nglyphs = 1;
   
@@ -1556,16 +1733,20 @@ x_produce_image_glyph (it)
       glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
       if (glyph < it->glyph_row->glyphs[area + 1])
        {
-         glyph->type = IMAGE_GLYPH;
-         glyph->u.img_id = img->id;
-         glyph->face_id = it->face_id;
-         glyph->pixel_width = it->pixel_width;
          glyph->charpos = CHARPOS (it->position);
          glyph->object = it->object;
-         glyph->left_box_line_p = it->start_of_box_run_p;
-         glyph->right_box_line_p = it->end_of_box_run_p;
+         glyph->pixel_width = it->pixel_width;
          glyph->voffset = it->voffset;
+         glyph->type = IMAGE_GLYPH;
          glyph->multibyte_p = it->multibyte_p;
+         glyph->left_box_line_p = it->start_of_box_run_p;
+         glyph->right_box_line_p = it->end_of_box_run_p;
+         glyph->overlaps_vertically_p = 0;
+          glyph->padding_p = 0;
+         glyph->glyph_not_available_p = 0;
+         glyph->face_id = it->face_id;
+         glyph->u.img_id = img->id;
+          glyph->w32_font_type = UNKNOWN_FONT;
          ++it->glyph_row->used[area];
        }
     }
@@ -1592,17 +1773,21 @@ x_append_stretch_glyph (it, object, width, height, ascent)
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
     {
-      glyph->type = STRETCH_GLYPH;
-      glyph->u.stretch.ascent = height * ascent;
-      glyph->u.stretch.height = height;
-      glyph->face_id = it->face_id;
-      glyph->pixel_width = width;
       glyph->charpos = CHARPOS (it->position);
       glyph->object = object;
-      glyph->left_box_line_p = it->start_of_box_run_p;
-      glyph->right_box_line_p = it->end_of_box_run_p;
+      glyph->pixel_width = width;
       glyph->voffset = it->voffset;
+      glyph->type = STRETCH_GLYPH;
       glyph->multibyte_p = it->multibyte_p;
+      glyph->left_box_line_p = it->start_of_box_run_p;
+      glyph->right_box_line_p = it->end_of_box_run_p;
+      glyph->overlaps_vertically_p = 0;
+      glyph->padding_p = 0;
+      glyph->glyph_not_available_p = 0;
+      glyph->face_id = it->face_id;
+      glyph->u.stretch.ascent = height * ascent;
+      glyph->u.stretch.height = height;
+      glyph->w32_font_type = UNKNOWN_FONT;
       ++it->glyph_row->used[area];
     }
 }
@@ -1650,7 +1835,10 @@ x_produce_stretch_glyph (it)
      struct it *it;
 {
   /* (space :width WIDTH :height HEIGHT.  */
-  extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
+#if GLYPH_DEBUG
+  extern Lisp_Object Qspace;
+#endif
+  extern Lisp_Object QCwidth, QCheight, QCascent;
   extern Lisp_Object QCrelative_width, QCrelative_height;
   extern Lisp_Object QCalign_to;
   Lisp_Object prop, plist;
@@ -1780,9 +1968,10 @@ x_produce_stretch_glyph (it)
 */
 
 #define VCENTER_BASELINE_OFFSET(FONT, F)                       \
- (FONT_DESCENT (FONT)                                          \
-  + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2       \
-  - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
+  (FONT_DESCENT (FONT)                                         \
+   + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))           \
+      + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2  \
+   - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
 
 /* Produce glyphs/get display metrics for the display element IT is
    loaded with.  See the description of struct display_iterator in
@@ -1803,9 +1992,17 @@ x_produce_glyphs (it)
       int font_not_found_p;
       struct font_info *font_info;
       int boff;                 /* baseline offset */
-      HDC hdc;
-
-      hdc = get_frame_dc (it->f);
+      /* We may change it->multibyte_p upon unibyte<->multibyte
+        conversion.  So, save the current value now and restore it
+        later.
+
+        Note: It seems that we don't have to record multibyte_p in
+        struct glyph because the character code itself tells if or
+        not the character is multibyte.  Thus, in the future, we must
+        consider eliminating the field `multibyte_p' in the struct
+        glyph.
+      */
+      int saved_multibyte_p = it->multibyte_p;
 
       /* Maybe translate single-byte characters to multibyte, or the
          other way.  */
@@ -1818,6 +2015,7 @@ x_produce_glyphs (it)
                   || !NILP (Vnonascii_translation_table)))
             {
               it->char_to_display = unibyte_char_to_multibyte (it->c);
+              it->multibyte_p = 1;
              it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
              face = FACE_FROM_ID (it->f, it->face_id);
            }
@@ -1825,6 +2023,7 @@ x_produce_glyphs (it)
                   && !it->multibyte_p)
            {
              it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
+              it->multibyte_p = 0;
              it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
              face = FACE_FROM_ID (it->f, it->face_id);
            }
@@ -1852,9 +2051,6 @@ x_produce_glyphs (it)
            boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
        }
 
-      if (font->hfont)
-        SelectObject (hdc, font->hfont);
-
       if (it->char_to_display >= ' '
          && (!it->multibyte_p || it->char_to_display < 128))
        {
@@ -1863,8 +2059,8 @@ x_produce_glyphs (it)
 
          it->nglyphs = 1;
 
-          pcm = w32_per_char_metric (hdc, font, &char2b,
-                                     font->bdf ? BDF_FONT : ANSI_FONT);
+          pcm = w32_per_char_metric (font, &char2b,
+                                     font->bdf ? BDF_1D_FONT : ANSI_FONT);
          it->ascent = FONT_BASE (font) + boff;
          it->descent = FONT_DESCENT (font) - boff;
 
@@ -1877,9 +2073,9 @@ x_produce_glyphs (it)
           else
             {
               it->glyph_not_available_p = 1;
-              it->phys_ascent = FONT_BASE(font) + boff;
-              it->phys_descent = FONT_DESCENT(font) - boff;
-              it->pixel_width = FONT_WIDTH(font);
+              it->phys_ascent = FONT_BASE (font) + boff;
+              it->phys_descent = FONT_DESCENT (font) - boff;
+              it->pixel_width = FONT_WIDTH (font);
             }
           
          /* If this is a space inside a region of text with
@@ -1931,8 +2127,6 @@ x_produce_glyphs (it)
                 glyph row.  This is used to optimize X output code.  */
              if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
                it->glyph_row->contains_overlapping_glyphs_p = 1;
-              if (pcm)
-                xfree (pcm);
            }
        }
       else if (it->char_to_display == '\n')
@@ -1956,6 +2150,12 @@ x_produce_glyphs (it)
          int x = it->current_x + it->continuation_lines_width;
          int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
       
+         /* If the distance from the current position to the next tab
+            stop is less than a canonical character width, use the
+            tab stop after that.  */
+         if (next_tab_x - x < CANON_X_UNIT (it->f))
+           next_tab_x += tab_width;
+
          it->pixel_width = next_tab_x - x;
          it->nglyphs = 1;
          it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
@@ -1976,8 +2176,16 @@ x_produce_glyphs (it)
              default font and calculate the width of the character
              from the charset width; this is what old redisplay code
              did.  */
-          pcm = w32_per_char_metric (hdc, font, &char2b,
-                                     font->bdf ? BDF_FONT : UNICODE_FONT);
+          enum w32_char_font_type type;
+
+          if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (it->c)) == 1)
+            type = BDF_1D_FONT;
+          else if (font->bdf)
+            type = BDF_2D_FONT;
+          else
+            type = UNICODE_FONT;
+
+          pcm = w32_per_char_metric (font, &char2b, type);
 
          if (font_not_found_p || !pcm)
            {
@@ -2002,7 +2210,6 @@ x_produce_glyphs (it)
           it->nglyphs = 1;
           it->ascent = FONT_BASE (font) + boff;
           it->descent = FONT_DESCENT (font) - boff;
-
          if (face->box != FACE_NO_BOX)
            {
              int thick = face->box_line_width;
@@ -2024,27 +2231,301 @@ x_produce_glyphs (it)
   
          if (it->glyph_row)
            x_append_glyph (it);
-
-          if (pcm)
-            xfree (pcm);
        }
-      release_frame_dc (it->f, hdc);
+      it->multibyte_p = saved_multibyte_p;
     }
   else if (it->what == IT_COMPOSITION)
     {
-      /* NTEMACS_TODO: Composite glyphs.  */
-    }
-  else if (it->what == IT_IMAGE)
-    x_produce_image_glyph (it);
-  else if (it->what == IT_STRETCH)
-    x_produce_stretch_glyph (it);
+      /* Note: A composition is represented as one glyph in the
+        glyph matrix.  There are no padding glyphs.  */
+      wchar_t char2b;
+      XFontStruct *font;
+      struct face *face = FACE_FROM_ID (it->f, it->face_id);
+      XCharStruct *pcm;
+      int font_not_found_p;
+      struct font_info *font_info;
+      int boff;                        /* baseline offset */
+      struct composition *cmp = composition_table[it->cmp_id];
 
-  /* Accumulate dimensions.  */
-  xassert (it->ascent >= 0 && it->descent > 0);
-  if (it->area == TEXT_AREA)
-    it->current_x += it->pixel_width;
+      /* Maybe translate single-byte characters to multibyte.  */
+      it->char_to_display = it->c;
+      if (unibyte_display_via_language_environment
+         && SINGLE_BYTE_CHAR_P (it->c)
+         && (it->c >= 0240
+             || (it->c >= 0200
+                 && !NILP (Vnonascii_translation_table))))
+       {
+         it->char_to_display = unibyte_char_to_multibyte (it->c);
+       }
 
-  it->descent += it->extra_line_spacing;
+      /* Get face and font to use.  Encode IT->char_to_display.  */
+      it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+      face = FACE_FROM_ID (it->f, it->face_id);
+      x_get_char_face_and_encoding (it->f, it->char_to_display,
+                                   it->face_id, &char2b, it->multibyte_p);
+      font = face->font;
+
+      /* When no suitable font found, use the default font.  */
+      font_not_found_p = font == NULL;
+      if (font_not_found_p)
+       {
+         font = FRAME_FONT (it->f);
+         boff = it->f->output_data.w32->baseline_offset;
+         font_info = NULL;
+       }
+      else
+       {
+         font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+         boff = font_info->baseline_offset;
+         if (font_info->vertical_centering)
+           boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+       }
+
+      /* There are no padding glyphs, so there is only one glyph to
+        produce for the composition.  Important is that pixel_width,
+        ascent and descent are the values of what is drawn by
+        draw_glyphs (i.e. the values of the overall glyphs composed).  */
+      it->nglyphs = 1;
+
+      /* If we have not yet calculated pixel size data of glyphs of
+        the composition for the current face font, calculate them
+        now.  Theoretically, we have to check all fonts for the
+        glyphs, but that requires much time and memory space.  So,
+        here we check only the font of the first glyph.  This leads
+        to incorrect display very rarely, and C-l (recenter) can
+        correct the display anyway.  */
+      if (cmp->font != (void *) font)
+       {
+         /* Ascent and descent of the font of the first character of
+            this composition (adjusted by baseline offset).  Ascent
+            and descent of overall glyphs should not be less than
+            them respectively.  */
+         int font_ascent = FONT_BASE (font) + boff;
+         int font_descent = FONT_DESCENT (font) - boff;
+         /* Bounding box of the overall glyphs.  */
+         int leftmost, rightmost, lowest, highest;
+         int i, width, ascent, descent;
+          enum w32_char_font_type font_type;
+
+         cmp->font = (void *) font;
+
+          if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (it->c)) == 1)
+            font_type = BDF_1D_FONT;
+          else if (font->bdf)
+            font_type = BDF_2D_FONT;
+          else
+            font_type = UNICODE_FONT;
+
+         /* Initialize the bounding box.  */
+         if (font_info
+              && (pcm = w32_per_char_metric (font, &char2b, font_type)))
+           {
+             width = pcm->width;
+             ascent = pcm->ascent;
+             descent = pcm->descent;
+           }
+         else
+           {
+             width = FONT_WIDTH (font);
+             ascent = FONT_BASE (font);
+             descent = FONT_DESCENT (font);
+           }
+         
+         rightmost = width;
+         lowest = - descent + boff;
+         highest = ascent + boff;
+         leftmost = 0;
+         
+         if (font_info
+             && font_info->default_ascent
+             && CHAR_TABLE_P (Vuse_default_ascent)
+             && !NILP (Faref (Vuse_default_ascent,
+                              make_number (it->char_to_display))))
+           highest = font_info->default_ascent + boff;
+
+         /* Draw the first glyph at the normal position.  It may be
+            shifted to right later if some other glyphs are drawn at
+            the left.  */
+         cmp->offsets[0] = 0;
+         cmp->offsets[1] = boff;
+
+         /* Set cmp->offsets for the remaining glyphs.  */
+         for (i = 1; i < cmp->glyph_len; i++)
+           {
+             int left, right, btm, top;
+             int ch = COMPOSITION_GLYPH (cmp, i);
+             int face_id = FACE_FOR_CHAR (it->f, face, ch);
+
+             face = FACE_FROM_ID (it->f, face_id);
+             x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
+                                           it->multibyte_p);
+             font = face->font;
+             if (font == NULL)
+               {
+                 font = FRAME_FONT (it->f);
+                 boff = it->f->output_data.w32->baseline_offset;
+                 font_info = NULL;
+               }
+             else
+               {
+                 font_info
+                   = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+                 boff = font_info->baseline_offset;
+                 if (font_info->vertical_centering)
+                   boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+               }
+
+              if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (ch)) == 1)
+                font_type = BDF_1D_FONT;
+              else if (font->bdf)
+                font_type = BDF_2D_FONT;
+              else
+                font_type = UNICODE_FONT;
+
+             if (font_info
+                  && (pcm = w32_per_char_metric (font, &char2b, font_type)))
+               {
+                 width = pcm->width;
+                 ascent = pcm->ascent;
+                 descent = pcm->descent;
+               }
+             else
+               {
+                 width = FONT_WIDTH (font);
+                 ascent = 1;
+                 descent = 0;
+               }
+
+             if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
+               {
+                 /* Relative composition with or without
+                    alternate chars.  */
+                 left = (leftmost + rightmost - width) / 2;
+                 btm = - descent + boff;
+                 if (font_info && font_info->relative_compose
+                     && (! CHAR_TABLE_P (Vignore_relative_composition)
+                         || NILP (Faref (Vignore_relative_composition,
+                                         make_number (ch)))))
+                   {
+
+                     if (- descent >= font_info->relative_compose)
+                       /* One extra pixel between two glyphs.  */
+                       btm = highest + 1;
+                     else if (ascent <= 0)
+                       /* One extra pixel between two glyphs.  */
+                       btm = lowest - 1 - ascent - descent;
+                   }
+               }
+             else
+               {
+                 /* A composition rule is specified by an integer
+                    value that encodes global and new reference
+                    points (GREF and NREF).  GREF and NREF are
+                    specified by numbers as below:
+
+                       0---1---2 -- ascent
+                       |       |
+                       |       |
+                       |       |
+                       9--10--11 -- center
+                       |       |
+                    ---3---4---5--- baseline
+                       |       |
+                       6---7---8 -- descent
+                 */
+                 int rule = COMPOSITION_RULE (cmp, i);
+                 int gref, nref, grefx, grefy, nrefx, nrefy;
+
+                 COMPOSITION_DECODE_RULE (rule, gref, nref);
+                 grefx = gref % 3, nrefx = nref % 3;
+                 grefy = gref / 3, nrefy = nref / 3;
+
+                 left = (leftmost
+                         + grefx * (rightmost - leftmost) / 2
+                         - nrefx * width / 2);
+                 btm = ((grefy == 0 ? highest
+                         : grefy == 1 ? 0
+                         : grefy == 2 ? lowest
+                         : (highest + lowest) / 2)
+                        - (nrefy == 0 ? ascent + descent
+                           : nrefy == 1 ? descent - boff
+                           : nrefy == 2 ? 0
+                           : (ascent + descent) / 2));
+               }
+
+             cmp->offsets[i * 2] = left;
+             cmp->offsets[i * 2 + 1] = btm + descent;
+
+             /* Update the bounding box of the overall glyphs. */
+             right = left + width;
+             top = btm + descent + ascent;
+             if (left < leftmost)
+               leftmost = left;
+             if (right > rightmost)
+               rightmost = right;
+             if (top > highest)
+               highest = top;
+             if (btm < lowest)
+               lowest = btm;
+           }
+
+         /* If there are glyphs whose x-offsets are negative,
+            shift all glyphs to the right and make all x-offsets
+            non-negative.  */
+         if (leftmost < 0)
+           {
+             for (i = 0; i < cmp->glyph_len; i++)
+               cmp->offsets[i * 2] -= leftmost;
+             rightmost -= leftmost;
+           }
+
+         cmp->pixel_width = rightmost;
+         cmp->ascent = highest;
+         cmp->descent = - lowest;
+         if (cmp->ascent < font_ascent)
+           cmp->ascent = font_ascent;
+         if (cmp->descent < font_descent)
+           cmp->descent = font_descent;
+       }
+
+      it->pixel_width = cmp->pixel_width;
+      it->ascent = it->phys_ascent = cmp->ascent;
+      it->descent = it->phys_descent = cmp->descent;
+
+      if (face->box != FACE_NO_BOX)
+       {
+         int thick = face->box_line_width;
+         it->ascent += thick;
+         it->descent += thick;
+         
+         if (it->start_of_box_run_p)
+           it->pixel_width += thick;
+         if (it->end_of_box_run_p)
+           it->pixel_width += thick;
+       }
+  
+      /* If face has an overline, add the height of the overline
+        (1 pixel) and a 1 pixel margin to the character height.  */
+      if (face->overline_p)
+       it->ascent += 2;
+
+      take_vertical_position_into_account (it);
+  
+      if (it->glyph_row)
+       x_append_composite_glyph (it);
+    }
+  else if (it->what == IT_IMAGE)
+    x_produce_image_glyph (it);
+  else if (it->what == IT_STRETCH)
+    x_produce_stretch_glyph (it);
+
+  /* Accumulate dimensions.  Note: can't assume that it->descent > 0
+     because this isn't true for images with `:ascent 100'.  */
+  xassert (it->ascent >= 0 && it->descent >= 0);
+  if (it->area == TEXT_AREA)
+    it->current_x += it->pixel_width;
+
+  it->descent += it->extra_line_spacing;
 
   it->max_ascent = max (it->max_ascent, it->ascent);
   it->max_descent = max (it->max_descent, it->descent);
@@ -2061,7 +2542,7 @@ x_estimate_mode_line_height (f, face_id)
      struct frame *f;
      enum face_id face_id;
 {
-  int height = 1;
+  int height = FONT_HEIGHT (FRAME_FONT (f));
 
   /* This function is called so early when Emacs starts that the face
      cache and mode line face are not yet initialized.  */
@@ -2069,23 +2550,16 @@ x_estimate_mode_line_height (f, face_id)
       {
        struct face *face = FACE_FROM_ID (f, face_id);
        if (face)
-         height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
+          {
+            if (face->font)
+              height = FONT_HEIGHT (face->font);
+            height += 2 * face->box_line_width;
+          }
       }
   
   return height;
 }
 
-\f
-
-BOOL 
-w32_use_unicode_for_codepage (codepage)
-     int codepage;
-{
-  /* If the current codepage is supported, use Unicode for output. */
-  return (w32_enable_unicode_output
-          && codepage != CP_DEFAULT && IsValidCodePage (codepage));
-}
-
 \f
 /***********************************************************************
                            Glyph display
@@ -2211,7 +2685,7 @@ struct glyph_string
 
 /* Encapsulate the different ways of displaying text under W32.  */
 
-void W32_TEXTOUT(s, x, y,chars,nchars)
+void W32_TEXTOUT (s, x, y,chars,nchars)
      struct glyph_string * s;
      int x, y;
      wchar_t * chars;
@@ -2220,7 +2694,8 @@ void W32_TEXTOUT(s, x, y,chars,nchars)
   int charset_dim = w32_font_is_double_byte (s->gc->font) ? 2 : 1;
   if (s->gc->font->bdf)
     w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
-                     x, y, (char *) chars, charset_dim, nchars, 0);
+                     x, y, (char *) chars, charset_dim,
+                     nchars * charset_dim, 0);
   else if (s->first_glyph->w32_font_type == UNICODE_FONT)
     ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
   else
@@ -2267,13 +2742,13 @@ static int x_left_overwritten P_ ((struct glyph_string *));
 static int x_left_overwriting P_ ((struct glyph_string *));
 static int x_right_overwritten P_ ((struct glyph_string *));
 static int x_right_overwriting P_ ((struct glyph_string *));
-static int x_fill_glyph_string P_ ((struct glyph_string *, int, int,
-                                    int, int));
+static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
+                                    int));
 static void w32_init_glyph_string P_ ((struct glyph_string *, HDC hdc,
-                                     wchar_t *, struct window *,
-                                     struct glyph_row *,
-                                     enum glyph_row_area, int, 
-                                     enum draw_glyphs_face));
+                                       wchar_t *, struct window *,
+                                       struct glyph_row *,
+                                       enum glyph_row_area, int, 
+                                       enum draw_glyphs_face));
 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
                              enum glyph_row_area, int, int,
                              enum draw_glyphs_face, int *, int *, int));
@@ -2310,6 +2785,13 @@ static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
                                 int, int, int, RECT *));
 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
                                        enum glyph_row_area));
+static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
+                                           struct glyph_row *,
+                                           enum glyph_row_area, int, int));
+
+#if GLYPH_DEBUG
+static void x_check_font P_ ((struct frame *, XFontStruct *));
+#endif
 
      
 /* Append the list of glyph strings with head H and tail T to the list
@@ -2428,10 +2910,16 @@ x_set_mouse_face_gc (s)
   int face_id;
   struct face *face;
 
-  /* What face has to be used for the mouse face?  */
+  /* What face has to be used last for the mouse face?  */
   face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
   face = FACE_FROM_ID (s->f, face_id);
-  face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+  if (face == NULL)
+    face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
+  
+  if (s->first_glyph->type == CHAR_GLYPH)
+    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+  else
+    face_id = FACE_FOR_CHAR (s->f, face, 0);
   s->face = FACE_FROM_ID (s->f, face_id);
   PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
 
@@ -2474,7 +2962,6 @@ x_set_mode_line_face_gc (s)
      struct glyph_string *s;
 {     
   s->gc = s->face->gc;
-  xassert (s->gc != 0);
 }
 
 
@@ -2486,6 +2973,8 @@ static INLINE void
 x_set_glyph_string_gc (s)
      struct glyph_string *s;
 {
+  PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
+  
   if (s->hl == DRAW_NORMAL_TEXT)
     {
       s->gc = s->face->gc;
@@ -2614,16 +3103,9 @@ static INLINE void
 x_compute_glyph_string_overhangs (s)
      struct glyph_string *s;
 {
-  if (s->cmp == NULL
-      && s->first_glyph->type == CHAR_GLYPH)
-    {
-      XCharStruct cs;
-      int direction, font_ascent, font_descent;
-      XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
-                     &font_ascent, &font_descent, &cs);
-      s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
-      s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
-    }
+  /* TODO: Windows does not appear to have a method for
+     getting this info without getting the ABC widths for each
+     individual character and working it out manually. */
 }
 
 
@@ -2671,8 +3153,6 @@ w32_get_glyph_overhangs (hdc, glyph, f, left, right)
      struct frame *f;
      int *left, *right;
 {
-  int c;
-
   *left = *right = 0;
   
   if (glyph->type == CHAR_GLYPH)
@@ -2686,14 +3166,13 @@ w32_get_glyph_overhangs (hdc, glyph, f, left, right)
       font = face->font;
 
       if (font
-          && (pcm = w32_per_char_metric (hdc, font, &char2b,
+          && (pcm = w32_per_char_metric (font, &char2b,
                                          glyph->w32_font_type)))
        {
          if (pcm->rbearing > pcm->width)
            *right = pcm->rbearing - pcm->width;
          if (pcm->lbearing < 0)
            *left = -pcm->lbearing;
-          xfree (pcm);
        }
     }
 }
@@ -2865,7 +3344,7 @@ x_draw_glyph_string_background (s, force_p)
      shouldn't be drawn in the first place.  */
   if (!s->background_filled_p)
     {
-#if 0 /* NTEMACS_TODO: stipple */
+#if 0 /* TODO: stipple */
       if (s->stippled_p)
        {
          /* Fill background with a stipple pattern.  */
@@ -2882,6 +3361,7 @@ x_draw_glyph_string_background (s, force_p)
         if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
               || s->font_not_found_p
               || s->extends_to_end_of_line_p
+               || s->font->bdf
               || force_p)
        {
          x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
@@ -2900,6 +3380,7 @@ x_draw_glyph_string_foreground (s)
      struct glyph_string *s;
 {
   int i, x;
+  HFONT old_font;
 
   /* If first glyph of S has a left box line, start drawing the text
      of S to the right of that box line.  */
@@ -2919,7 +3400,7 @@ x_draw_glyph_string_foreground (s)
   SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
 
   if (s->font && s->font->hfont)
-    SelectObject (s->hdc, s->font->hfont);
+    old_font = SelectObject (s->hdc, s->font->hfont);
 
   /* Draw characters of S as rectangles if S's font could not be
      loaded. */
@@ -2950,6 +3431,8 @@ x_draw_glyph_string_foreground (s)
       /* Draw text with TextOut and friends. */
       W32_TEXTOUT (s, x, s->ybase - boff, s->char2b, s->nchars);
     }
+  if (s->font && s->font->hfont)
+    SelectObject (s->hdc, old_font);
 }
 
 /* Draw the foreground of composite glyph string S.  */
@@ -2959,6 +3442,7 @@ x_draw_composite_glyph_string_foreground (s)
      struct glyph_string *s;
 {
   int i, x;
+  HFONT old_font;
 
   /* If first glyph of S has a left box line, start drawing the text
      of S to the right of that box line.  */
@@ -2978,6 +3462,9 @@ x_draw_composite_glyph_string_foreground (s)
   SetBkMode (s->hdc, TRANSPARENT);
   SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
 
+  if (s->font && s->font->hfont)
+    old_font = SelectObject (s->hdc, s->font->hfont);
+
   /* Draw a rectangle for the composition if the font for the very
      first character of the composition could not be loaded.  */
   if (s->font_not_found_p)
@@ -2989,12 +3476,29 @@ x_draw_composite_glyph_string_foreground (s)
   else
     {
       for (i = 0; i < s->nchars; i++, ++s->gidx)
-       W32_TEXTOUT (s, x + s->cmp->offsets[s->gidx * 2],
-                     s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
-                     s->char2b + i, 1);
+          W32_TEXTOUT (s, x + s->cmp->offsets[s->gidx * 2],
+                       s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
+                       s->char2b + i, 1);
     }
+  if (s->font && s->font->hfont)
+    SelectObject (s->hdc, old_font);
 }
 
+
+/* Brightness beyond which a color won't have its highlight brightness
+   boosted.
+
+   Nominally, highlight colors for `3d' faces are calculated by
+   brightening an object's color by a constant scale factor, but this
+   doesn't yield good results for dark colors, so for colors who's
+   brightness is less than this value (on a scale of 0-255) have to
+   use an additional additive factor.
+
+   The value here is set so that the default menu-bar/mode-line color
+   (grey75) will not have its highlights changed at all.  */
+#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
+
+
 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
    or DELTA.  Try a color with RGB values multiplied by FACTOR first.
    If this produces the same color as COLOR, try a color where all RGB
@@ -3010,19 +3514,49 @@ w32_alloc_lighter_color (f, color, factor, delta)
      int delta;
 {
   COLORREF new;
+  long bright;
+
+  /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
+  delta /= 256;
 
   /* Change RGB values by specified FACTOR.  Avoid overflow!  */
   xassert (factor >= 0);
   new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
                     min (0xff, factor * GetGValue (*color)),
                     min (0xff, factor * GetBValue (*color)));
+
+  /* Calculate brightness of COLOR.  */
+  bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
+            + GetBValue (*color)) / 6;
+
+  /* We only boost colors that are darker than
+     HIGHLIGHT_COLOR_DARK_BOOST_LIMIT.  */
+  if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
+    /* Make an additive adjustment to NEW, because it's dark enough so
+       that scaling by FACTOR alone isn't enough.  */
+    {
+      /* How far below the limit this color is (0 - 1, 1 being darker).  */
+      double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
+      /* The additive adjustment.  */
+      int min_delta = delta * dimness * factor / 2;
+      
+      if (factor < 1)
+        new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
+                          max (0, min (0xff, min_delta - GetGValue (*color))),
+                          max (0, min (0xff, min_delta - GetBValue (*color))));
+      else
+        new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
+                          max (0, min (0xff, min_delta + GetGValue (*color))),
+                          max (0, min (0xff, min_delta + GetBValue (*color))));
+    }
+  
   if (new == *color)
     new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
                       max (0, min (0xff, delta + GetGValue (*color))),
                       max (0, min (0xff, delta + GetBValue (*color))));
 
-  /* NTEMACS_TODO: Map to palette and retry with delta if same? */
-  /* NTEMACS_TODO: Free colors (if using palette)? */
+  /* TODO: Map to palette and retry with delta if same? */
+  /* TODO: Free colors (if using palette)? */
 
   if (new == *color)
     return 0;
@@ -3055,7 +3589,7 @@ w32_setup_relief_color (f, relief, factor, delta, default_pixel)
   COLORREF background = di->relief_background;
   struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
 
-  /* NTEMACS_TODO: Free colors (if using palette)? */
+  /* TODO: Free colors (if using palette)? */
 
   /* Allocate new color.  */
   xgcv.foreground = default_pixel;
@@ -3068,7 +3602,7 @@ w32_setup_relief_color (f, relief, factor, delta, default_pixel)
   
   if (relief->gc == 0)
     {
-#if 0 /* NTEMACS_TODO: stipple */
+#if 0 /* TODO: stipple */
       xgcv.stipple = dpyinfo->gray;
       mask |= GCStipple;
 #endif
@@ -3125,9 +3659,9 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   HDC hdc = get_frame_dc (f);
 
   if (raised_p)
-    gc.foreground = PALETTERGB (255, 255, 255);
+    gc.foreground = f->output_data.w32->white_relief.gc->foreground;
   else
-    gc.foreground = PALETTERGB (0, 0, 0);
+    gc.foreground = f->output_data.w32->black_relief.gc->foreground;
 
   w32_set_clip_rectangle (hdc, clip_rect);
 
@@ -3151,9 +3685,10 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   w32_set_clip_rectangle (hdc, NULL);
 
   if (raised_p)
-    gc.foreground = PALETTERGB (0, 0, 0);
+    gc.foreground = f->output_data.w32->black_relief.gc->foreground;
   else
-    gc.foreground = PALETTERGB (255, 255, 255);
+    gc.foreground = f->output_data.w32->white_relief.gc->foreground;
+
 
   w32_set_clip_rectangle (hdc, clip_rect);
   
@@ -3198,24 +3733,24 @@ w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
   
   /* Top.  */
   w32_fill_area (s->f, s->hdc, s->face->box_color,
-                 left_x, top_y, right_x - left_x, width);
+                 left_x, top_y, right_x - left_x + 1, width);
 
   /* Left.  */
   if (left_p)
     {
       w32_fill_area (s->f, s->hdc, s->face->box_color,
-                     left_x, top_y, width, bottom_y - top_y);
+                     left_x, top_y, width, bottom_y - top_y + 1);
     }
   
   /* Bottom.  */
   w32_fill_area (s->f, s->hdc, s->face->box_color,
-                 left_x, bottom_y - width, right_x - left_x, width);
+                 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
   
   /* Right.  */
   if (right_p)
     {
       w32_fill_area (s->f, s->hdc, s->face->box_color,
-                     right_x - width, top_y, width, bottom_y - top_y);
+                     right_x - width + 1, top_y, width, bottom_y - top_y + 1);
     }
 
   w32_set_clip_rectangle (s->hdc, NULL);
@@ -3298,17 +3833,14 @@ x_draw_image_foreground (s)
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  if (s->img->margin)
-    {
-      x += s->img->margin;
-      y += s->img->margin;
-    }
+  x += s->img->hmargin;
+  y += s->img->vmargin;
 
   SaveDC (s->hdc);
 
   if (s->img->pixmap)
     {
-#if 0 /* NTEMACS_TODO: image mask */
+#if 0 /* TODO: image mask */
       if (s->img->mask)
        {
          /* We can't set both a clip mask and use XSetClipRectangles
@@ -3332,7 +3864,7 @@ x_draw_image_foreground (s)
          image_rect.y = y;
          image_rect.width = s->img->width;
          image_rect.height = s->img->height;
-         if (w32_intersect_rectangles (&clip_rect, &image_rect, &r))
+         if (IntersectRect (&r, &clip_rect, &image_rect))
            XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
                       r.x - x, r.y - y, r.width, r.height, r.x, r.y);
        }
@@ -3343,15 +3875,18 @@ x_draw_image_foreground (s)
           HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
           HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
           HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
+          x_set_glyph_string_clipping (s);
 
           SetTextColor (s->hdc, s->gc->foreground);
           SetBkColor (s->hdc, s->gc->background);
 #if 0 /* From w32bdf.c (which is from Meadow).  */
           BitBlt (s->hdc, x, y, s->img->width, s->img->height,
                   compat_hdc, 0, 0, SRCCOPY);
-#else
           BitBlt (s->hdc, x, y, s->img->width, s->img->height,
                   compat_hdc, 0, 0, 0xB8074A);
+#else
+          BitBlt (s->hdc, x, y, s->img->width, s->img->height,
+                  compat_hdc, 0, 0, 0xE20746);
 #endif
           SelectObject (s->hdc, orig_brush);
           DeleteObject (fg_brush);
@@ -3367,6 +3902,7 @@ x_draw_image_foreground (s)
          if (s->hl == DRAW_CURSOR)
             w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width - 1,
                                 s->img->height - 1);
+          w32_set_clip_rectangle (s->hdc, NULL);
        }
     }
   else
@@ -3399,11 +3935,8 @@ x_draw_image_relief (s)
   
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  if (s->img->margin)
-    {
-      x += s->img->margin;
-      y += s->img->margin;
-    }
+  x += s->img->hmargin;
+  y += s->img->vmargin;
   
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
@@ -3450,15 +3983,12 @@ w32_draw_image_foreground_1 (s, pixmap)
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
-  if (s->img->margin)
-    {
-      x += s->img->margin;
-      y += s->img->margin;
-    }
+  x += s->img->hmargin;
+  y += s->img->vmargin;
 
   if (s->img->pixmap)
     {
-#if 0 /* NTEMACS_TODO: image mask */
+#if 0 /* TODO: image mask */
       if (s->img->mask)
        {
          /* We can't set both a clip mask and use XSetClipRectangles
@@ -3493,9 +4023,11 @@ w32_draw_image_foreground_1 (s, pixmap)
 #if 0 /* From w32bdf.c (which is from Meadow).  */
           BitBlt (hdc, x, y, s->img->width, s->img->height,
                   compat_hdc, 0, 0, SRCCOPY);
-#else
           BitBlt (hdc, x, y, s->img->width, s->img->height,
                   compat_hdc, 0, 0, 0xB8074A);
+#else
+          BitBlt (hdc, x, y, s->img->width, s->img->height,
+                  compat_hdc, 0, 0, 0xE20746);
 #endif
           SelectObject (hdc, orig_brush);
           DeleteObject (fg_brush);
@@ -3530,7 +4062,7 @@ x_draw_glyph_string_bg_rect (s, x, y, w, h)
      struct glyph_string *s;
      int x, y, w, h;
 {
-#if 0 /* NTEMACS_TODO: stipple */
+#if 0 /* TODO: stipple */
   if (s->stippled_p)
     {
       /* Fill background with a stipple pattern.  */
@@ -3551,7 +4083,7 @@ x_draw_glyph_string_bg_rect (s, x, y, w, h)
             |   s->face->box
             |
             |     +-------------------------
-            |     |  s->img->margin
+            |     |  s->img->vmargin
             |     |
             |     |       +-------------------
             |     |       |  the image
@@ -3564,7 +4096,6 @@ x_draw_image_glyph_string (s)
 {
   int x, y;
   int box_line_width = s->face->box_line_width;
-  int margin = s->img->margin;
   int height;
   HBITMAP pixmap = 0;
 
@@ -3575,8 +4106,9 @@ x_draw_image_glyph_string (s)
      flickering.  */
   s->stippled_p = s->face->stipple != 0;
   if (height > s->img->height
-      || margin
-#if 0 /* NTEMACS_TODO: image mask */
+      || s->img->hmargin
+      || s->img->vmargin
+#if 0 /* TODO: image mask */
       || s->img->mask
 #endif
       || s->img->pixmap == 0
@@ -3588,12 +4120,12 @@ x_draw_image_glyph_string (s)
        x = s->x;
       
       y = s->y + box_line_width;
-#if 0 /* NTEMACS_TODO: image mask */
+#if 0 /* TODO: image mask */
       if (s->img->mask)
        {
-         /* Create a pixmap as large as the glyph string Fill it with
-            the background color.  Copy the image to it, using its
-            mask.  Copy the temporary pixmap to the display.  */
+         /* Create a pixmap as large as the glyph string.  Fill it
+            with the background color.  Copy the image to it, using
+            its mask.  Copy the temporary pixmap to the display.  */
          Screen *screen = FRAME_X_SCREEN (s->f);
          int depth = DefaultDepthOfScreen (screen);
 
@@ -3628,10 +4160,6 @@ x_draw_image_glyph_string (s)
        }
       else
 #endif
-       /* Implementation idea: Is it possible to construct a mask?
-          We could look at the color at the margins of the image, and
-          say that this color is probably the background color of the
-          image.  */
        x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
       
       s->background_filled_p = 1;
@@ -3653,9 +4181,11 @@ x_draw_image_glyph_string (s)
 #if 0 /* From w32bdf.c (which is from Meadow).  */
         BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
                 compat_hdc, 0, 0, SRCCOPY);
-#else
         BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
                 compat_hdc, 0, 0, 0xB8074A);
+#else
+        BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
+                compat_hdc, 0, 0, 0xE20746);
 #endif
         SelectObject (s->hdc, orig_brush);
         DeleteObject (fg_brush);
@@ -3706,7 +4236,7 @@ x_draw_stretch_glyph_string (s)
          w32_get_glyph_string_clip_rect (s, &r);
          w32_set_clip_rectangle (hdc, &r);
 
-#if 0 /* NTEMACS_TODO: stipple */
+#if 0 /* TODO: stipple */
          if (s->face->stipple)
            {
              /* Fill background with a stipple pattern.  */
@@ -3851,11 +4381,12 @@ static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
                                              struct face **, int));
 
 
-/* Load glyph string S with a composition components specified by S->cmp.
+/* Fill glyph string S with composition components specified by S->cmp.
+   
    FACES is an array of faces for all components of this composition.
    S->gidx is the index of the first component for S.
    OVERLAPS_P non-zero means S should draw the foreground only, and
-   use its lines physical height for clipping.
+   use its physical height for clipping.
 
    Value is the index of a component not in S.  */
 
@@ -3909,11 +4440,12 @@ x_fill_composite_glyph_string (s, faces, overlaps_p)
 }
 
 
-/* Load glyph string S with a sequence of characters.
+/* Fill glyph string S from a sequence of character glyphs.
+   
    FACE_ID is the face id of the string.  START is the index of the
    first glyph to consider, END is the index of the last + 1.
    OVERLAPS_P non-zero means S should draw the foreground only, and
-   use its lines physical height for clipping.
+   use its physical height for clipping.
 
    Value is the index of the first glyph not in S.  */
 
@@ -3996,19 +4528,48 @@ x_fill_image_glyph_string (s)
 }
 
 
-/* Fill glyph string S from stretch glyph S->first_glyph.  */
+/* Fill glyph string S from a sequence of stretch glyphs.
 
-static void
-x_fill_stretch_glyph_string (s)
+   ROW is the glyph row in which the glyphs are found, AREA is the
+   area within the row.  START is the index of the first glyph to
+   consider, END is the index of the last + 1.
+
+   Value is the index of the first glyph not in S.  */
+
+static int
+x_fill_stretch_glyph_string (s, row, area, start, end)
      struct glyph_string *s;
+     struct glyph_row *row;
+     enum glyph_row_area area;
+     int start, end;
 {
+  struct glyph *glyph, *last;
+  int voffset, face_id;
+  
   xassert (s->first_glyph->type == STRETCH_GLYPH);
-  s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
+  
+  glyph = s->row->glyphs[s->area] + start;
+  last = s->row->glyphs[s->area] + end;
+  face_id = glyph->face_id;
+  s->face = FACE_FROM_ID (s->f, face_id);
   s->font = s->face->font;
-  s->width = s->first_glyph->pixel_width;
+  s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+  s->width = glyph->pixel_width;
+  voffset = glyph->voffset;
+
+  for (++glyph;
+       (glyph < last
+       && glyph->type == STRETCH_GLYPH
+       && glyph->voffset == voffset
+       && glyph->face_id == face_id);
+       ++glyph)
+    s->width += glyph->pixel_width;
   
   /* Adjust base line for subscript/superscript text.  */
-  s->ybase += s->first_glyph->voffset;
+  s->ybase += voffset;
+
+  xassert (s->face && s->face->gc);
+  return glyph - s->row->glyphs[s->area];
 }
 
 
@@ -4096,9 +4657,8 @@ x_set_glyph_string_background_width (s, start, last_x)
        {                                                                   \
         s = (struct glyph_string *) alloca (sizeof *s);                    \
         w32_init_glyph_string (s, hdc, NULL, W, ROW, AREA, START, HL);     \
-        x_fill_stretch_glyph_string (s);                                   \
+        START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END);            \
         x_append_glyph_string (&HEAD, &TAIL, s);                           \
-        ++START;                                                           \
          s->x = (X);                                                       \
        }                                                                   \
      while (0)
@@ -4137,7 +4697,7 @@ x_set_glyph_string_background_width (s, start, last_x)
 #define BUILD_CHAR_GLYPH_STRINGS(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P)                    \
      do                                                                           \
        {                                                                  \
-        int c, charset, face_id;                                          \
+        int c, face_id;                                           \
         wchar_t *char2b;                                                  \
                                                                           \
         c = (ROW)->glyphs[AREA][START].u.ch;                              \
@@ -4304,8 +4864,9 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
   HDC hdc = get_frame_dc (XFRAME (WINDOW_FRAME (w)));
 
   /* Let's rather be paranoid than getting a SEGV.  */
-  start = max (0, start);
   end = min (end, row->used[area]);
+  start = max (0, start);
+  start = min (end, start);
   if (real_start)
     *real_start = start;
   if (real_end)
@@ -4315,10 +4876,9 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
      end of the drawing area.  */
   if (row->full_width_p)
     {
-      struct frame *f = XFRAME (WINDOW_FRAME (w));
-
       /* X is relative to the left edge of W, without scroll bars
         or flag areas.  */
+      struct frame *f = XFRAME (WINDOW_FRAME (w));
       /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
       int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
 
@@ -4360,7 +4920,7 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
   /* If there are any glyphs with lbearing < 0 or rbearing > width in
      the row, redraw some glyphs in front or following the glyph
      strings built above.  */
-  if (!overlaps_p && row->contains_overlapping_glyphs_p)
+  if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
     {
       int dummy_x = 0;
       struct glyph_string *h, *t;
@@ -4618,6 +5178,16 @@ static void
 x_delete_glyphs (n)
      register int n;
 {
+  struct frame *f;
+
+  if (updating_frame)
+    f = updating_frame;
+  else
+    f = SELECTED_FRAME ();
+
+  if (! FRAME_W32_P (f))
+    return;
+
   abort ();
 }
 
@@ -4712,6 +5282,9 @@ x_clear_frame ()
   else
     f = SELECTED_FRAME ();
 
+  if (! FRAME_W32_P (f))
+    return;
+
   /* Clearing the frame will erase any cursor, so mark them all as no
      longer visible.  */
   mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
@@ -4737,9 +5310,13 @@ x_clear_frame ()
 static void
 w32_ring_bell (void)
 {
+  struct frame *f;
+
+  f = SELECTED_FRAME ();
+
   BLOCK_INPUT;
 
-  if (visible_bell)
+  if (FRAME_W32_P (f) && visible_bell)
     {
       int i;
       HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
@@ -4783,6 +5360,16 @@ static void
 x_ins_del_lines (vpos, n)
      int vpos, n;
 {
+  struct frame *f;
+
+  if (updating_frame)
+    f = updating_frame;
+  else
+    f = SELECTED_FRAME ();
+
+  if (! FRAME_W32_P (f))
+    return;
+
   abort ();
 }
 
@@ -4907,7 +5494,7 @@ expose_frame (f, x, y, w, h)
       window_rect.right = window_x + window_width;
       window_rect.bottom = window_y + window_height;
 
-      if (w32_intersect_rectangles (&r, &window_rect, &intersection_rect))
+      if (IntersectRect (&intersection_rect, &r, &window_rect))
        expose_window (w, &intersection_rect);
     }
 }
@@ -4949,7 +5536,7 @@ expose_window_tree (w, r)
          window_rect.bottom = window_rect.top
            + window_height + CURRENT_MODE_LINE_HEIGHT (w);
 
-         if (w32_intersect_rectangles (r, &window_rect, &intersection_rect))
+         if (IntersectRect (&intersection_rect, r, &window_rect))
            expose_window (w, &intersection_rect);
        }
 
@@ -4968,31 +5555,31 @@ expose_area (w, row, r, area)
      RECT *r;
      enum glyph_row_area area;
 {
-  int x;
   struct glyph *first = row->glyphs[area];
   struct glyph *end = row->glyphs[area] + row->used[area];
   struct glyph *last;
-  int first_x;
-
-  /* Set x to the window-relative start position for drawing glyphs of
-     AREA.  The first glyph of the text area can be partially visible.
-     The first glyphs of other areas cannot.  */
-  if (area == LEFT_MARGIN_AREA)
-    x = 0;
-  else if (area == TEXT_AREA)
-    x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
-  else
-    x = (window_box_width (w, LEFT_MARGIN_AREA)
-        + window_box_width (w, TEXT_AREA));
+  int first_x, start_x, x;
 
   if (area == TEXT_AREA && row->fill_line_p)
     /* If row extends face to end of line write the whole line.  */
-    x_draw_glyphs (w, x, row, area,
+    x_draw_glyphs (w, 0, row, area,
                   0, row->used[area],
                   row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
                   NULL, NULL, 0);
   else
     {
+      /* Set START_X to the window-relative start position for drawing glyphs of
+        AREA.  The first glyph of the text area can be partially visible.
+        The first glyphs of other areas cannot.  */
+      if (area == LEFT_MARGIN_AREA)
+       start_x = 0;
+      else if (area == TEXT_AREA)
+       start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
+      else
+       start_x = (window_box_width (w, LEFT_MARGIN_AREA)
+                  + window_box_width (w, TEXT_AREA));
+      x = start_x;
+
       /* Find the first glyph that must be redrawn.  */
       while (first < end
              && x + first->pixel_width < r->left)
@@ -5010,10 +5597,10 @@ expose_area (w, row, r, area)
           x += last->pixel_width;
           ++last;
         }
-      
+
       /* Repaint.  */
       if (last > first)
-        x_draw_glyphs (w, first_x, row, area,
+        x_draw_glyphs (w, first_x - start_x, row, area,
                        first - row->glyphs[area],
                        last - row->glyphs[area],
                        row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
@@ -5067,7 +5654,7 @@ x_phys_cursor_in_rect_p (w, r)
       cr.top = w->phys_cursor.y;
       cr.right = cr.left + cursor_glyph->pixel_width;
       cr.bottom = cr.top + w->phys_cursor_height;
-      return w32_intersect_rectangles (&cr, r, &result);
+      return IntersectRect (&result, &cr, r);
     }
   else
     return 0;
@@ -5091,7 +5678,7 @@ expose_window (w, r)
      happen when toolkit scroll bars are used and a window is split.
      Reconfiguring the scroll bar will generate an expose for a newly
      created window.  */
-  if (w->current_matrix == NULL)
+  if (w->current_matrix == NULL || w == updated_window)
     return;
 
   TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
@@ -5152,60 +5739,6 @@ expose_window (w, r)
     }
 }
 
-
-/* Determine the intersection of two rectangles R1 and R2.  Return
-   the intersection in *RESULT.  Value is non-zero if RESULT is not
-   empty.  */
-
-static int
-w32_intersect_rectangles (r1, r2, result)
-     RECT *r1, *r2, *result;
-{
-  RECT *left, *right;
-  RECT *upper, *lower;
-  int intersection_p = 0;
-  
-  /* Rerrange so that R1 is the left-most rectangle.  */
-  if (r1->left < r2->left)
-    left = r1, right = r2;
-  else
-    left = r2, right = r1;
-
-  /* X0 of the intersection is right.x0, if this is inside R1,
-     otherwise there is no intersection.  */
-  if (right->left <= left->right)
-    {
-      result->left = right->left;
-      
-      /* The right end of the intersection is the minimum of the
-        the right ends of left and right.  */
-      result->right = min (left->right, right->right);
-
-      /* Same game for Y.  */
-      if (r1->top < r2->top)
-       upper = r1, lower = r2;
-      else
-       upper = r2, lower = r1;
-
-      /* The upper end of the intersection is lower.y0, if this is inside
-        of upper.  Otherwise, there is no intersection.  */
-      if (lower->top <= upper->bottom)
-       {
-         result->top = lower->top;
-         
-         /* The lower end of the intersection is the minimum of the lower
-            ends of upper and lower.  */
-         result->bottom = min (lower->bottom, upper->bottom);
-         intersection_p = 1;
-       }
-    }
-
-  return intersection_p;
-}
-
-
-
-
 \f
 static void
 frame_highlight (f)
@@ -5273,6 +5806,8 @@ static void
 w32_frame_rehighlight (frame)
      struct frame *frame;
 {
+  if (! FRAME_W32_P (frame))
+    return;
   x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
 }
 
@@ -5318,7 +5853,7 @@ x_get_keysym_name (keysym)
   static char value[100];
 
   BLOCK_INPUT;
-  GetKeyNameText(keysym, value, 100);
+  GetKeyNameText (keysym, value, 100);
   UNBLOCK_INPUT;
 
   return value;
@@ -5352,7 +5887,7 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
   /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
      even for negative values.  */
   if (pix_x < 0)
-    pix_x -= FONT_WIDTH ((f)->output_data.w32->font) - 1;
+    pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
   if (pix_y < 0)
     pix_y -= (f)->output_data.w32->line_height - 1;
 
@@ -5363,7 +5898,7 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
     {
       bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
       bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
-      bounds->right  = bounds->left + FONT_WIDTH  (f->output_data.w32->font) - 1;
+      bounds->right  = bounds->left + FONT_WIDTH  (FRAME_FONT (f)) - 1;
       bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
     }
 
@@ -5371,8 +5906,8 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
     {
       if (pix_x < 0)
        pix_x = 0;
-      else if (pix_x > f->width)
-       pix_x = f->width;
+      else if (pix_x > FRAME_WINDOW_WIDTH (f))
+       pix_x = FRAME_WINDOW_WIDTH (f);
 
       if (pix_y < 0)
        pix_y = 0;
@@ -5491,7 +6026,7 @@ parse_button (message, pbutton, pup)
    If the event is a button press, then note that we have grabbed
    the mouse.  */
 
-static void
+static Lisp_Object
 construct_mouse_click (result, msg, f)
      struct input_event *result;
      W32Msg *msg;
@@ -5512,16 +6047,14 @@ construct_mouse_click (result, msg, f)
                          ? up_modifier
                          : down_modifier));
 
-  {
-    int row, column;
-
-    XSETINT (result->x, LOWORD (msg->msg.lParam));
-    XSETINT (result->y, HIWORD (msg->msg.lParam));
-    XSETFRAME (result->frame_or_window, f);
-  }
+  XSETINT (result->x, LOWORD (msg->msg.lParam));
+  XSETINT (result->y, HIWORD (msg->msg.lParam));
+  XSETFRAME (result->frame_or_window, f);
+  result->arg = Qnil;
+  return Qnil;
 }
 
-static void
+static Lisp_Object
 construct_mouse_wheel (result, msg, f)
      struct input_event *result;
      W32Msg *msg;
@@ -5534,13 +6067,15 @@ construct_mouse_wheel (result, msg, f)
   result->modifiers = msg->dwModifiers;
   p.x = LOWORD (msg->msg.lParam);
   p.y = HIWORD (msg->msg.lParam);
-  ScreenToClient(msg->msg.hwnd, &p);
+  ScreenToClient (msg->msg.hwnd, &p);
   XSETINT (result->x, p.x);
   XSETINT (result->y, p.y);
   XSETFRAME (result->frame_or_window, f);
+  result->arg = Qnil;
+  return Qnil;
 }
 
-static void
+static Lisp_Object
 construct_drag_n_drop (result, msg, f)
      struct input_event *result;
      W32Msg *msg;
@@ -5588,6 +6123,8 @@ construct_drag_n_drop (result, msg, f)
 
   XSETFRAME (frame, f);
   result->frame_or_window = Fcons (frame, files);
+  result->arg = Qnil;
+  return Qnil;
 }
 
 \f
@@ -5626,7 +6163,6 @@ note_mouse_movement (frame, msg)
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
-
       note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
     }
 }
@@ -5656,7 +6192,7 @@ x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
      int *hpos, *vpos, *area;
 {
   struct glyph *glyph, *end;
-  struct glyph_row *row;
+  struct glyph_row *row = NULL;
   int x0, i, left_area_width;
 
   /* Find row containing Y.  Give up if some row is not enabled.  */
@@ -5751,7 +6287,7 @@ frame_to_window_pixel_xy (w, x, y)
 }
 
 
-/* Take proper action when mouse has moved to the mode or top line of
+/* Take proper action when mouse has moved to the mode or header line of
    window W, x-position X.  MODE_LINE_P non-zero means mouse is on the
    mode line.  X is relative to the start of the text display area of
    W, so the width of bitmap areas and scroll bars must be subtracted
@@ -5783,6 +6319,7 @@ note_mode_line_highlight (w, x, mode_line_p)
       end = glyph + row->used[TEXT_AREA];
       x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
              + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
+      
       while (glyph < end
             && x >= x0 + glyph->pixel_width)
        {
@@ -5802,17 +6339,29 @@ note_mode_line_highlight (w, x, mode_line_p)
          help = Fget_text_property (make_number (glyph->charpos),
                                     Qhelp_echo, glyph->object);
          if (!NILP (help))
-           help_echo = help;
+            {
+              help_echo = help;
+              XSETWINDOW (help_echo_window, w);
+              help_echo_object = glyph->object;
+              help_echo_pos = glyph->charpos;
+            }
 
          /* Change the mouse pointer according to what is under X/Y.  */
          map = Fget_text_property (make_number (glyph->charpos),
                                    Qlocal_map, glyph->object);
-         if (!NILP (Fkeymapp (map)))
+         if (KEYMAPP (map))
            cursor = f->output_data.w32->nontext_cursor;
+         else
+           {
+             map = Fget_text_property (make_number (glyph->charpos),
+                                       Qkeymap, glyph->object);
+             if (KEYMAPP (map))
+               cursor = f->output_data.w32->nontext_cursor;
+           }
        }
     }
 
-#if 0 /* NTEMACS_TODO: mouse cursor */
+#if 0 /* TODO: mouse cursor */
   XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
 #endif
 }
@@ -5883,7 +6432,10 @@ note_mouse_highlight (f, x, y)
       note_mode_line_highlight (w, x, portion == 1);
       return;
     }
-#if 0 /* NTEMACS_TODO: mouse cursor */
+#if 0 /* TODO: mouse cursor */
+  else if (portion == 2)
+    XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                  f->output_data.x->horizontal_drag_cursor);
   else
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                   f->output_data.x->text_cursor);
@@ -5945,14 +6497,15 @@ note_mouse_highlight (f, x, y)
           enough space for all, and try again.  */
         len = 10;
         overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-        noverlays =  overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
+        noverlays =  overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
        if (noverlays > len)
          {
            len = noverlays;
            overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
-           noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
+           noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
          }
 
+       /* Sort overlays into increasing priority order.  */
         noverlays = sort_overlays (overlay_vec, noverlays, w);
 
        /* Check mouse-face highlighting.  */
@@ -5970,7 +6523,7 @@ note_mouse_highlight (f, x, y)
 
             /* Find the highest priority overlay that has a mouse-face prop.  */
             overlay = Qnil;
-            for (i = 0; i < noverlays; i++)
+            for (i = noverlays - 1; i >= 0; --i)
               {
                 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
                 if (!NILP (mouse_face))
@@ -6056,26 +6609,43 @@ note_mouse_highlight (f, x, y)
 
         /* Look for a `help-echo' property.  */
         {
-          Lisp_Object help;
+          Lisp_Object help, overlay;
 
          /* Check overlays first.  */
-         help = Qnil;
-         for (i = 0; i < noverlays && NILP (help); ++i)
-           help = Foverlay_get (overlay_vec[i], Qhelp_echo); 
-           
-         /* Try text properties.  */
-         if (NILP (help)
-             && ((STRINGP (glyph->object)
+         help = overlay = Qnil;
+         for (i = noverlays - 1; i >= 0 && NILP (help); --i)
+            {
+              overlay = overlay_vec[i];
+              help = Foverlay_get (overlay, Qhelp_echo); 
+            }
+
+          if (!NILP (help))
+            {
+              help_echo = help;
+              help_echo_window = window;
+              help_echo_object = overlay;
+              help_echo_pos = pos;
+            }
+          else
+            {
+              /* Try text properties.  */
+              if ((STRINGP (glyph->object)
                   && glyph->charpos >= 0
                   && glyph->charpos < XSTRING (glyph->object)->size)
                  || (BUFFERP (glyph->object)
                      && glyph->charpos >= BEGV
-                     && glyph->charpos < ZV)))
-           help = Fget_text_property (make_number (glyph->charpos),
-                                      Qhelp_echo, glyph->object);
+                     && glyph->charpos < ZV))
+                help = Fget_text_property (make_number (glyph->charpos),
+                                           Qhelp_echo, glyph->object);
            
-         if (!NILP (help))
-           help_echo = help;
+              if (!NILP (help))
+                {
+                  help_echo = help;
+                  help_echo_window = window;
+                  help_echo_object = glyph->object;
+                  help_echo_pos = glyph->charpos;
+                }
+            }
         }
         
         BEGV = obegv;
@@ -6114,7 +6684,7 @@ static int last_tool_bar_item;
    Return in *GLYPH a pointer to the glyph of the tool-bar item in
    the current matrix of the tool-bar window of F, or NULL if not
    on a tool-bar item.  Return in *PROP_IDX the index of the tool-bar
-   item in F->current_tool_bar_items.  Value is
+   item in F->tool_bar_items.  Value is
 
    -1  if X/Y is not on a tool-bar item
    0   if X/Y is on the same item that was highlighted before.
@@ -6137,7 +6707,7 @@ x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
     return -1;
 
   /* Get the start of this tool-bar item's properties in
-     f->current_tool_bar_items.  */
+     f->tool_bar_items.  */
   if (!tool_bar_item_info (f, *glyph, prop_idx))
     return -1;
 
@@ -6179,8 +6749,7 @@ w32_handle_tool_bar_click (f, button_event)
     return;
 
   /* If item is disabled, do nothing.  */
-  enabled_p = (XVECTOR (f->current_tool_bar_items)
-              ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
+  enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
   if (NILP (enabled_p))
     return;
   
@@ -6200,8 +6769,7 @@ w32_handle_tool_bar_click (f, button_event)
       show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
       dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
 
-      key = (XVECTOR (f->current_tool_bar_items)
-            ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
+      key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
 
       XSETFRAME (frame, f);
       event.kind = TOOL_BAR_EVENT;
@@ -6273,8 +6841,7 @@ note_tool_bar_highlight (f, x, y)
   draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
   
   /* If tool-bar item is not enabled, don't highlight it.  */
-  enabled_p = (XVECTOR (f->current_tool_bar_items)
-              ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
+  enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
   if (!NILP (enabled_p))
     {
       /* Compute the x-position of the glyph.  In front and past the
@@ -6306,11 +6873,11 @@ note_tool_bar_highlight (f, x, y)
   
   /* Set help_echo to a help string.to display for this tool-bar item.
      w32_read_socket does the rest.  */
-  help_echo = (XVECTOR (f->current_tool_bar_items)
-              ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
+  help_echo_object = help_echo_window = Qnil;
+  help_echo_pos = -1;
+  help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
   if (NILP (help_echo))
-    help_echo = (XVECTOR (f->current_tool_bar_items)
-                ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
+    help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
 }
 
 
@@ -6480,8 +7047,11 @@ show_mouse_face (dpyinfo, draw)
        }
 
       if (end_hpos > start_hpos)
-       x_draw_glyphs (w, start_x, row, TEXT_AREA,
-                      start_hpos, end_hpos, draw, NULL, NULL, 0);
+        {
+          row->mouse_face_p = draw == DRAW_MOUSE_FACE;
+          x_draw_glyphs (w, start_x, row, TEXT_AREA,
+                         start_hpos, end_hpos, draw, NULL, NULL, 0);
+        }
     }
 
   /* If we turned the cursor off, turn it back on.  */
@@ -6493,7 +7063,7 @@ show_mouse_face (dpyinfo, draw)
   output_cursor = saved_cursor;
 
  set_x_cursor:
-#if 0 /* NTEMACS_TODO: mouse cursor */
+#if 0 /* TODO: mouse cursor */
   /* Change the mouse cursor.  */
   if (draw == DRAW_NORMAL_TEXT)
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
@@ -6515,8 +7085,11 @@ void
 clear_mouse_face (dpyinfo)
      struct w32_display_info *dpyinfo;
 {
-  if (tip_frame)
+#if 0 /* This prevents redrawing tool bar items when changing from one
+        to another while a tooltip is open, so don't do it.  */
+  if (!NILP (tip_frame))
     return;
+#endif
 
   if (! NILP (dpyinfo->mouse_face_window))
     show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
@@ -6526,8 +7099,29 @@ clear_mouse_face (dpyinfo)
   dpyinfo->mouse_face_window = Qnil;
 }
 
-/* Just discard the mouse face information for frame F, if any.
-   This is used when the size of F is changed.  */
+
+/* Clear any mouse-face on window W.  This function is part of the
+   redisplay interface, and is called from try_window_id and similar
+   functions to ensure the mouse-highlight is off.  */
+
+static void
+x_clear_mouse_face (w)
+     struct window *w;
+{
+  struct w32_display_info *dpyinfo
+    = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
+  Lisp_Object window;
+
+  BLOCK_INPUT;
+  XSETWINDOW (window, w);
+  if (EQ (window, dpyinfo->mouse_face_window))
+    clear_mouse_face (dpyinfo);
+  UNBLOCK_INPUT;
+}
+
+
+/* Just discard the mouse face information for frame F, if any.
+   This is used when the size of F is changed.  */
 
 void
 cancel_mouse_face (f)
@@ -6610,13 +7204,15 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time)
        else
          {
            /* Is window under mouse one of our frames?  */
-           f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
+           f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
+                                    WindowFromPoint (pt));
          }
 
        /* If not, is it one of our scroll bars?  */
        if (! f1)
          {
-           struct scroll_bar *bar = x_window_to_scroll_bar (WindowFromPoint(pt));
+           struct scroll_bar *bar
+              = x_window_to_scroll_bar (WindowFromPoint (pt));
 
            if (bar)
              {
@@ -6684,7 +7280,7 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time)
 \f
 /* Scroll bar support.  */
 
-/* Given an window ID, find the struct scroll_bar which manages it.
+/* Given a window ID, find the struct scroll_bar which manages it.
    This can be called in GC, so we have to make sure to strip off mark
    bits.  */
 
@@ -6828,7 +7424,7 @@ my_set_window_pos (HWND hwnd, HWND hwndAfter,
 #endif
 }
 
-BOOL
+void
 my_set_focus (f, hwnd)
      struct frame * f;
      HWND hwnd;
@@ -6837,7 +7433,7 @@ my_set_focus (f, hwnd)
               (WPARAM) hwnd, 0);
 }
 
-BOOL
+void
 my_set_foreground_window (hwnd)
      HWND hwnd;
 {
@@ -7093,13 +7689,16 @@ w32_condemn_scroll_bars (frame)
     }
 }
 
+
 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
    Note that WINDOW isn't necessarily condemned at all.  */
+
 static void
 w32_redeem_scroll_bar (window)
      struct window *window;
 {
   struct scroll_bar *bar;
+  struct frame *f;
 
   /* We can't redeem this window's scroll bar if it doesn't have one.  */
   if (NILP (window->vertical_scroll_bar))
@@ -7108,36 +7707,33 @@ w32_redeem_scroll_bar (window)
   bar = XSCROLL_BAR (window->vertical_scroll_bar);
 
   /* Unlink it from the condemned list.  */
-  {
-    FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
-
-    if (NILP (bar->prev))
-      {
-       /* If the prev pointer is nil, it must be the first in one of
-           the lists.  */
-       if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
-         /* It's not condemned.  Everything's fine.  */
-         return;
-       else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
-                    window->vertical_scroll_bar))
-         FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
-       else
-         /* If its prev pointer is nil, it must be at the front of
-             one or the other!  */
-         abort ();
-      }
-    else
-      XSCROLL_BAR (bar->prev)->next = bar->next;
+  f = XFRAME (WINDOW_FRAME (window));
+  if (NILP (bar->prev))
+    {
+      /* If the prev pointer is nil, it must be the first in one of
+         the lists.  */
+      if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
+        /* It's not condemned.  Everything's fine.  */
+        return;
+      else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
+                   window->vertical_scroll_bar))
+        FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
+      else
+        /* If its prev pointer is nil, it must be at the front of
+           one or the other!  */
+        abort ();
+    }
+  else
+    XSCROLL_BAR (bar->prev)->next = bar->next;
 
-    if (! NILP (bar->next))
-      XSCROLL_BAR (bar->next)->prev = bar->prev;
+  if (! NILP (bar->next))
+    XSCROLL_BAR (bar->next)->prev = bar->prev;
 
-    bar->next = FRAME_SCROLL_BARS (f);
-    bar->prev = Qnil;
-    XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
-    if (! NILP (bar->next))
-      XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
-  }
+  bar->next = FRAME_SCROLL_BARS (f);
+  bar->prev = Qnil;
+  XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
+  if (! NILP (bar->next))
+    XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
 }
 
 /* Remove all scroll bars on FRAME that haven't been saved since the
@@ -7176,7 +7772,7 @@ w32_judge_scroll_bars (f)
    mark bits.  */
 
 static int
-x_scroll_bar_handle_click (bar, msg, emacs_event)
+w32_scroll_bar_handle_click (bar, msg, emacs_event)
      struct scroll_bar *bar;
      W32Msg *msg;
      struct input_event *emacs_event;
@@ -7189,6 +7785,7 @@ x_scroll_bar_handle_click (bar, msg, emacs_event)
   /* not really meaningful to distinguish up/down */
   emacs_event->modifiers = msg->dwModifiers;
   emacs_event->frame_or_window = bar->window;
+  emacs_event->arg = Qnil;
   emacs_event->timestamp = msg->msg.time;
 
   {
@@ -7347,8 +7944,8 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
       break;
   }
 
-  XSETINT(*x, pos);
-  XSETINT(*y, top_range);
+  XSETINT (*x, pos);
+  XSETINT (*y, top_range);
 
   f->mouse_moved = 0;
   last_mouse_scroll_bar = Qnil;
@@ -7394,20 +7991,6 @@ x_scroll_bar_clear (f)
       }
 }
 
-show_scroll_bars (f, how)
-     FRAME_PTR f;
-     int how;
-{
-  Lisp_Object bar;
-
-  for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
-       bar = XSCROLL_BAR (bar)->next)
-    {
-      HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
-      my_show_window (f, window, how);
-    }
-}
-
 \f
 /* The main W32 event-reading loop - w32_read_socket.  */
 
@@ -7472,7 +8055,7 @@ w32_read_socket (sd, bufp, numchars, expected)
   if (numchars <= 0)
     abort ();                   /* Don't think this happens. */
 
-  /* NTEMACS_TODO: tooltips, tool-bars, ghostscript integration, mouse
+  /* TODO: tooltips, tool-bars, ghostscript integration, mouse
      cursors. */
   while (get_next_msg (&msg, FALSE))
     {
@@ -7506,11 +8089,12 @@ w32_read_socket (sd, bufp, numchars, expected)
                      {
                        bufp->kind = deiconify_event;
                        XSETFRAME (bufp->frame_or_window, f);
+                       bufp->arg = Qnil;
                        bufp++;
                        count++;
                        numchars--;
                      }
-                   else if (! NILP(Vframe_list)
+                   else if (! NILP (Vframe_list)
                             && ! NILP (XCDR (Vframe_list)))
                      /* Force a redisplay sooner or later to update the
                         frame titles in case this is the second frame.  */
@@ -7543,6 +8127,7 @@ w32_read_socket (sd, bufp, numchars, expected)
          
              bufp->kind = language_change_event;
              XSETFRAME (bufp->frame_or_window, f);
+             bufp->arg = Qnil;
              bufp->code = msg.msg.wParam;
              bufp->modifiers = msg.msg.lParam & 0xffff;
              bufp++;
@@ -7564,6 +8149,7 @@ w32_read_socket (sd, bufp, numchars, expected)
              bufp->code = msg.msg.wParam;
              bufp->modifiers = msg.dwModifiers;
              XSETFRAME (bufp->frame_or_window, f);
+             bufp->arg = Qnil;
              bufp->timestamp = msg.msg.time;
              bufp++;
              numchars--;
@@ -7584,6 +8170,7 @@ w32_read_socket (sd, bufp, numchars, expected)
              bufp->code = msg.msg.wParam;
              bufp->modifiers = msg.dwModifiers;
              XSETFRAME (bufp->frame_or_window, f);
+             bufp->arg = Qnil;
              bufp->timestamp = msg.msg.time;
              bufp++;
              numchars--;
@@ -7593,7 +8180,8 @@ w32_read_socket (sd, bufp, numchars, expected)
 
        case WM_MOUSEMOVE:
           previous_help_echo = help_echo;
-          help_echo = Qnil;
+          help_echo = help_echo_object = help_echo_window = Qnil;
+          help_echo_pos = -1;
 
          if (dpyinfo->grabbed && last_mouse_frame
              && FRAME_LIVE_P (last_mouse_frame))
@@ -7616,6 +8204,7 @@ w32_read_socket (sd, bufp, numchars, expected)
               || !NILP (previous_help_echo))
             {
               Lisp_Object frame;
+              int n;
 
               if (f)
                 XSETFRAME (frame, f);
@@ -7623,10 +8212,10 @@ w32_read_socket (sd, bufp, numchars, expected)
                 frame = Qnil;
 
               any_help_event_p = 1;
-              bufp->kind = HELP_EVENT;
-              bufp->frame_or_window = frame;
-              bufp->arg = help_echo;
-              ++bufp, ++count, --numchars;
+              n = gen_help_event (bufp, numchars, help_echo, frame,
+                                 help_echo_window, help_echo_object,
+                                 help_echo_pos);
+              bufp += n, count += n, numchars -= n;
             }
           break;
 
@@ -7661,7 +8250,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                     && XFASTINT (XWINDOW (f->tool_bar_window)->height))
                   {
                     Lisp_Object window;
-                    int p, x, y;
+                    int p;
 
                     /* Set x and y.  */
                     window = window_from_coordinates (f,
@@ -7737,14 +8326,7 @@ w32_read_socket (sd, bufp, numchars, expected)
             UINT menu_item = (UINT) LOWORD (msg.msg.wParam);
             UINT flags = (UINT) HIWORD (msg.msg.wParam);
 
-            /* NTEMACS_TODO: Can't call the below with input blocked,
-               as it may result in hooks being called if the window
-               layout needs to change to display the message, and
-               Feval will abort if input is blocked. But unblocking
-               temporarily is not the best solution. */
-            UNBLOCK_INPUT;
             w32_menu_display_help (menu, menu_item, flags);
-            BLOCK_INPUT;
           }
           break;
 
@@ -7767,7 +8349,7 @@ w32_read_socket (sd, bufp, numchars, expected)
              
            if (bar && numchars >= 1)
              {
-               if (x_scroll_bar_handle_click (bar, &msg, bufp))
+               if (w32_scroll_bar_handle_click (bar, &msg, bufp))
                  {
                    bufp++;
                    count++;
@@ -7830,6 +8412,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                  
                  bufp->kind = iconify_event;
                  XSETFRAME (bufp->frame_or_window, f);
+                 bufp->arg = Qnil;
                  bufp++;
                  count++;
                  numchars--;
@@ -7859,6 +8442,7 @@ w32_read_socket (sd, bufp, numchars, expected)
 
                      bufp->kind = deiconify_event;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      bufp++;
                      count++;
                      numchars--;
@@ -7881,7 +8465,7 @@ w32_read_socket (sd, bufp, numchars, expected)
              int width;
              int height;
              
-             GetClientRect(msg.msg.hwnd, &rect);
+             GetClientRect (msg.msg.hwnd, &rect);
              
              height = rect.bottom - rect.top;
              width = rect.right - rect.left;
@@ -7926,13 +8510,11 @@ w32_read_socket (sd, bufp, numchars, expected)
          break;
 
        case WM_KILLFOCUS:
-          /* NTEMACS_TODO: some of this belongs in MOUSE_LEAVE */
+          /* TODO: some of this belongs in MOUSE_LEAVE */
          f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
 
           if (f)
             {
-              Lisp_Object frame;
-
               if (f == dpyinfo->w32_focus_event_frame)
                 dpyinfo->w32_focus_event_frame = 0;
 
@@ -7953,11 +8535,14 @@ w32_read_socket (sd, bufp, numchars, expected)
                  the mouse leaves the frame.  */
               if (any_help_event_p)
                 {
+                  Lisp_Object frame;
+                  int n;
+
                   XSETFRAME (frame, f);
-                  bufp->kind = HELP_EVENT;
-                  bufp->frame_or_window = frame;
-                  bufp->arg = Qnil;
-                  ++bufp, ++count, --numchars;
+                  help_echo = Qnil;
+                  n = gen_help_event (bufp, numchars,
+                                      Qnil, frame, Qnil, Qnil, 0);
+                  bufp += n, count += n, numchars -=n;
                 }
             }
 
@@ -7975,6 +8560,7 @@ w32_read_socket (sd, bufp, numchars, expected)
              
              bufp->kind = delete_window_event;
              XSETFRAME (bufp->frame_or_window, f);
+             bufp->arg = Qnil;
              bufp++;
              count++;
              numchars--;
@@ -7991,6 +8577,7 @@ w32_read_socket (sd, bufp, numchars, expected)
          
              bufp->kind = menu_bar_activate_event;
              XSETFRAME (bufp->frame_or_window, f);
+             bufp->arg = Qnil;
              bufp++;
              count++;
              numchars--;
@@ -8195,7 +8782,7 @@ x_draw_hollow_cursor (w, row)
      struct glyph_row *row;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  HDC hdc = get_frame_dc (f);
+  HDC hdc;
   RECT rect;
   int wd;
   struct glyph *cursor_glyph;
@@ -8224,7 +8811,7 @@ x_draw_hollow_cursor (w, row)
     wd = min (CANON_X_UNIT (f), wd);
 
   rect.right = rect.left + wd;
-
+  hdc = get_frame_dc (f);
   FrameRect (hdc, &rect, hb);
   DeleteObject (hb);
 
@@ -8245,26 +8832,35 @@ x_draw_bar_cursor (w, row, width)
      struct glyph_row *row;
      int width;
 {
-  /* If cursor hpos is out of bounds, don't draw garbage.  This can
-     happen in mini-buffer windows when switching between echo area
-     glyphs and mini-buffer.  */
-  if (w->phys_cursor.hpos < row->used[TEXT_AREA])
-    {
-      struct frame *f = XFRAME (w->frame);
-      struct glyph *cursor_glyph;
-      int x;
-      HDC hdc;
-
-      cursor_glyph = get_phys_cursor_glyph (w);
-      if (cursor_glyph == NULL)
-       return;
+  struct frame *f = XFRAME (w->frame);
+  struct glyph *cursor_glyph;
+  int x;
+  HDC hdc;
 
-      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+  /* If cursor is out of bounds, don't draw garbage.  This can happen
+     in mini-buffer windows when switching between echo area glyphs
+     and mini-buffer.  */
+  cursor_glyph = get_phys_cursor_glyph (w);
+  if (cursor_glyph == NULL)
+    return;
 
+  /* If on an image, draw like a normal cursor.  That's usually better
+     visible than drawing a bar, esp. if the image is large so that
+     the bar might not be in the window.  */
+  if (cursor_glyph->type == IMAGE_GLYPH)
+    {
+      struct glyph_row *row;
+      row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
+      x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
+    }
+  else
+    {
       if (width < 0)
         width = f->output_data.w32->cursor_width;
 
+      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
       hdc = get_frame_dc (f);
+      w32_clip_to_row (w, row, hdc, 0);
       w32_fill_area (f, hdc, f->output_data.w32->cursor_pixel,
                      x,
                      WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
@@ -8365,7 +8961,8 @@ x_erase_phys_cursor (w)
         
   /* If the cursor is in the mouse face area, redisplay that when
      we clear the cursor.  */
-  if (w == XWINDOW (dpyinfo->mouse_face_window)
+  if (! NILP (dpyinfo->mouse_face_window)
+      && w == XWINDOW (dpyinfo->mouse_face_window)
       && (vpos > dpyinfo->mouse_face_beg_row
          || (vpos == dpyinfo->mouse_face_beg_row
              && hpos >= dpyinfo->mouse_face_beg_col))
@@ -8482,7 +9079,9 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
         {
          extern int cursor_in_non_selected_windows;
 
-          if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
+          if (MINI_WINDOW_P (w) 
+              || !cursor_in_non_selected_windows
+              || NILP (XBUFFER (w->buffer)->cursor_type))
             new_cursor_type = NO_CURSOR;
           else
             new_cursor_type = HOLLOW_BOX_CURSOR;
@@ -8632,8 +9231,6 @@ x_bitmap_icon (f, icon)
      struct frame *f;
      Lisp_Object icon;
 {
-  int mask, bitmap_id;
-  Window icon_window;
   HANDLE hicon;
 
   if (FRAME_W32_WINDOW (f) == 0)
@@ -8677,6 +9274,30 @@ x_bitmap_icon (f, icon)
   return 0;
 }
 
+\f
+/************************************************************************
+                         Handling X errors
+ ************************************************************************/
+
+/* Display Error Handling functions not used on W32. Listing them here
+   helps diff stay in step when comparing w32term.c with xterm.c.
+
+x_error_catcher (display, error)
+x_catch_errors (dpy)
+x_catch_errors_unwind (old_val)
+x_check_errors (dpy, format)
+x_had_errors_p (dpy)
+x_clear_errors (dpy)
+x_uncatch_errors (dpy, count)
+x_trace_wire ()
+x_connection_signal (signalnum)
+x_connection_closed (dpy, error_message)
+x_error_quitter (display, error)
+x_error_handler (display, error)
+x_io_error_quitter (display)
+
+ */
+
 \f
 /* Changing the font of the frame.  */
 
@@ -8703,11 +9324,14 @@ x_new_font (f, fontname)
   /* Compute the scroll bar width in character columns.  */
   if (f->scroll_bar_pixel_width > 0)
     {
-      int wid = FONT_WIDTH (f->output_data.w32->font);
+      int wid = FONT_WIDTH (FRAME_FONT (f));
       f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
     }
   else
-    f->scroll_bar_cols = 2;
+    {
+      int wid = FONT_WIDTH (FRAME_FONT (f));
+      f->scroll_bar_cols = (14 + wid - 1) / wid;
+    }
 
   /* Now make the frame display the given font.  */
   if (FRAME_W32_WINDOW (f) != 0)
@@ -8718,7 +9342,7 @@ x_new_font (f, fontname)
   else
     /* If we are setting a new frame's font for the first time,
        there are no faces yet, so this font's height is the line height.  */
-    f->output_data.w32->line_height = FONT_HEIGHT (f->output_data.w32->font);
+    f->output_data.w32->line_height = FONT_HEIGHT (FRAME_FONT (f));
 
   return build_string (fontp->full_name);
 }
@@ -8735,7 +9359,6 @@ x_new_fontset (f, fontsetname)
 {
   int fontset = fs_query_fontset (build_string (fontsetname), 0);
   Lisp_Object result;
-  char *fontname;
 
   if (fontset < 0)
     return Qnil;
@@ -8757,97 +9380,20 @@ x_new_fontset (f, fontsetname)
   return build_string (fontsetname);
 }
 
+\f
+/***********************************************************************
+       TODO: W32 Input Methods
+ ***********************************************************************/
+/* Listing missing functions from xterm.c helps diff stay in step.
 
-#if GLYPH_DEBUG
-
-/* Check that FONT is valid on frame F.  It is if it can be found in F's
-   font table.  */
-
-static void
-x_check_font (f, font)
-     struct frame *f;
-     XFontStruct *font;
-{
-  int i;
-  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
-
-  xassert (font != NULL);
-
-  for (i = 0; i < dpyinfo->n_fonts; i++)
-    if (dpyinfo->font_table[i].name 
-       && font == dpyinfo->font_table[i].font)
-      break;
-
-  xassert (i < dpyinfo->n_fonts);
-}
-
-#endif /* GLYPH_DEBUG != 0 */
-
-/* Set *W to the minimum width, *H to the minimum font height of FONT.
-   Note: There are (broken) X fonts out there with invalid XFontStruct
-   min_bounds contents.  For example, handa@etl.go.jp reports that
-   "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
-   have font->min_bounds.width == 0.  */
-
-static INLINE void
-x_font_min_bounds (font, w, h)
-     XFontStruct *font;
-     int *w, *h;
-{
-  *h = FONT_HEIGHT (font);
-  *w = FONT_WIDTH (font);
-#if 0 /* NTEMACS_TODO: min/max bounds of Windows fonts */
-  *w = font->min_bounds.width;
-
-  /* Try to handle the case where FONT->min_bounds has invalid
-     contents.  Since the only font known to have invalid min_bounds
-     is fixed-width, use max_bounds if min_bounds seems to be invalid.  */
-  if (*w <= 0)
-    *w = font->max_bounds.width;
-#endif
-}
-
-
-/* Compute the smallest character width and smallest font height over
-   all fonts available on frame F.  Set the members smallest_char_width
-   and smallest_font_height in F's x_display_info structure to
-   the values computed.  Value is non-zero if smallest_font_height or
-   smallest_char_width become smaller than they were before.  */
-
-int
-x_compute_min_glyph_bounds (f)
-     struct frame *f;
-{
-  int i;
-  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
-  XFontStruct *font;
-  int old_width = dpyinfo->smallest_char_width;
-  int old_height = dpyinfo->smallest_font_height;
-  
-  dpyinfo->smallest_font_height = 100000;
-  dpyinfo->smallest_char_width = 100000;
-  
-  for (i = 0; i < dpyinfo->n_fonts; ++i)
-    if (dpyinfo->font_table[i].name)
-      {
-       struct font_info *fontp = dpyinfo->font_table + i;
-       int w, h;
-       
-       font = (XFontStruct *) fontp->font;
-       xassert (font != (XFontStruct *) ~0);
-       x_font_min_bounds (font, &w, &h);
-       
-       dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
-       dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
-      }
-
-  xassert (dpyinfo->smallest_char_width > 0
-          && dpyinfo->smallest_font_height > 0);
+xim_destroy_callback (xim, client_data, call_data)
+xim_open_dpy (dpyinfo, resource_name)
+struct xim_inst_t
+xim_instantiate_callback (display, client_data, call_data)
+xim_initialize (dpyinfo, resource_name)
+xim_close_dpy (dpyinfo)
 
-  return (dpyinfo->n_fonts == 1
-         || dpyinfo->smallest_char_width < old_width
-         || dpyinfo->smallest_font_height < old_height);
-}
+ */
 
 \f
 /* Calculate the absolute position in frame F
@@ -8857,14 +9403,14 @@ void
 x_calc_absolute_position (f)
      struct frame *f;
 {
-  Window child;
   POINT pt;
   int flags = f->output_data.w32->size_hint_flags;
 
   pt.x = pt.y = 0;
 
   /* Find the position of the outside upper-left corner of
-     the inner window, with respect to the outer window.  */
+     the inner window, with respect to the outer window.
+     But do this only if we will need the results.  */
   if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
     {
       BLOCK_INPUT;
@@ -8894,7 +9440,7 @@ x_calc_absolute_position (f)
                              - 2 * f->output_data.w32->border_width - pt.x
                              - PIXEL_WIDTH (f)
                              + f->output_data.w32->left_pos);
-  /* NTEMACS_TODO: Subtract menubar height?  */
+
   if (flags & YNegative)
     f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
                             - 2 * f->output_data.w32->border_width - pt.y
@@ -8936,18 +9482,8 @@ x_set_offset (f, xoff, yoff, change_gravity)
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
-  /* It is a mystery why we need to add the border_width here
-     when the frame is already visible, but experiment says we do.  */
   modified_left = f->output_data.w32->left_pos;
   modified_top = f->output_data.w32->top_pos;
-#ifndef HAVE_NTGUI
-  /* Do not add in border widths under W32.  */
-  if (change_gravity != 0)
-    {
-      modified_left += f->output_data.w32->border_width;
-      modified_top += f->output_data.w32->border_width;
-    }
-#endif
 
   my_set_window_pos (FRAME_W32_WINDOW (f),
                     NULL,
@@ -8961,6 +9497,7 @@ x_set_offset (f, xoff, yoff, change_gravity)
    If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
    for this size change and subsequent size changes.
    Otherwise we leave the window gravity unchanged.  */
+
 void
 x_set_window_size (f, change_gravity, cols, rows)
      struct frame *f;
@@ -9009,7 +9546,7 @@ x_set_window_size (f, change_gravity, cols, rows)
      
      We could just not bother storing any of this information here,
      and let the ConfigureNotify event set everything up, but that
-     might be kind of confusing to the lisp code, since size changes
+     might be kind of confusing to the Lisp code, since size changes
      wouldn't be reported in the frame parameters until some random
      point in the future when the ConfigureNotify event arrives.
 
@@ -9039,6 +9576,27 @@ x_set_window_size (f, change_gravity, cols, rows)
 \f
 /* Mouse warping.  */
 
+void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
+
+void
+x_set_mouse_position (f, x, y)
+     struct frame *f;
+     int x, y;
+{
+  int pix_x, pix_y;
+
+  pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH  (f->output_data.w32->font) / 2;
+  pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
+
+  if (pix_x < 0) pix_x = 0;
+  if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
+
+  if (pix_y < 0) pix_y = 0;
+  if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
+
+  x_set_mouse_pixel_position (f, pix_x, pix_y);
+}
+
 void
 x_set_mouse_pixel_position (f, pix_x, pix_y)
      struct frame *f;
@@ -9059,27 +9617,10 @@ x_set_mouse_pixel_position (f, pix_x, pix_y)
   UNBLOCK_INPUT;
 }
 
-void
-x_set_mouse_position (f, x, y)
-     struct frame *f;
-     int x, y;
-{
-  int pix_x, pix_y;
-
-  pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH  (f->output_data.w32->font) / 2;
-  pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
-
-  if (pix_x < 0) pix_x = 0;
-  if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
-
-  if (pix_y < 0) pix_y = 0;
-  if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
-
-  x_set_mouse_pixel_position (f, pix_x, pix_y);
-}
 \f
 /* focus shifting, raising and lowering.  */
 
+void
 x_focus_on_frame (f)
      struct frame *f;
 {
@@ -9097,6 +9638,7 @@ x_focus_on_frame (f)
   UNBLOCK_INPUT;
 }
 
+void
 x_unfocus_frame (f)
      struct frame *f;
 {
@@ -9176,11 +9718,14 @@ x_lower_frame (f)
 }
 
 static void
-w32_frame_raise_lower (f, raise)
+w32_frame_raise_lower (f, raise_flag)
      FRAME_PTR f;
-     int raise;
+     int raise_flag;
 {
-  if (raise)
+  if (! FRAME_W32_P (f))
+    return;
+
+  if (raise_flag)
     x_raise_frame (f);
   else
     x_lower_frame (f);
@@ -9195,6 +9740,7 @@ w32_frame_raise_lower (f, raise)
    but it will become visible later when the window manager
    finishes with it.  */
 
+void
 x_make_frame_visible (f)
      struct frame *f;
 {
@@ -9241,7 +9787,7 @@ x_make_frame_visible (f)
         input_signal_count < count && !FRAME_VISIBLE_P (f);)
       {
        /* Force processing of queued events.  */
-        /* NTEMACS_TODO: x_sync equivalent?  */
+        /* TODO: x_sync equivalent?  */
 
        /* Machines that do polling rather than SIGIO have been observed
           to go into a busy-wait here.  So we'll fake an alarm signal
@@ -9296,7 +9842,6 @@ void
 x_iconify_frame (f)
      struct frame *f;
 {
-  int result;
   Lisp_Object type;
 
   /* Don't keep the highlight on an invisible frame.  */
@@ -9317,22 +9862,40 @@ x_iconify_frame (f)
 
   UNBLOCK_INPUT;
 }
+
 \f
-/* Destroy the window of frame F.  */
+/* Free X resources of frame F.  */
 
-x_destroy_window (f)
+void
+x_free_frame_resources (f)
      struct frame *f;
 {
   struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
 
   BLOCK_INPUT;
 
-  my_destroy_window (f, FRAME_W32_WINDOW (f));
+  if (FRAME_W32_WINDOW (f))
+    my_destroy_window (f, FRAME_W32_WINDOW (f));
+      
   free_frame_menubar (f);
-  free_frame_faces (f);
 
+  unload_color (f, f->output_data.x->foreground_pixel);
+  unload_color (f, f->output_data.x->background_pixel);
+  unload_color (f, f->output_data.w32->cursor_pixel);
+  unload_color (f, f->output_data.w32->cursor_foreground_pixel);
+  unload_color (f, f->output_data.w32->border_pixel);
+  unload_color (f, f->output_data.w32->mouse_pixel);
+  if (f->output_data.w32->white_relief.allocated_p)
+    unload_color (f, f->output_data.w32->white_relief.pixel);
+  if (f->output_data.w32->black_relief.allocated_p)
+    unload_color (f, f->output_data.w32->black_relief.pixel);
+
+  if (FRAME_FACE_CACHE (f))
+    free_frame_faces (f);
+      
   xfree (f->output_data.w32);
-  f->output_data.w32 = 0;
+  f->output_data.w32 = NULL;
+  
   if (f == dpyinfo->w32_focus_frame)
     dpyinfo->w32_focus_frame = 0;
   if (f == dpyinfo->w32_focus_event_frame)
@@ -9340,8 +9903,6 @@ x_destroy_window (f)
   if (f == dpyinfo->w32_highlight_frame)
     dpyinfo->w32_highlight_frame = 0;
 
-  dpyinfo->reference_count--;
-
   if (f == dpyinfo->mouse_face_mouse_frame)
     {
       dpyinfo->mouse_face_beg_row
@@ -9349,10 +9910,26 @@ x_destroy_window (f)
       dpyinfo->mouse_face_end_row
        = dpyinfo->mouse_face_end_col = -1;
       dpyinfo->mouse_face_window = Qnil;
+      dpyinfo->mouse_face_deferred_gc = 0;
+      dpyinfo->mouse_face_mouse_frame = 0;
     }
 
   UNBLOCK_INPUT;
 }
+
+
+/* Destroy the window of frame F.  */
+
+x_destroy_window (f)
+     struct frame *f;
+{
+  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+
+  x_free_frame_resources (f);
+
+  dpyinfo->reference_count--;
+}
+
 \f
 /* Setting window manager hints.  */
 
@@ -9395,7 +9972,113 @@ x_wm_set_icon_position (f, icon_x, icon_y)
 #endif
 }
 
+\f
+/***********************************************************************
+                               Fonts
+ ***********************************************************************/
+
+/* The following functions are listed here to help diff stay in step
+   with xterm.c.  See w32fns.c for definitions.
+
+x_get_font_info (f, font_idx)
+x_list_fonts (f, pattern, size, maxnames)
+
+ */
+
+#if GLYPH_DEBUG
+
+/* Check that FONT is valid on frame F.  It is if it can be found in F's
+   font table.  */
+
+static void
+x_check_font (f, font)
+     struct frame *f;
+     XFontStruct *font;
+{
+  int i;
+  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+
+  xassert (font != NULL);
+
+  for (i = 0; i < dpyinfo->n_fonts; i++)
+    if (dpyinfo->font_table[i].name 
+       && font == dpyinfo->font_table[i].font)
+      break;
+
+  xassert (i < dpyinfo->n_fonts);
+}
+
+#endif /* GLYPH_DEBUG != 0 */
+
+/* Set *W to the minimum width, *H to the minimum font height of FONT.
+   Note: There are (broken) X fonts out there with invalid XFontStruct
+   min_bounds contents.  For example, handa@etl.go.jp reports that
+   "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
+   have font->min_bounds.width == 0.  */
+
+static INLINE void
+x_font_min_bounds (font, w, h)
+     XFontStruct *font;
+     int *w, *h;
+{
+  /*
+   * TODO: Windows does not appear to offer min bound, only
+   * average and maximum width, and maximum height.
+   */
+  *h = FONT_HEIGHT (font);
+  *w = FONT_WIDTH (font);
+}
+
+
+/* Compute the smallest character width and smallest font height over
+   all fonts available on frame F.  Set the members smallest_char_width
+   and smallest_font_height in F's x_display_info structure to
+   the values computed.  Value is non-zero if smallest_font_height or
+   smallest_char_width become smaller than they were before.  */
+
+int
+x_compute_min_glyph_bounds (f)
+     struct frame *f;
+{
+  int i;
+  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+  XFontStruct *font;
+  int old_width = dpyinfo->smallest_char_width;
+  int old_height = dpyinfo->smallest_font_height;
+  
+  dpyinfo->smallest_font_height = 100000;
+  dpyinfo->smallest_char_width = 100000;
+  
+  for (i = 0; i < dpyinfo->n_fonts; ++i)
+    if (dpyinfo->font_table[i].name)
+      {
+       struct font_info *fontp = dpyinfo->font_table + i;
+       int w, h;
+       
+       font = (XFontStruct *) fontp->font;
+       xassert (font != (XFontStruct *) ~0);
+       x_font_min_bounds (font, &w, &h);
+       
+       dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
+       dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
+      }
+
+  xassert (dpyinfo->smallest_char_width > 0
+          && dpyinfo->smallest_font_height > 0);
+
+  return (dpyinfo->n_fonts == 1
+         || dpyinfo->smallest_char_width < old_width
+         || dpyinfo->smallest_font_height < old_height);
+}
+
+/* The following functions are listed here to help diff stay in step
+   with xterm.c.  See w32fns.c for definitions.
 
+x_load_font (f, fontname, size)
+x_query_font (f, fontname)
+x_find_ccl_program (fontp)
+
+*/
 \f
 /***********************************************************************
                            Initialization
@@ -9440,7 +10123,7 @@ w32_initialize_display_info (display_name)
   dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
   dpyinfo->mouse_face_window = Qnil;
 
-  /* NTEMACS_TODO: dpyinfo->gray */
+  /* TODO: dpyinfo->gray */
 
 }
 
@@ -9567,7 +10250,7 @@ x_delete_display (dpyinfo)
     {
       struct w32_palette_entry * pentry = plist;
       plist = plist->next;
-      xfree(pentry);
+      xfree (pentry);
     }
     dpyinfo->color_list = NULL;
     if (dpyinfo->palette)
@@ -9605,6 +10288,7 @@ static struct redisplay_interface w32_redisplay_interface =
   x_update_window_end,
   w32_cursor_to,
   x_flush,
+  x_clear_mouse_face,
   x_get_glyph_overhangs,
   x_fix_overlapping_area
 };
@@ -9617,18 +10301,14 @@ w32_initialize ()
   /* MSVC does not type K&R functions with no arguments correctly, and
      so we must explicitly cast them.  */
   clear_frame_hook = (void (*)(void)) x_clear_frame;
-  ins_del_lines_hook = x_ins_del_lines;
-  change_line_highlight_hook = x_change_line_highlight;
-  delete_glyphs_hook = x_delete_glyphs;
   ring_bell_hook = (void (*)(void)) w32_ring_bell;
-  reset_terminal_modes_hook = (void (*)(void)) w32_reset_terminal_modes;
-  set_terminal_modes_hook = (void (*)(void)) w32_set_terminal_modes;
   update_begin_hook = x_update_begin;
   update_end_hook = x_update_end;
-  set_terminal_window_hook = w32_set_terminal_window;
+
   read_socket_hook = w32_read_socket;
+
   frame_up_to_date_hook = w32_frame_up_to_date;
-  reassert_line_highlight_hook = w32_reassert_line_highlight;
+
   mouse_position_hook = w32_mouse_position;
   frame_rehighlight_hook = w32_frame_rehighlight;
   frame_raise_lower_hook = w32_frame_raise_lower;
@@ -9694,8 +10374,8 @@ w32_initialize ()
 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
 
     /* New proportional scroll bar functions. */
-    LOAD_PROC( SetScrollInfo );
-    LOAD_PROC( GetScrollInfo );
+    LOAD_PROC (SetScrollInfo);
+    LOAD_PROC (GetScrollInfo);
 
 #undef LOAD_PROC
 
@@ -9716,8 +10396,6 @@ w32_initialize ()
 void
 syms_of_w32term ()
 {
-  Lisp_Object codepage;
-
   staticpro (&w32_display_name_list);
   w32_display_name_list = Qnil;
 
@@ -9768,10 +10446,15 @@ NT uses Unicode internally anyway, so this flag will probably have no\n\
 affect on NT machines.");
   w32_enable_unicode_output = 1;
 
-  staticpro (&help_echo);
   help_echo = Qnil;
-  staticpro (&previous_help_echo);
+  staticpro (&help_echo);
+  help_echo_object = Qnil;
+  staticpro (&help_echo_object);
+  help_echo_window = Qnil;
+  staticpro (&help_echo_window);
   previous_help_echo = Qnil;
+  staticpro (&previous_help_echo);
+  help_echo_pos = -1;
 
   DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
     "*Non-nil means draw block cursor as wide as the glyph under it.\n\
@@ -9779,9 +10462,9 @@ For example, if a block cursor is over a tab, it will be drawn as\n\
 wide as that tab on the display.");
   x_stretch_cursor_p = 0;
 
-  DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
+  DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
     "If not nil, Emacs uses toolkit scroll bars.");
-  x_toolkit_scroll_bars_p = 1;
+  Vx_toolkit_scroll_bars = Qt;
 
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;