*** empty log message ***
[bpt/emacs.git] / src / w32term.c
index dff7bf9..6116f9a 100644 (file)
@@ -1,5 +1,6 @@
 /* Implementation of GUI terminal on the Microsoft W32 API.
-   Copyright (C) 1989, 93, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
+   Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
+   Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -14,8 +15,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to the
-Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+along with GNU Emacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
 #include <config.h>
@@ -24,7 +25,6 @@ Boston, MA 02111-1307, USA.  */
 #include <stdlib.h>
 #include "lisp.h"
 #include "charset.h"
-#include "fontset.h"
 #include "blockinput.h"
 
 #include "w32heap.h"
@@ -34,14 +34,17 @@ Boston, MA 02111-1307, USA.  */
 
 #include "systty.h"
 #include "systime.h"
+#include "atimer.h"
 
 #include <ctype.h>
 #include <errno.h>
 #include <setjmp.h>
 #include <sys/stat.h>
 
+#include "keyboard.h"
 #include "frame.h"
 #include "dispextern.h"
+#include "fontset.h"
 #include "termhooks.h"
 #include "termopts.h"
 #include "termchar.h"
@@ -49,7 +52,6 @@ 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"
@@ -89,6 +91,7 @@ enum bitmap_type
 #define zv_height 8
 static unsigned short zv_bits[] = {
    0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00};
+static HBITMAP zv_bmp;
 
 /* An arrow like this: `<-'.  */
 
@@ -96,6 +99,7 @@ static unsigned short zv_bits[] = {
 #define left_height 8
 static unsigned short left_bits[] = {
    0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
+static HBITMAP left_bmp;
 
 /* Right truncation arrow bitmap `->'.  */
 
@@ -103,6 +107,7 @@ static unsigned short left_bits[] = {
 #define right_height 8
 static unsigned short right_bits[] = {
    0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
+static HBITMAP right_bmp;
 
 /* Marker for continued lines.  */
 
@@ -110,6 +115,7 @@ static unsigned short right_bits[] = {
 #define continued_height 8
 static unsigned short continued_bits[] = {
    0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
+static HBITMAP continued_bmp;
 
 /* Marker for continuation lines.  */
 
@@ -117,6 +123,7 @@ static unsigned short continued_bits[] = {
 #define continuation_height 8
 static unsigned short continuation_bits[] = {
    0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
+static HBITMAP continuation_bmp;
 
 /* Overlay arrow bitmap.  */
 
@@ -132,8 +139,8 @@ static unsigned short ov_bits[] = {
 #define ov_height 8
 static unsigned short ov_bits[] = {
    0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
-
 #endif
+static HBITMAP ov_bmp;
 
 extern Lisp_Object Qhelp_echo;
 
@@ -146,6 +153,9 @@ int x_toolkit_scroll_bars_p;
    (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.  */
 
@@ -162,12 +172,16 @@ static int any_help_event_p;
 
 int x_stretch_cursor_p;
 
-#define CP_DEFAULT 1004
-
 extern unsigned int msh_mousewheel;
 
 extern void free_frame_menubar ();
 
+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
@@ -244,6 +258,7 @@ int last_scroll_bar_drag_pos;
 /* Mouse movement. */
 
 /* Where the mouse was last time we reported a mouse event.  */
+
 FRAME_PTR last_mouse_frame;
 static RECT last_mouse_glyph;
 static Lisp_Object last_mouse_press_frame;
@@ -269,21 +284,21 @@ Lisp_Object Vw32_recognize_altgr;
 
    If the last motion event didn't occur in a scroll bar, we set this
    to Qnil, to tell w32_mouse_position to return an ordinary motion event.  */
-Lisp_Object last_mouse_scroll_bar;
-int last_mouse_scroll_bar_pos;
+static Lisp_Object last_mouse_scroll_bar;
+static int last_mouse_scroll_bar_pos;
 
 /* This is a hack.  We would really prefer that w32_mouse_position would
    return the time associated with the position it returns, but there
-   doesn't seem to be any way to wrest the timestamp from the server
+   doesn't seem to be any way to wrest the time-stamp from the server
    along with the position query.  So, we just keep track of the time
    of the last movement we received, and return that in hopes that
    it's somewhat accurate.  */
-Time last_mouse_movement_time;
 
-/* Associative list linking character set strings to Windows codepages. */
-Lisp_Object Vw32_charset_to_codepage_alist;
+static Time last_mouse_movement_time;
+
+/* Incremented by w32_read_socket whenever it really tries to read
+   events.  */
 
-/* Incremented by w32_read_socket whenever it really tries to read events.  */
 #ifdef __STDC__
 static int volatile input_signal_count;
 #else
@@ -294,9 +309,12 @@ 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.  */
+
 extern int extra_keyboard_modifiers;
 
 /* Enumeration for overriding/changing the face to use for drawing
@@ -312,7 +330,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 *,
@@ -361,8 +379,7 @@ static void w32_new_focus_frame P_ ((struct w32_display_info *,
 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 *));
-static int w32_intersect_rectangles P_ ((RECT *, RECT *, RECT *));
+static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
 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 *));
@@ -387,9 +404,14 @@ static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
 static Lisp_Object Qvendor_specific_keysyms;
 
 \f
+/***********************************************************************
+                             Debugging
+ ***********************************************************************/
+
 #if 0
-/* This is a function useful for recording debugging information
-   about the sequence of occurrences in this file.  */
+
+/* This is a function useful for recording debugging information about
+   the sequence of occurrences in this file.  */
 
 struct record 
 {
@@ -444,13 +466,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)
 {
@@ -464,14 +479,6 @@ w32_set_clip_rectangle (HDC hdc, RECT *rect)
     SelectClipRgn (hdc, NULL);
 }
 
-/* Return the struct w32_display_info.  */
-
-struct w32_display_info *
-w32_display_info_for_display ()
-{
-  return (&one_w32_display_info);
-}
-
 
 /* Draw a hollow rectangle at the specified position.  */
 void
@@ -517,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);
 }
 
@@ -572,11 +586,18 @@ x_update_window_begin (w)
       /* Don't do highlighting for mouse motion during the update.  */
       display_info->mouse_face_defer = 1;
 
-      /* If the frame needs to be redrawn,
-        simply forget about any prior mouse highlighting.  */
+      /* If F needs to be redrawn, simply forget about any prior mouse
+        highlighting.  */
       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;
@@ -594,6 +615,7 @@ x_update_window_begin (w)
          if (i < w->desired_matrix->nrows)
            clear_mouse_face (display_info);
        }
+#endif /* 0 */
     }
 
   UNBLOCK_INPUT;
@@ -625,26 +647,46 @@ 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,
@@ -656,6 +698,10 @@ x_update_window_end (w, cursor_on_p)
   updated_window = NULL;
 }
 
+
+/* End update of frame F.  This function is installed as a hook in
+   update_end.  */
+
 static void
 x_update_end (f)
      struct frame *f;
@@ -664,6 +710,7 @@ x_update_end (f)
   FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
 }
 
+
 /* This function is called from various places in xdisp.c whenever a
    complete update has been performed.  The global variable
    updated_window is not available here.  */
@@ -747,7 +794,6 @@ w32_draw_bitmap (w, hdc, row, which)
   Window window = FRAME_W32_WINDOW (f);
   HDC compat_hdc;
   int x, y, wd, h, dy;
-  unsigned short *bits;
   HBITMAP pixmap;
   HBRUSH fg_brush, orig_brush;
   HANDLE horig_obj;
@@ -761,7 +807,7 @@ w32_draw_bitmap (w, hdc, row, which)
     case LEFT_TRUNCATION_BITMAP:
       wd = left_width;
       h = left_height;
-      bits = left_bits;
+      pixmap = left_bmp;
       x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
           - wd
           - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
@@ -770,7 +816,7 @@ w32_draw_bitmap (w, hdc, row, which)
     case OVERLAY_ARROW_BITMAP:
       wd = ov_width;
       h = ov_height;
-      bits = ov_bits;
+      pixmap = ov_bmp;
       x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
           - wd
           - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
@@ -779,7 +825,7 @@ w32_draw_bitmap (w, hdc, row, which)
     case RIGHT_TRUNCATION_BITMAP:
       wd = right_width;
       h = right_height;
-      bits = right_bits;
+      pixmap = right_bmp;
       x = window_box_right (w, -1);
       x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
       break;
@@ -787,7 +833,7 @@ w32_draw_bitmap (w, hdc, row, which)
     case CONTINUED_LINE_BITMAP:
       wd = continued_width;
       h = continued_height;
-      bits = continued_bits;
+      pixmap = continued_bmp;
       x = window_box_right (w, -1);
       x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
       break;
@@ -795,7 +841,7 @@ w32_draw_bitmap (w, hdc, row, which)
     case CONTINUATION_LINE_BITMAP:
       wd = continuation_width;
       h = continuation_height;
-      bits = continuation_bits;
+      pixmap = continuation_bmp;
       x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
           - wd
           - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
@@ -804,7 +850,7 @@ w32_draw_bitmap (w, hdc, row, which)
     case ZV_LINE_BITMAP:
       wd = zv_width;
       h = zv_height;
-      bits = zv_bits;
+      pixmap = zv_bmp;
       x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
           - wd
           - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
@@ -819,26 +865,25 @@ w32_draw_bitmap (w, hdc, row, which)
   y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
   dy = (row->height - h) / 2;
 
-  /* Draw the bitmap.  I believe these small pixmaps can be cached
-     by the server.  */
+  /* Draw the bitmap.  */
   face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
-  pixmap = CreateBitmap (wd, h, 1, 1, bits);
 
   compat_hdc = CreateCompatibleDC (hdc);
   SaveDC (hdc);
-  fg_brush = CreateSolidBrush (FRAME_FOREGROUND_PIXEL (f));
+  fg_brush = CreateSolidBrush (face->foreground);
   orig_brush = SelectObject (hdc, fg_brush);
   horig_obj = SelectObject (compat_hdc, pixmap);
-  SetTextColor (hdc, FRAME_BACKGROUND_PIXEL (f));
-  SetBkColor (hdc, FRAME_FOREGROUND_PIXEL (f));
+  SetTextColor (hdc, face->foreground);
+  SetBkColor (hdc, face->background);
 #if 0 /* From w32bdf.c (which is from Meadow).  */
+  /* Old versions - in case we find a reason to fall back on them.  */
   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);
+#else
+  BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, 0xE20746);
 #endif
   SelectObject (compat_hdc, horig_obj);
   SelectObject (hdc, orig_brush);
-  DeleteObject (pixmap);
   DeleteObject (fg_brush);
   DeleteDC (compat_hdc);
   RestoreDC (hdc, -1);
@@ -943,7 +988,6 @@ x_draw_row_bitmaps (w, row)
 }
 
 \f
-
 /***********************************************************************
                          Line Highlighting
  ***********************************************************************/
@@ -969,24 +1013,25 @@ x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
   abort ();
 }
 
-/* This is used 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 rarely happens).  */
+/* 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
+   rarely happens).  */
 
 static void
 w32_set_terminal_modes (void)
 {
 }
 
-/* This is called when exiting or suspending Emacs.
-   Exiting will make the W32 windows go away, and suspending
-   requires no action.  */
+/* This is called when exiting or suspending Emacs. Exiting will make
+   the W32 windows go away, and suspending requires no action. */
 
 static void
 w32_reset_terminal_modes (void)
 {
 }
 
+
 \f
 /***********************************************************************
                            Output Cursor
@@ -994,6 +1039,7 @@ w32_reset_terminal_modes (void)
 
 /* Set the global variable output_cursor to CURSOR.  All cursor
    positions are relative to updated_window.  */
+
 static void
 set_output_cursor (cursor)
     struct cursor_pos *cursor;
@@ -1043,6 +1089,7 @@ w32_cursor_to (vpos, hpos, y, x)
     }
 }
 
+
 \f
 /***********************************************************************
                           Display Iterator
@@ -1052,12 +1099,15 @@ w32_cursor_to (vpos, hpos, y, x)
 
 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
                                                       struct glyph *,
-                                                      wchar_t *));
+                                                      wchar_t *,
+                                                       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 *,
-                                             wchar_t *, int unicode_p));
-static void x_encode_char P_ ((int, wchar_t *, struct font_info *));
+static XCharStruct *w32_per_char_metric P_ ((XFontStruct *,
+                                             wchar_t *,
+                                             enum w32_char_font_type));
+static enum w32_char_font_type
+  w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
 static void x_append_glyph P_ ((struct it *));
 static void x_append_composite_glyph P_ ((struct it *));
 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
@@ -1080,83 +1130,234 @@ static void x_produce_image_glyph P_ ((struct it *it));
 
 /* 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. If unicode_p is non-zero, use unicode functions,
-   otherwise use ANSI functions.  */
+   metric is returned. */
 
-static INLINE XCharStruct *
-w32_per_char_metric (hdc, font, char2b, unicode_p)
-     HDC hdc;
+static int
+w32_bdf_per_char_metric (font, char2b, dim, pcm)
+     XFontStruct *font;
+     wchar_t *char2b;
+     int dim;
+     XCharStruct * pcm;
+{
+  glyph_metric * bdf_metric;
+  char buf[2];
+
+  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 (bdf_metric)
+    {
+      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;
+}
+
+
+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);
+
+  old_font = SelectObject (hdc, font->hfont);
+
+  if ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
+    {
+      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);
+       }
+    }
+
+  if (!retval)
+    {
+      /* 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);
+      else
+       retval = GetTextExtentPoint32A (hdc, (char*)char2b, 1, &sz);
+
+      if (retval)
+       {
+         pcm->width = sz.cx - font->tm.tmOverhang;
+         pcm->rbearing = sz.cx;
+         pcm->lbearing = 0;
+         pcm->ascent = FONT_BASE (font);
+         pcm->descent = FONT_DESCENT (font);
+       }
+    }
+
+
+  if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
+    {
+      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;
-     int unicode_p;
+     enum w32_char_font_type font_type;
 {
   /* The result metric information.  */
   XCharStruct *pcm;
-  ABC char_widths;
-  SIZE sz;
   BOOL retval;
 
   xassert (font && char2b);
+  xassert (font_type != UNKNOWN_FONT);
 
-  pcm = (XCharStruct *) xmalloc (sizeof (XCharStruct));
+  /* 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];
 
-  if (font->hfont)
-    SelectObject (hdc, font->hfont);
+  pcm = &font->scratch;
 
-  if (unicode_p)
-    retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
+  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 = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
+    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)
     {
-      pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
-      pcm->lbearing = char_widths.abcA;
-      pcm->rbearing = pcm->width - char_widths.abcC;
+      /* 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
     {
-      /* 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). */
-      if (unicode_p)
-          retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
+      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;
 
-      if (retval)
-        {
-          pcm->width = sz.cx;
-          pcm->rbearing = sz.cx;
-          pcm->lbearing = 0;
-        }
+         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
-        {
-          pcm->width = FONT_MAX_WIDTH (font);
-          pcm->rbearing = FONT_MAX_WIDTH (font);
-          pcm->lbearing = 0;
-        }
+       w32_native_per_char_metric (font, &char2b, ANSI_FONT,
+                                   &font->max_bounds);
     }
+}
 
-  pcm->ascent = FONT_BASE (font);
-  pcm->descent = FONT_DESCENT (font);
 
-  return pcm;
+/* Determine if a font is double byte. */
+int w32_font_is_double_byte (XFontStruct *font)
+{
+  return font->double_byte_p;
 }
 
 
 /* Encode CHAR2B using encoding information from FONT_INFO.  CHAR2B is
    the two-byte form of C.  Encoding is returned in *CHAR2B.  */
 
-static INLINE void
-x_encode_char (c, char2b, font_info)
+static INLINE enum w32_char_font_type
+w32_encode_char (c, char2b, font_info, two_byte_p)
      int c;
      wchar_t *char2b;
      struct font_info *font_info;
+     int * two_byte_p;
 {
   int charset = CHAR_CHARSET (c);
   int codepage;
+  int unicode_p = 0;
+
   XFontStruct *font = font_info->font;
 
+  xassert (two_byte_p);
+
+  *two_byte_p = w32_font_is_double_byte (font);
+
   /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
      This may be either a program in a special encoder language or a
      fixed encoding.  */
@@ -1181,16 +1382,10 @@ x_encode_char (c, char2b, font_info)
 
       /* We assume that MSBs are appropriately set/reset by CCL
         program.  */
-      /* NTEMACS_TODO : Use GetFontLanguageInfo to determine if
-         font is double byte. */
-#if 0
-      if (FONT_MAX_BYTE1 (font) == 0)  /* 1-byte font */
-#endif
+      if (!*two_byte_p)        /* 1-byte font */
        *char2b = BUILD_WCHAR_T (0, ccl->reg[1]);
-#if 0
       else
        *char2b = BUILD_WCHAR_T (ccl->reg[1], ccl->reg[2]);
-#endif
     }
   else if (font_info->encoding[charset])
     {
@@ -1225,11 +1420,26 @@ x_encode_char (c, char2b, font_info)
       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_2D_FONT;
+  else if (unicode_p)
+    return UNICODE_FONT;
+  else
+    return ANSI_FONT;
 }
 
 
@@ -1252,12 +1462,8 @@ x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
       /* Unibyte case.  We don't have to encode, but we have to make
         sure to use a face suitable for unibyte.  */
       *char2b = BUILD_WCHAR_T (0, c);
-      
-      if (!FACE_SUITABLE_FOR_CHARSET_P (face, -1))
-       {
-         face_id = FACE_FOR_CHARSET (f, face_id, -1);
-         face = FACE_FROM_ID (f, face_id);
-       }
+      face_id = FACE_FOR_CHAR (f, face, c);
+      face = FACE_FROM_ID (f, face_id);
     }
   else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
     {
@@ -1275,32 +1481,14 @@ x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
        *char2b = BUILD_WCHAR_T (c1, c2);
       else
        *char2b = BUILD_WCHAR_T (0, c1);
-
-      /* Get the face for displaying C.  If `face' is not suitable for
-        charset, get the one that fits.  (This can happen for the
-        translations of a composition where the glyph
-        specifies a face for the first component, but the other
-         components have a different charset.)  */
-      if (!FACE_SUITABLE_FOR_CHARSET_P (face, charset))
-       {
-         face_id = FACE_FOR_CHARSET (f, face_id, charset);
-         face = FACE_FROM_ID (f, face_id);
-       }
   
       /* Maybe encode the character in *CHAR2B.  */
-      if (charset != CHARSET_ASCII)
+      if (face->font != NULL)
        {
          struct font_info *font_info
            = FONT_INFO_FROM_ID (f, face->font_info_id);
          if (font_info)
-           {
-             x_encode_char (c, char2b, font_info);
-#if 0 /* NTEMACS_TODO: Isn't this undoing what we just did?  Investigate. */
-             if (charset == charset_latin_iso8859_1)
-                *char2b = BUILD_WCHAR_T (BYTE1 (*char2b),
-                                         BYTE2 (*char2b) | 0x80);
-#endif
-           }
+             w32_encode_char (c, char2b, font_info, &multibyte_p);
        }
     }
 
@@ -1317,16 +1505,23 @@ x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
    a pointer to a realized face that is ready for display.  */
 
 static INLINE struct face *
-x_get_glyph_face_and_encoding (f, glyph, char2b)
+x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
      struct frame *f;
      struct glyph *glyph;
      wchar_t *char2b;
+     int *two_byte_p;
 {
   struct face *face;
+  int dummy = 0;
 
   xassert (glyph->type == CHAR_GLYPH);
   face = FACE_FROM_ID (f, glyph->face_id);
 
+  if (two_byte_p)
+    *two_byte_p = 0;
+  else
+    two_byte_p = &dummy;
+
   if (!glyph->multibyte_p)
     {
       /* Unibyte case.  We don't have to encode, but we have to make
@@ -1358,12 +1553,8 @@ x_get_glyph_face_and_encoding (f, glyph, char2b)
            = FONT_INFO_FROM_ID (f, face->font_info_id);
          if (font_info)
            {
-             x_encode_char (glyph->u.ch, char2b, font_info);
-#if 0 /* NTEMACS_TODO: Isn't this undoing what we just did?  Investigate. */
-             if (charset == charset_latin_iso8859_1)
-               *char2b = BUILD_WCHAR_T (BYTE1 (*char2b),
-                                         BYTE2 (*char2b) | 0x80);
-#endif
+             glyph->w32_font_type
+                = w32_encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
            }
        }
     }
@@ -1391,23 +1582,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];
     }
 }
@@ -1427,23 +1616,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];
     }
 }
@@ -1491,7 +1678,7 @@ x_produce_image_glyph (it)
   PREPARE_FACE_FOR_DISPLAY (it->f, face);
   prepare_image_for_display (it->f, img);
 
-  it->ascent = it->phys_ascent = IMAGE_ASCENT (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;
 
@@ -1518,16 +1705,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];
        }
     }
@@ -1554,17 +1745,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];
     }
 }
@@ -1742,9 +1937,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
@@ -1754,35 +1950,58 @@ static void
 x_produce_glyphs (it)
      struct it *it;
 {
+  it->glyph_not_available_p = 0;
+
   if (it->what == IT_CHARACTER)
     {
       wchar_t char2b;
       XFontStruct *font;
-      struct face *face;
+      struct face *face = FACE_FROM_ID (it->f, it->face_id);
       XCharStruct *pcm;
-     int font_not_found_p;
+      int font_not_found_p;
       struct font_info *font_info;
       int boff;                 /* baseline offset */
-      HDC hdc;
-
-      hdc = get_frame_dc (it->f);
-
-      /* Maybe translate single-byte characters to multibyte.  */
+      /* 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.  */
       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->charset = CHAR_CHARSET (it->char_to_display);
-       }
+      if (!ASCII_BYTE_P (it->c))
+        {
+          if (unibyte_display_via_language_environment
+              && SINGLE_BYTE_CHAR_P (it->c)
+              && (it->c >= 0240
+                  || !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);
+           }
+         else if (!SINGLE_BYTE_CHAR_P (it->c)
+                  && !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);
+           }
+        }
       
-      /* Get face and font to use.  Encode IT->char_to_display.  */
-      face = x_get_char_face_and_encoding (it->f, it->char_to_display,
-                                          it->face_id, &char2b,
-                                          it->multibyte_p);
+      /* Get font to use.  Encode IT->char_to_display.  */
+      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.  */
@@ -1801,9 +2020,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))
        {
@@ -1812,13 +2028,25 @@ x_produce_glyphs (it)
 
          it->nglyphs = 1;
 
-          pcm = w32_per_char_metric (hdc, font, &char2b, 0);
+          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;
-          it->phys_ascent = pcm->ascent + boff;
-          it->phys_descent = pcm->descent - boff;
-         it->pixel_width = pcm->width;
 
+          if (pcm)
+            {
+              it->phys_ascent = pcm->ascent + boff;
+              it->phys_descent = pcm->descent - boff;
+              it->pixel_width = pcm->width;
+            }
+          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);
+            }
+          
          /* If this is a space inside a region of text with
             `space-width' property, change its width.  */
          stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
@@ -1866,8 +2094,7 @@ x_produce_glyphs (it)
              /* If characters with lbearing or rbearing are displayed
                 in this line, record that fact in a flag of the
                 glyph row.  This is used to optimize X output code.  */
-             if (pcm->lbearing < 0
-                 || pcm->rbearing > pcm->width)
+             if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
                it->glyph_row->contains_overlapping_glyphs_p = 1;
            }
        }
@@ -1889,11 +2116,15 @@ x_produce_glyphs (it)
       else if (it->char_to_display == '\t')
        {
          int tab_width = it->tab_width * CANON_X_UNIT (it->f);
-         int x = (it->current_x
-                  - it->prompt_width
-                  + it->continuation_lines_width);
+         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;
@@ -1914,33 +2145,40 @@ x_produce_glyphs (it)
              default font and calculate the width of the character
              from the charset width; this is what old redisplay code
              did.  */
-          if (font_not_found_p)
-            {
-              wchar_t dummy = BUILD_WCHAR_T (0, 'X');
-
-              /* Get some metrics for the default font.  */
-              pcm = w32_per_char_metric (hdc, font, &dummy, 0);
+          enum w32_char_font_type type;
 
-              /* Ignore the width obtained above, and use the average
-                 width of a character in the default font. */
-              it->pixel_width = FONT_WIDTH (font)
-                * CHARSET_WIDTH (it->charset);
-            }
+          if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (it->c)) == 1)
+            type = BDF_1D_FONT;
+          else if (font->bdf)
+            type = BDF_2D_FONT;
           else
-            {
-              pcm = w32_per_char_metric (hdc, font, &char2b, 1);
-              it->pixel_width = pcm->width;
-            }
+            type = UNICODE_FONT;
 
+          pcm = w32_per_char_metric (font, &char2b, type);
+
+         if (font_not_found_p || !pcm)
+           {
+             int charset = CHAR_CHARSET (it->char_to_display);
+
+             it->glyph_not_available_p = 1;
+             it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
+                                * CHARSET_WIDTH (charset));
+             it->phys_ascent = FONT_BASE (font) + boff;
+             it->phys_descent = FONT_DESCENT (font) - boff;
+           }
+         else
+           {
+             it->pixel_width = pcm->width;
+              it->phys_ascent = pcm->ascent + boff;
+              it->phys_descent = pcm->descent - boff;
+              if (it->glyph_row
+                  && (pcm->lbearing < 0
+                      || pcm->rbearing > pcm->width))
+                it->glyph_row->contains_overlapping_glyphs_p = 1;
+            }
           it->nglyphs = 1;
           it->ascent = FONT_BASE (font) + boff;
           it->descent = FONT_DESCENT (font) - boff;
-          it->phys_ascent = pcm->ascent + boff;
-          it->phys_descent = pcm->descent - boff;
-          if (it->glyph_row
-              && (pcm->lbearing < 0
-                  || pcm->rbearing > pcm->width))
-            it->glyph_row->contains_overlapping_glyphs_p = 1;
 
          if (face->box != FACE_NO_BOX)
            {
@@ -1964,16 +2202,15 @@ x_produce_glyphs (it)
          if (it->glyph_row)
            x_append_glyph (it);
        }
-      release_frame_dc (it->f, hdc);
+      it->multibyte_p = saved_multibyte_p;
     }
   else if (it->what == IT_COMPOSITION)
     {
-#if 0 /* NTEMACS_TODO: Composite glyphs.  */
       /* Note: A composition is represented as one glyph in the
         glyph matrix.  There are no padding glyphs.  */
-      XChar2b char2b;
+      wchar_t char2b;
       XFontStruct *font;
-      struct face *face;
+      struct face *face = FACE_FROM_ID (it->f, it->face_id);
       XCharStruct *pcm;
       int font_not_found_p;
       struct font_info *font_info;
@@ -1989,13 +2226,13 @@ x_produce_glyphs (it)
                  && !NILP (Vnonascii_translation_table))))
        {
          it->char_to_display = unibyte_char_to_multibyte (it->c);
-         it->charset = CHAR_CHARSET (it->char_to_display);
        }
-      
+
       /* Get face and font to use.  Encode IT->char_to_display.  */
-      face = x_get_char_face_and_encoding (it->f, it->char_to_display,
-                                          it->face_id, &char2b,
-                                          it->multibyte_p);
+      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.  */
@@ -2003,7 +2240,7 @@ x_produce_glyphs (it)
       if (font_not_found_p)
        {
          font = FRAME_FONT (it->f);
-         boff = it->f->output_data.x->baseline_offset;
+         boff = it->f->output_data.w32->baseline_offset;
          font_info = NULL;
        }
       else
@@ -2033,20 +2270,42 @@ x_produce_glyphs (it)
             this composition (adjusted by baseline offset).  Ascent
             and descent of overall glyphs should not be less than
             them respectively.  */
-         int font_ascent = font->ascent + boff;
-         int font_descent = font->descent - boff;
+         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;
+         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.  */
-         pcm = x_per_char_metric (font, &char2b);
+         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;
-         rightmost = pcm->width;
-         lowest = - pcm->descent + boff;
-         highest = pcm->ascent + boff;
+         
          if (font_info
              && font_info->default_ascent
              && CHAR_TABLE_P (Vuse_default_ascent)
@@ -2065,15 +2324,16 @@ x_produce_glyphs (it)
            {
              int left, right, btm, top;
              int ch = COMPOSITION_GLYPH (cmp, i);
+             int face_id = FACE_FOR_CHAR (it->f, face, ch);
 
-             face = x_get_char_face_and_encoding (it->f, ch,
-                                                  it->face_id, &char2b,
-                                                  it->multibyte_p);
+             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.x->baseline_offset;
+                 boff = it->f->output_data.w32->baseline_offset;
                  font_info = NULL;
                }
              else
@@ -2085,27 +2345,45 @@ x_produce_glyphs (it)
                    boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
                }
 
-             pcm = x_per_char_metric (font, &char2b);
+              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 - pcm->width) / 2;
-                 btm = - pcm->descent + boff;
+                 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 (- pcm->descent
-                         >= font_info->relative_compose)
+                     if (- descent >= font_info->relative_compose)
                        /* One extra pixel between two glyphs.  */
                        btm = highest + 1;
-                     else if (pcm->ascent <= 0)
+                     else if (ascent <= 0)
                        /* One extra pixel between two glyphs.  */
-                       btm = lowest - 1 - pcm->ascent - pcm->descent;
+                       btm = lowest - 1 - ascent - descent;
                    }
                }
              else
@@ -2134,23 +2412,23 @@ x_produce_glyphs (it)
 
                  left = (leftmost
                          + grefx * (rightmost - leftmost) / 2
-                         - nrefx * pcm->width / 2);
+                         - nrefx * width / 2);
                  btm = ((grefy == 0 ? highest
                          : grefy == 1 ? 0
                          : grefy == 2 ? lowest
                          : (highest + lowest) / 2)
-                        - (nrefy == 0 ? pcm->ascent + pcm->descent
-                           : nrefy == 1 ? pcm->descent - boff
+                        - (nrefy == 0 ? ascent + descent
+                           : nrefy == 1 ? descent - boff
                            : nrefy == 2 ? 0
-                           : (pcm->ascent + pcm->descent) / 2));
+                           : (ascent + descent) / 2));
                }
 
              cmp->offsets[i * 2] = left;
-             cmp->offsets[i * 2 + 1] = btm + pcm->descent;
+             cmp->offsets[i * 2 + 1] = btm + descent;
 
              /* Update the bounding box of the overall glyphs. */
-             right = left + pcm->width;
-             top = btm + pcm->descent + pcm->ascent;
+             right = left + width;
+             top = btm + descent + ascent;
              if (left < leftmost)
                leftmost = left;
              if (right > rightmost)
@@ -2205,7 +2483,6 @@ x_produce_glyphs (it)
   
       if (it->glyph_row)
        x_append_composite_glyph (it);
-#endif
     }
   else if (it->what == IT_IMAGE)
     x_produce_image_glyph (it);
@@ -2217,6 +2494,8 @@ x_produce_glyphs (it)
   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);
   it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
@@ -2232,7 +2511,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.  */
@@ -2240,50 +2519,18 @@ 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
-/* Get the Windows codepage corresponding to the specified font.  The
-   charset info in the font name is used to look up
-   w32-charset-to-codepage-alist.  */
-int 
-w32_codepage_for_font (char *fontname)
-{
-  Lisp_Object codepage;
-  char charset_str[20], *charset, *end;
-
-  /* Extract charset part of font string.  */
-  if (sscanf (fontname,
-              "-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%19s",
-              charset_str) == EOF)
-    return CP_DEFAULT;
-
-  /* Remove leading "*-".  */
-  if (strncmp ("*-", charset_str, 2) == 0)
-    charset = charset_str + 2;
-  else
-    charset = charset_str;
-
-  /* Stop match at wildcard (including preceding '-'). */
-  if (end = strchr (charset, '*'))
-      {
-        if (end > charset && *(end-1) == '-')
-          end--;
-        *end = '\0';
-      }
-
-  codepage = Fcdr (Fassoc (build_string(charset),
-                           Vw32_charset_to_codepage_alist));
-
-  if (INTEGERP (codepage))
-    return XINT (codepage);
-  else
-    return CP_DEFAULT;
-}
 
 BOOL 
 w32_use_unicode_for_codepage (codepage)
@@ -2291,7 +2538,8 @@ w32_use_unicode_for_codepage (codepage)
 {
   /* If the current codepage is supported, use Unicode for output. */
   return (w32_enable_unicode_output
-          && codepage != CP_DEFAULT && IsValidCodePage (codepage));
+          && codepage != CP_8BIT
+          && (codepage == CP_UNICODE || IsValidCodePage (codepage)));
 }
 
 \f
@@ -2355,9 +2603,6 @@ struct glyph_string
   wchar_t *char2b;
   int nchars;
 
-  /* Character set of this glyph string.  */
-  int charset;
-
   /* A face-override for drawing cursors, mouse face and similar.  */
   enum draw_glyphs_face hl;
 
@@ -2420,20 +2665,20 @@ struct glyph_string
 };
 
 
-/* Encapsulate the different ways of printing text under W32.  */
+/* 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;
      int nchars;
 {
-  int charset_dim = CHARSET_DIMENSION (s->charset);
-
+  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);
-  else if (s->two_byte_p)
+                     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
     ExtTextOut (s->hdc, x, y, 0, NULL, (char *) chars,
@@ -2495,8 +2740,6 @@ static void x_draw_glyph_string_background P_ ((struct glyph_string *,
                                                int));
 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
-static void x_draw_glyph_string_underline P_ ((struct glyph_string *));
-static void x_draw_glyph_string_underline P_ ((struct glyph_string *));
 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
 static void x_draw_glyph_string  P_ ((struct glyph_string *));
 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
@@ -2505,7 +2748,7 @@ static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
 static void w32_get_glyph_overhangs P_ ((HDC hdc, struct glyph *,
                                          struct frame *,
-                                         int *, int *, int));
+                                         int *, int *));
 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
 static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
 static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
@@ -2640,10 +2883,12 @@ x_set_mouse_face_gc (s)
      struct glyph_string *s;
 {     
   int face_id;
+  struct face *face;
 
   /* What face has to be used for the mouse face?  */
   face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
-  face_id = FACE_FOR_CHARSET (s->f, face_id, s->charset);
+  face = FACE_FROM_ID (s->f, face_id);
+  face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
   s->face = FACE_FROM_ID (s->f, face_id);
   PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
 
@@ -2686,7 +2931,6 @@ x_set_mode_line_face_gc (s)
      struct glyph_string *s;
 {     
   s->gc = s->face->gc;
-  xassert (s->gc != 0);
 }
 
 
@@ -2698,6 +2942,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;
@@ -2826,16 +3072,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. */
 }
 
 
@@ -2877,11 +3116,11 @@ x_compute_overhangs_and_x (s, x, backward_p)
    assumed to be zero.  */
 
 static void
-w32_get_glyph_overhangs (hdc, glyph, f, left, right, unicode_p)
+w32_get_glyph_overhangs (hdc, glyph, f, left, right)
      HDC hdc;
      struct glyph *glyph;
      struct frame *f;
-     int *left, *right, unicode_p;
+     int *left, *right;
 {
   int c;
 
@@ -2891,17 +3130,16 @@ w32_get_glyph_overhangs (hdc, glyph, f, left, right, unicode_p)
     {
       XFontStruct *font;
       struct face *face;
-      struct font_info *font_info;
       wchar_t char2b;
-      
-      face = x_get_glyph_face_and_encoding (f, glyph, &char2b);
+      XCharStruct *pcm;
+
+      face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
       font = face->font;
-      font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
-      if (font)
-       {
-         XCharStruct *pcm = w32_per_char_metric (hdc, font, &char2b,
-                                                  unicode_p);
 
+      if (font
+          && (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)
@@ -2918,7 +3156,8 @@ x_get_glyph_overhangs (glyph, f, left, right)
      int *left, *right;
 {
   HDC hdc = get_frame_dc (f);
-  w32_get_glyph_overhangs (hdc, glyph, f, left, right, glyph->multibyte_p);
+  /* Convert to unicode! */
+  w32_get_glyph_overhangs (hdc, glyph, f, left, right);
   release_frame_dc (f, hdc);
 }
 
@@ -2968,8 +3207,7 @@ x_left_overwriting (s)
   for (i = first - 1; i >= 0; --i)
     {
       int left, right;
-      w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left,
-                               &right, s->two_byte_p);
+      w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left, &right);
       if (x + right > 0)
        k = i;
       x -= glyphs[i].pixel_width;
@@ -3024,8 +3262,7 @@ x_right_overwriting (s)
   for (i = first; i < end; ++i)
     {
       int left, right;
-      w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left,
-                               &right, s->two_byte_p);
+      w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left, &right);
       if (x - left < 0)
        k = i;
       x += glyphs[i].pixel_width;
@@ -3078,7 +3315,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.  */
@@ -3095,6 +3332,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,
@@ -3113,6 +3351,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.  */
@@ -3132,7 +3371,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. */
@@ -3163,6 +3402,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.  */
@@ -3172,6 +3413,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.  */
@@ -3191,6 +3433,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)
@@ -3202,12 +3447,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
@@ -3223,17 +3485,50 @@ 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))));
 
+  /* TODO: Map to palette and retry with delta if same? */
+  /* TODO: Free colors (if using palette)? */
+
   if (new == *color)
     return 0;
 
@@ -3265,6 +3560,8 @@ 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);
 
+  /* TODO: Free colors (if using palette)? */
+
   /* Allocate new color.  */
   xgcv.foreground = default_pixel;
   pixel = background;
@@ -3276,7 +3573,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
@@ -3333,9 +3630,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);
 
@@ -3359,9 +3656,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);
   
@@ -3406,24 +3704,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);
@@ -3494,7 +3792,7 @@ x_draw_image_foreground (s)
      struct glyph_string *s;
 {
   int x;
-  int y = s->ybase - IMAGE_ASCENT (s->img);
+  int y = s->ybase - image_ascent (s->img, s->face);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
@@ -3516,7 +3814,7 @@ x_draw_image_foreground (s)
 
   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
@@ -3540,7 +3838,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);
        }
@@ -3551,6 +3849,7 @@ 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);
@@ -3575,6 +3874,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
@@ -3595,8 +3895,8 @@ x_draw_image_relief (s)
   int x0, y0, x1, y1, thick, raised_p;
   RECT r;
   int x;
-  int y = s->ybase - IMAGE_ASCENT (s->img);
-  
+  int y = s->ybase - image_ascent (s->img, s->face);
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
   if (s->face->box != FACE_NO_BOX
@@ -3646,7 +3946,7 @@ w32_draw_image_foreground_1 (s, pixmap)
   HDC hdc = CreateCompatibleDC (s->hdc);
   HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
   int x;
-  int y = s->ybase - s->y - IMAGE_ASCENT (s->img);
+  int y = s->ybase - s->y - image_ascent (s->img, s->face);
 
   /* If first glyph of S has a left box line, start drawing it to the
      right of that line.  */
@@ -3666,7 +3966,7 @@ w32_draw_image_foreground_1 (s, pixmap)
 
   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
@@ -3738,7 +4038,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.  */
@@ -3784,7 +4084,7 @@ x_draw_image_glyph_string (s)
   s->stippled_p = s->face->stipple != 0;
   if (height > s->img->height
       || margin
-#if 0 /* NTEMACS_TODO: image mask */
+#if 0 /* TODO: image mask */
       || s->img->mask
 #endif
       || s->img->pixmap == 0
@@ -3796,7 +4096,7 @@ 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
@@ -3836,10 +4136,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;
@@ -3914,7 +4210,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.  */
@@ -3991,7 +4287,8 @@ x_draw_glyph_string (s)
   if (!s->for_overlaps_p)
     {
       /* Draw underline.  */
-      if (s->face->underline_p && (!s->font->bdf && !s->font->tm.tmUnderlined))
+      if (s->face->underline_p
+          && (s->font->bdf || !s->font->tm.tmUnderlined))
         {
           unsigned long h = 1;
           unsigned long dy = s->height - h;
@@ -4026,7 +4323,8 @@ x_draw_glyph_string (s)
         }
 
       /* Draw strike-through.  */
-      if (s->face->strike_through_p && (!s->font->bdf &&!s->font->tm.tmStruckOut))
+      if (s->face->strike_through_p
+          && (s->font->bdf || !s->font->tm.tmStruckOut))
         {
           unsigned long h = 1;
           unsigned long dy = (s->height - h) / 2;
@@ -4131,28 +4429,32 @@ x_fill_glyph_string (s, face_id, start, end, overlaps_p)
 {
   struct glyph *glyph, *last;
   int voffset;
+  int glyph_not_available_p;
 
   xassert (s->f == XFRAME (s->w->frame));
   xassert (s->nchars == 0);
   xassert (start >= 0 && end > start);
 
   s->for_overlaps_p = overlaps_p;
-
   glyph = s->row->glyphs[s->area] + start;
   last = s->row->glyphs[s->area] + end;
   voffset = glyph->voffset;
-  
+
+  glyph_not_available_p = glyph->glyph_not_available_p;
+
   while (glyph < last
         && glyph->type == CHAR_GLYPH
         && glyph->voffset == voffset
-        /* Same face id implies same charset, nowadays.  */
-        && glyph->face_id == face_id)
+        /* Same face id implies same font, nowadays.  */
+        && glyph->face_id == face_id
+         && glyph->glyph_not_available_p == glyph_not_available_p)
     {
+      int two_byte_p;
+
       s->face = x_get_glyph_face_and_encoding (s->f, glyph,
-                                              s->char2b + s->nchars);
-      if (BYTE2(s->char2b[s->nchars]) != 0)
-       s->two_byte_p = 1;
-      
+                                              s->char2b + s->nchars,
+                                               &two_byte_p);
+      s->two_byte_p = two_byte_p;
       ++s->nchars;
       xassert (s->nchars <= end - start);
       s->width += glyph->pixel_width;
@@ -4166,7 +4468,7 @@ x_fill_glyph_string (s, face_id, start, end, overlaps_p)
      but record the fact that we couldn't load it in
      S->font_not_found_p so that we can draw rectangles for the
      characters of the glyph string.  */
-  if (s->font == NULL)
+  if (s->font == NULL || glyph_not_available_p)
     {
       s->font_not_found_p = 1;
       s->font = FRAME_FONT (s->f);
@@ -4198,19 +4500,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];
 }
 
 
@@ -4298,9 +4629,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)
@@ -4339,17 +4669,16 @@ 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;                              \
-        charset = CHAR_CHARSET (c);                                       \
         face_id = (ROW)->glyphs[AREA][START].face_id;                     \
+                                                                          \
         s = (struct glyph_string *) alloca (sizeof *s);                   \
         char2b = (wchar_t *) alloca ((END - START) * sizeof *char2b);     \
         w32_init_glyph_string (s, hdc, char2b, W, ROW, AREA, START, HL);  \
         x_append_glyph_string (&HEAD, &TAIL, s);                          \
-        s->charset = charset;                                             \
         s->x = (X);                                                       \
         START = x_fill_glyph_string (s, face_id, START, END,              \
                                           OVERLAPS_P);                    \
@@ -4370,6 +4699,7 @@ x_set_glyph_string_background_width (s, start, last_x)
   do {                                                                   \
     int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id;                    \
     int face_id = (ROW)->glyphs[AREA][START].face_id;                    \
+    struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id);          \
     struct composition *cmp = composition_table[cmp_id];                 \
     int glyph_len = cmp->glyph_len;                                      \
     wchar_t *char2b;                                                     \
@@ -4377,14 +4707,17 @@ x_set_glyph_string_background_width (s, start, last_x)
     struct glyph_string *first_s = NULL;                                 \
     int n;                                                               \
                                                                          \
+    base_face = base_face->ascii_face;                                   \
     char2b = (wchar_t *) alloca ((sizeof *char2b) * glyph_len);                  \
     faces = (struct face **) alloca ((sizeof *faces) * glyph_len);       \
     /* At first, fill in `char2b' and `faces'.  */                       \
     for (n = 0; n < glyph_len; n++)                                      \
       {                                                                          \
        int c = COMPOSITION_GLYPH (cmp, n);                               \
-       faces[n] = x_get_char_face_and_encoding (XFRAME (w->frame), c,    \
-                                                face_id, char2b + n, 1); \
+       int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
+       faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id);        \
+       x_get_char_face_and_encoding (XFRAME (w->frame), c,               \
+                                     this_face_id, char2b + n, 1);       \
       }                                                                          \
                                                                          \
     /* Make glyph_strings for each glyph sequence that is drawable by    \
@@ -4396,7 +4729,6 @@ x_set_glyph_string_background_width (s, start, last_x)
        x_append_glyph_string (&(HEAD), &(TAIL), s);                      \
        s->cmp = cmp;                                                     \
        s->gidx = n;                                                      \
-       s->charset = 0;                                                   \
        s->x = (X);                                                       \
                                                                          \
        if (n == 0)                                                       \
@@ -4409,6 +4741,7 @@ x_set_glyph_string_background_width (s, start, last_x)
     s = first_s;                                                         \
   } while (0)
 
+
 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
    of AREA of glyph row ROW on window W between indices START and END.
    HL overrides the face for drawing glyph strings, e.g. it is
@@ -4503,8 +4836,10 @@ 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)
@@ -4514,10 +4849,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);
 
@@ -4551,7 +4885,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
   i = start;
   BUILD_GLYPH_STRINGS (hdc, w, row, area, i, end, head, tail, hl, x, last_x,
                        overlaps_p);
-
   if (tail)
     x_reached = tail->x + tail->background_width;
   else
@@ -4560,7 +4893,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;
@@ -4601,7 +4934,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
          BUILD_GLYPH_STRINGS (hdc, w, row, area, i, start, h, t,
                               DRAW_NORMAL_TEXT, dummy_x, last_x,
                                overlaps_p);
-
          for (s = h; s; s = s->next)
            s->background_filled_p = 1;
          if (real_start)
@@ -4620,7 +4952,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
          BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
                               DRAW_NORMAL_TEXT, x, last_x,
                                overlaps_p);
-
          x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
          x_append_glyph_string_lists (&head, &tail, h, t);
          if (real_end)
@@ -4638,7 +4969,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
          BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
                               DRAW_NORMAL_TEXT, x, last_x,
                                overlaps_p);
-
          for (s = h; s; s = s->next)
            s->background_filled_p = 1;
          x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
@@ -5043,6 +5373,7 @@ x_scroll_run (w, run)
   release_frame_dc (f, hdc);
 }
 
+
 \f
 /***********************************************************************
                           Exposure Events
@@ -5109,7 +5440,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);
     }
 }
@@ -5151,7 +5482,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);
        }
 
@@ -5170,11 +5501,10 @@ 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;
+  int first_x, start_x, 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.
@@ -5195,6 +5525,18 @@ expose_area (w, row, r, area)
                   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)
@@ -5212,10 +5554,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,
@@ -5269,7 +5611,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;
@@ -5354,57 +5696,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;
-  
-  /* Arrange so that left 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)
@@ -5420,14 +5711,13 @@ frame_unhighlight (f)
   x_update_cursor (f, 1);
 }
 
-
 /* The focus has changed.  Update the frames as necessary to reflect
    the new situation.  Note that we can't change the selected frame
    here, because the Lisp code we are interrupting might become confused.
    Each event gets marked with the frame in which it occurred, so the
    Lisp code can tell when the switch took place by examining the events.  */
 
-void
+static void
 x_new_focus_frame (dpyinfo, frame)
      struct w32_display_info *dpyinfo;
      struct frame *frame;
@@ -5463,11 +5753,12 @@ x_mouse_leave (dpyinfo)
 
 /* The focus has changed, or we have redirected a frame's focus to
    another frame (this happens when a frame uses a surrogate
-   minibuffer frame).  Shift the highlight as appropriate.
+   mini-buffer frame).  Shift the highlight as appropriate.
 
    The FRAME argument doesn't necessarily have anything to do with which
-   frame is being highlighted or unhighlighted; we only use it to find
-   the appropriate display info.  */
+   frame is being highlighted or un-highlighted; we only use it to find
+   the appropriate X display info.  */
+
 static void
 w32_frame_rehighlight (frame)
      struct frame *frame;
@@ -5517,18 +5808,20 @@ x_get_keysym_name (keysym)
   static char value[100];
 
   BLOCK_INPUT;
-  GetKeyNameText(keysym, value, 100);
+  GetKeyNameText (keysym, value, 100);
   UNBLOCK_INPUT;
 
   return value;
 }
+
+
 \f
 /* Mouse clicks and mouse movement.  Rah.  */
 
-/* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
-   glyph co-ordinates in (*X, *Y).  Set *BOUNDS to the rectangle
-   that the glyph at X, Y occupies, if BOUNDS != 0.
-   If NOCLIP is nonzero, do not force the value into range.  */
+/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
+   co-ordinates in (*X, *Y).  Set *BOUNDS to the rectangle that the
+   glyph at X, Y occupies, if BOUNDS != 0.  If NOCLIP is non-zero, do
+   not force the value into range.  */
 
 void
 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
@@ -5549,7 +5842,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;
 
@@ -5560,7 +5853,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;
     }
 
@@ -5568,8 +5861,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;
@@ -5688,7 +5981,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;
@@ -5709,16 +6002,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;
@@ -5731,13 +6022,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;
@@ -5785,6 +6078,8 @@ construct_drag_n_drop (result, msg, f)
 
   XSETFRAME (frame, f);
   result->frame_or_window = Fcons (frame, files);
+  result->arg = Qnil;
+  return Qnil;
 }
 
 \f
@@ -5829,6 +6124,7 @@ note_mouse_movement (frame, msg)
 }
 
 /* This is used for debugging, to turn off note_mouse_highlight.  */
+
 int disable_mouse_highlight;
 
 
@@ -5852,7 +6148,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.  */
@@ -5997,29 +6293,36 @@ note_mode_line_highlight (w, x, mode_line_p)
             setting the global variable help_echo to the help string.  */
          help = Fget_text_property (make_number (glyph->charpos),
                                     Qhelp_echo, glyph->object);
-         if (STRINGP (help))
-           help_echo = help;
+         if (!NILP (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;
        }
     }
-#if 0 /* NTEMACS_TODO: mouse cursor */
+
+#if 0 /* TODO: mouse cursor */
   XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
 #endif
 }
 
-/* Take proper action when the mouse has moved to position X, Y on frame F
-   as regards highlighting characters that have mouse-face properties.
-   Also dehighlighting chars where the mouse was before.
+
+/* Take proper action when the mouse has moved to position X, Y on
+   frame F as regards highlighting characters that have mouse-face
+   properties.  Also de-highlighting chars where the mouse was before.
    X and Y can be negative or out of range.  */
 
 static void
 note_mouse_highlight (f, x, y)
-     FRAME_PTR f;
+     struct frame *f;
      int x, y;
 {
   struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
@@ -6031,7 +6334,8 @@ note_mouse_highlight (f, x, y)
   if (popup_activated ())
     return;
 
-  if (disable_mouse_highlight)
+  if (disable_mouse_highlight
+      || !f->glyphs_initialized_p)
     return;
 
   dpyinfo->mouse_face_mouse_x = x;
@@ -6076,7 +6380,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);
@@ -6084,11 +6391,12 @@ note_mouse_highlight (f, x, y)
 
   /* Are we in a window whose display is up to date?
      And verify the buffer's text has not changed.  */
-  if (/* Within the text portion of the window.  */
+  if (/* Within text portion of the window.  */
       portion == 0
       && EQ (w->window_end_valid, w->buffer)
-      && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer))
-      && w->last_overlay_modified == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))
+      && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
+      && (XFASTINT (w->last_overlay_modified)
+         == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
     {
       int hpos, vpos, pos, i, area;
       struct glyph *glyph;
@@ -6137,14 +6445,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.  */
@@ -6162,7 +6471,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))
@@ -6248,26 +6557,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 && !STRINGP (help); ++i)
-           help = Foverlay_get (overlay_vec[i], Qhelp_echo); 
-           
-         /* Try text properties.  */
-         if (!STRINGP (help)
-             && ((STRINGP (glyph->object)
+         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 (STRINGP (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;
@@ -6277,7 +6603,6 @@ note_mouse_highlight (f, x, y)
     }
 }
 
-\f
 static void
 redo_mouse_highlight ()
 {
@@ -6307,7 +6632,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.
@@ -6330,7 +6655,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;
 
@@ -6349,7 +6674,7 @@ x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
 }
 
 
-/* Handle mouse button event on the tool_bar of frame F, at
+/* Handle mouse button event on the tool-bar of frame F, at
    frame-relative coordinates X/Y.  EVENT_TYPE is either ButtionPress
    or ButtonRelase.  */
 
@@ -6372,8 +6697,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;
   
@@ -6393,16 +6717,17 @@ 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;
-      event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
+      event.frame_or_window = frame;
+      event.arg = frame;
       kbd_buffer_store_event (&event);
 
       event.kind = TOOL_BAR_EVENT;
-      event.frame_or_window = Fcons (frame, key);
+      event.frame_or_window = frame;
+      event.arg = key;
       event.modifiers = button_event->modifiers;
       kbd_buffer_store_event (&event);
       last_tool_bar_item = -1;
@@ -6410,7 +6735,7 @@ w32_handle_tool_bar_click (f, button_event)
 }
 
 
-/* Possibly highlight a tool_bar item on frame F when mouse moves to
+/* Possibly highlight a tool-bar item on frame F when mouse moves to
    tool-bar window-relative coordinates X/Y.  Called from
    note_mouse_highlight.  */
 
@@ -6464,8 +6789,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
@@ -6497,13 +6821,14 @@ 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]);
-  if (!STRINGP (help_echo))
-    help_echo = (XVECTOR (f->current_tool_bar_items)
-                ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
+  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 = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
 }
 
+
 \f
 /* Find the glyph matrix position of buffer position POS in window W.
    *HPOS, *VPOS, *X, and *Y are set to the positions found.  W's
@@ -6550,6 +6875,9 @@ fast_find_position (w, pos, hpos, vpos, x, y)
           best_row_vpos = row_vpos;
         }
 
+      if (row->y + row->height >= yb)
+        break;
+
       ++row;
       ++row_vpos;
     }
@@ -6667,8 +6995,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.  */
@@ -6680,7 +7011,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),
@@ -6695,9 +7026,8 @@ show_mouse_face (dpyinfo, draw)
   ;
 }
 
-
 /* Clear out the mouse-highlighted active region.
-   Redraw it unhighlighted first.  */
+   Redraw it un-highlighted first.  */
 
 void
 clear_mouse_face (dpyinfo)
@@ -6714,6 +7044,27 @@ clear_mouse_face (dpyinfo)
   dpyinfo->mouse_face_window = Qnil;
 }
 
+
+/* 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.  */
 
@@ -6733,7 +7084,7 @@ cancel_mouse_face (f)
     }
 }
 \f
-struct scroll_bar *x_window_to_scroll_bar ();
+static struct scroll_bar *x_window_to_scroll_bar ();
 static void x_scroll_bar_report_motion ();
 
 /* Return the current position of the mouse.
@@ -6748,15 +7099,13 @@ static void x_scroll_bar_report_motion ();
    mouse is on, *bar_window to nil, and *x and *y to the character cell
    the mouse is over.
 
-   Set *time to the server timestamp for the time at which the mouse
+   Set *time to the server time-stamp for the time at which the mouse
    was at this position.
 
    Don't store anything if we don't have a valid set of values to report.
 
    This clears the mouse_moved flag, so we can wait for the next mouse
-   movement.  This also calls XQueryPointer, which will cause the
-   server to give us another MotionNotify when the mouse moves
-   again. */
+   movement.  */
 
 static void
 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
@@ -6772,7 +7121,6 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time)
   BLOCK_INPUT;
 
   if (! NILP (last_mouse_scroll_bar) && insist == 0)
-    /* This is never called at the moment.  */
     x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
   else
     {
@@ -6801,13 +7149,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)
              {
@@ -6875,10 +7225,11 @@ 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.  */
-struct scroll_bar *
+
+static struct scroll_bar *
 x_window_to_scroll_bar (window_id)
      Window window_id;
 {
@@ -7018,7 +7369,7 @@ my_set_window_pos (HWND hwnd, HWND hwndAfter,
 #endif
 }
 
-BOOL
+void
 my_set_focus (f, hwnd)
      struct frame * f;
      HWND hwnd;
@@ -7027,7 +7378,7 @@ my_set_focus (f, hwnd)
               (WPARAM) hwnd, 0);
 }
 
-BOOL
+void
 my_set_foreground_window (hwnd)
      HWND hwnd;
 {
@@ -7140,7 +7491,7 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
 {
   struct frame *f = XFRAME (w->frame);
   struct scroll_bar *bar;
-  int top, left, sb_left, width, sb_width, height;
+  int top, height, left, sb_left, width, sb_width;
   int window_x, window_y, window_width, window_height;
 
   /* Get window dimensions.  */
@@ -7263,7 +7614,8 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
 
 /* Arrange for all scroll bars on FRAME to be removed at the next call
    to `*judge_scroll_bars_hook'.  A scroll bar may be spared if
-   `*redeem_scroll_bar_hook' is applied to its window before the judgement.  */
+   `*redeem_scroll_bar_hook' is applied to its window before the judgment.  */
+
 static void
 w32_condemn_scroll_bars (frame)
      FRAME_PTR frame;
@@ -7282,7 +7634,7 @@ w32_condemn_scroll_bars (frame)
     }
 }
 
-/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
+/* 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)
@@ -7331,6 +7683,7 @@ w32_redeem_scroll_bar (window)
 
 /* Remove all scroll bars on FRAME that haven't been saved since the
    last call to `*condemn_scroll_bars_hook'.  */
+
 static void
 w32_judge_scroll_bars (f)
      FRAME_PTR f;
@@ -7377,6 +7730,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;
 
   {
@@ -7399,6 +7753,9 @@ x_scroll_bar_handle_click (bar, msg, emacs_event)
 
     bar->dragging = Qnil;
 
+
+    last_mouse_scroll_bar_pos = msg->msg.wParam;
     switch (LOWORD (msg->msg.wParam))
       {
       case SB_LINEDOWN:
@@ -7481,6 +7838,7 @@ x_scroll_bar_handle_click (bar, msg, emacs_event)
 
 /* Return information to the user about the current position of the mouse
    on the scroll bar.  */
+
 static void
 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
      FRAME_PTR *fp;
@@ -7531,8 +7889,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;
@@ -7542,34 +7900,40 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
   UNBLOCK_INPUT;
 }
 
+
 /* The screen has been cleared so we may have changed foreground or
    background colors, and the scroll bars may need to be redrawn.
    Clear out the scroll bars, and ask for expose events, so we can
    redraw them.  */
+
 void
 x_scroll_bar_clear (f)
-     struct frame *f;
+     FRAME_PTR f;
 {
   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));
-      HDC hdc = GetDC (window);
-      RECT rect;
+  /* We can have scroll bars even if this is 0,
+     if we just turned off scroll bar mode.
+     But in that case we should not clear them.  */
+  if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+    for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
+         bar = XSCROLL_BAR (bar)->next)
+      {
+        HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
+        HDC hdc = GetDC (window);
+        RECT rect;
 
-      /* Hide scroll bar until ready to repaint.  x_scroll_bar_move
-         arranges to refresh the scroll bar if hidden.  */
-      my_show_window (f, window, SW_HIDE);
+        /* Hide scroll bar until ready to repaint.  x_scroll_bar_move
+           arranges to refresh the scroll bar if hidden.  */
+        my_show_window (f, window, SW_HIDE);
 
-      GetClientRect (window, &rect);
-      select_palette (f, hdc);
-      w32_clear_rect (f, hdc, &rect);
-      deselect_palette (f, hdc);
+        GetClientRect (window, &rect);
+        select_palette (f, hdc);
+        w32_clear_rect (f, hdc, &rect);
+        deselect_palette (f, hdc);
 
-      ReleaseDC (window, hdc);
-    }
+        ReleaseDC (window, hdc);
+      }
 }
 
 show_scroll_bars (f, how)
@@ -7589,15 +7953,17 @@ show_scroll_bars (f, how)
 \f
 /* The main W32 event-reading loop - w32_read_socket.  */
 
-/* Timestamp of enter window event.  This is only used by w32_read_socket,
+/* Time stamp of enter window event.  This is only used by w32_read_socket,
    but we have to put it out here, since static variables within functions
    sometimes don't work.  */
+
 static Time enter_timestamp;
 
 /* Record the last 100 characters stored
    to help debug the loss-of-chars-during-GC problem.  */
-int temp_index;
-short temp_buffer[100];
+
+static int temp_index;
+static short temp_buffer[100];
 
 
 /* Read events coming from the W32 shell.
@@ -7623,8 +7989,8 @@ short temp_buffer[100];
 int
 w32_read_socket (sd, bufp, numchars, expected)
      register int sd;
-     register struct input_event *bufp;
-     register int numchars;
+     /* register */ struct input_event *bufp;
+     /* register */ int numchars;
      int expected;
 {
   int count = 0;
@@ -7648,7 +8014,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))
     {
@@ -7682,11 +8048,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.  */
@@ -7719,6 +8086,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++;
@@ -7740,13 +8108,11 @@ 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--;
              count++;
-              if (display_busy_cursor_p)
-                if (bufp->code != VK_RETURN || minibuf_level == 0)
-                  inhibit_busy_cursor = 2;
            }
          break;
 
@@ -7763,19 +8129,18 @@ 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--;
              count++;
-              if (display_busy_cursor_p)
-                if (bufp->code != VK_RETURN || minibuf_level == 0)
-                  inhibit_busy_cursor = 2;
            }
          break;
 
        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))
@@ -7794,10 +8159,11 @@ w32_read_socket (sd, bufp, numchars, expected)
 
           /* If the contents of the global variable help_echo
              has changed, generate a HELP_EVENT.  */
-          if (STRINGP (help_echo)
-              || STRINGP (previous_help_echo))
+          if (!NILP (help_echo)
+              || !NILP (previous_help_echo))
             {
               Lisp_Object frame;
+              int n;
 
               if (f)
                 XSETFRAME (frame, f);
@@ -7805,9 +8171,10 @@ w32_read_socket (sd, bufp, numchars, expected)
                 frame = Qnil;
 
               any_help_event_p = 1;
-              bufp->kind = HELP_EVENT;
-              bufp->frame_or_window = Fcons (frame, 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;
 
@@ -7887,8 +8254,6 @@ w32_read_socket (sd, bufp, numchars, expected)
 
                 if (!tool_bar_p)
                   last_tool_bar_item = -1;
-                if (display_busy_cursor_p)
-                  inhibit_busy_cursor = 2;
              }
            break;
          }
@@ -7914,6 +8279,16 @@ w32_read_socket (sd, bufp, numchars, expected)
             }
          break;
 
+        case WM_MENUSELECT:
+          {
+            HMENU menu = (HMENU) msg.msg.lParam;
+            UINT menu_item = (UINT) LOWORD (msg.msg.wParam);
+            UINT flags = (UINT) HIWORD (msg.msg.wParam);
+
+            w32_menu_display_help (menu, menu_item, flags);
+          }
+          break;
+
        case WM_DROPFILES:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
 
@@ -7996,6 +8371,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                  
                  bufp->kind = iconify_event;
                  XSETFRAME (bufp->frame_or_window, f);
+                 bufp->arg = Qnil;
                  bufp++;
                  count++;
                  numchars--;
@@ -8025,11 +8401,13 @@ w32_read_socket (sd, bufp, numchars, expected)
 
                      bufp->kind = deiconify_event;
                      XSETFRAME (bufp->frame_or_window, f);
+                     bufp->arg = Qnil;
                      bufp++;
                      count++;
                      numchars--;
                    }
-                 else
+                 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.  */
@@ -8046,7 +8424,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;
@@ -8091,7 +8469,7 @@ 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)
@@ -8111,16 +8489,19 @@ w32_read_socket (sd, bufp, numchars, expected)
                   clear_mouse_face (dpyinfo);
                   dpyinfo->mouse_face_mouse_frame = 0;
                 }
+
               /* Generate a nil HELP_EVENT to cancel a help-echo.
                  Do it only if there's something to cancel.
                  Otherwise, the startup message is cleared when
                  the mouse leaves the frame.  */
               if (any_help_event_p)
                 {
+                  int n;
+
                   XSETFRAME (frame, f);
-                  bufp->kind = HELP_EVENT;
-                  bufp->frame_or_window = Fcons (frame, Qnil);
-                  ++bufp, ++count, --numchars;
+                  n = gen_help_event (bufp, numchars, Qnil, frame,
+                                     Qnil, Qnil, 0);
+                  bufp += n, count += n, numchars -=n;
                 }
             }
 
@@ -8138,6 +8519,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--;
@@ -8154,6 +8536,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--;
@@ -8284,6 +8667,8 @@ w32_read_socket (sd, bufp, numchars, expected)
   return count;
 }
 
+
+
 \f
 /***********************************************************************
                             Text Cursor
@@ -8337,7 +8722,7 @@ w32_clip_to_row (w, row, hdc, whole_line_p)
   clip_rect.bottom = clip_rect.top + row->visible_height;
 
   /* If clipping to the whole line, including trunc marks, extend
-     the rectangle to the left and right.  */
+     the rectangle to the left and increase its width.  */
   if (whole_line_p)
     {
       clip_rect.left -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
@@ -8401,9 +8786,10 @@ x_draw_hollow_cursor (w, row)
    --gerd.  */
 
 static void
-x_draw_bar_cursor (w, row)
+x_draw_bar_cursor (w, row, width)
      struct window *w;
      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
@@ -8419,16 +8805,31 @@ x_draw_bar_cursor (w, row)
       if (cursor_glyph == NULL)
        return;
 
-      x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+      /* 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
+        {
 
-      hdc = get_frame_dc (f);
-      w32_fill_area (f, hdc, f->output_data.w32->cursor_pixel,
-                     x,
-                     WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
-                     min (cursor_glyph->pixel_width,
-                          f->output_data.w32->cursor_width),
-                     row->height);
-      release_frame_dc (f, hdc);
+          x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+
+          if (width < 0)
+            width = f->output_data.w32->cursor_width;
+
+          hdc = get_frame_dc (f);
+          w32_fill_area (f, hdc, f->output_data.w32->cursor_pixel,
+                         x,
+                         WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+                         min (cursor_glyph->pixel_width, width),
+                         row->height);
+          release_frame_dc (f, hdc);
+        }
     }
 }
 
@@ -8584,6 +8985,7 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
 {
   struct frame *f = XFRAME (w->frame);
   int new_cursor_type;
+  int new_cursor_width;
   struct glyph_matrix *current_glyphs;
   struct glyph_row *glyph_row;
   struct glyph *glyph;
@@ -8622,6 +9024,7 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
      the cursor type given by the frame parameter.  If explicitly
      marked off, draw no cursor.  In all other cases, we want a hollow
      box cursor.  */
+  new_cursor_width = -1;
   if (cursor_in_echo_area
       && FRAME_HAS_MINIBUF_P (f)
       && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
@@ -8636,7 +9039,11 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
       if (w != XWINDOW (selected_window)
           || f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
         {
-          if (MINI_WINDOW_P (w))
+         extern int 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;
@@ -8644,7 +9051,15 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
       else if (w->cursor_off_p)
         new_cursor_type = NO_CURSOR;
       else
-        new_cursor_type = FRAME_DESIRED_CURSOR (f);
+        {
+         struct buffer *b = XBUFFER (w->buffer);
+
+         if (EQ (b->cursor_type, Qt))
+            new_cursor_type = FRAME_DESIRED_CURSOR (f);
+         else
+           new_cursor_type = x_specified_cursor_type (b->cursor_type, 
+                                                      &new_cursor_width);
+       }
     }
 
   /* If cursor is currently being shown and we don't want it to be or
@@ -8684,7 +9099,7 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
          break;
 
        case BAR_CURSOR:
-         x_draw_bar_cursor (w, glyph_row);
+         x_draw_bar_cursor (w, glyph_row, new_cursor_width);
          break;
 
        case NO_CURSOR:
@@ -8756,13 +9171,20 @@ x_update_window_cursor (w, on)
      struct window *w;
      int on;
 {
-  BLOCK_INPUT;
-  x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
-                           w->phys_cursor.x, w->phys_cursor.y);
-  UNBLOCK_INPUT;
+  /* Don't update cursor in windows whose frame is in the process
+     of being deleted.  */
+  if (w->current_matrix)
+    {
+      BLOCK_INPUT;
+      x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
+                                w->phys_cursor.vpos, w->phys_cursor.x,
+                                w->phys_cursor.y);
+      UNBLOCK_INPUT;
+    }
 }
 
 
+
 \f
 /* Icons.  */
 
@@ -8830,8 +9252,7 @@ x_new_font (f, fontname)
      register char *fontname;
 {
   struct font_info *fontp
-    = fs_load_font (f, FRAME_W32_FONT_TABLE (f), CHARSET_ASCII,
-                    fontname, -1);
+    = FS_LOAD_FONT (f, 0, fontname, -1);
 
   if (!fontp)
     return Qnil;
@@ -8843,11 +9264,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)
@@ -8858,7 +9282,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);
 }
@@ -8873,9 +9297,9 @@ x_new_fontset (f, fontsetname)
      struct frame *f;
      char *fontsetname;
 {
-  int fontset = fs_query_fontset (f, fontsetname);
-  struct fontset_info *fontsetp;
+  int fontset = fs_query_fontset (build_string (fontsetname), 0);
   Lisp_Object result;
+  char *fontname;
 
   if (fontset < 0)
     return Qnil;
@@ -8883,15 +9307,9 @@ x_new_fontset (f, fontsetname)
   if (FRAME_FONTSET (f) == fontset)
     /* This fontset is already set in frame F.  There's nothing more
        to do.  */
-    return build_string (fontsetname);
+    return fontset_name (fontset);
 
-  fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
-
-  if (!fontsetp->fontname[CHARSET_ASCII])
-    /* This fontset doesn't contain ASCII font.  */
-    return Qnil;
-
-  result = x_new_font (f, fontsetp->fontname[CHARSET_ASCII]);
+  result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
 
   if (!STRINGP (result))
     /* Can't load ASCII font.  */
@@ -8899,8 +9317,6 @@ x_new_fontset (f, fontsetname)
 
   /* Since x_new_font doesn't update any fontset information, do it now.  */
   FRAME_FONTSET(f) = fontset;
-  FS_LOAD_FONT (f, FRAME_W32_FONT_TABLE (f),
-               CHARSET_ASCII, XSTRING (result)->data, fontset);
 
   return build_string (fontsetname);
 }
@@ -8942,17 +9358,12 @@ 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);
-#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
 }
 
 
@@ -9001,6 +9412,7 @@ x_compute_min_glyph_bounds (f)
 /* Calculate the absolute position in frame F
    from its current recorded position values and gravity.  */
 
+void
 x_calc_absolute_position (f)
      struct frame *f;
 {
@@ -9041,7 +9453,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
@@ -9059,6 +9471,7 @@ x_calc_absolute_position (f)
    position values).  It is -1 when calling from x_set_frame_parameters,
    which means, do adjust for borders but don't change the gravity.  */
 
+void
 x_set_offset (f, xoff, yoff, change_gravity)
      struct frame *f;
      register int xoff, yoff;
@@ -9082,18 +9495,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,
@@ -9155,7 +9558,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.
 
@@ -9185,6 +9588,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;
@@ -9205,27 +9629,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;
 {
@@ -9243,6 +9650,7 @@ x_focus_on_frame (f)
   UNBLOCK_INPUT;
 }
 
+void
 x_unfocus_frame (f)
      struct frame *f;
 {
@@ -9322,11 +9730,11 @@ 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 (raise_flag)
     x_raise_frame (f);
   else
     x_lower_frame (f);
@@ -9341,6 +9749,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;
 {
@@ -9387,7 +9796,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
@@ -9398,8 +9807,10 @@ x_make_frame_visible (f)
          {
            /* It could be confusing if a real alarm arrives while processing
               the fake one.  Turn it off and let the handler reset it.  */
-           alarm (0);
-           input_poll_signal (0);
+           int old_poll_suppress_count = poll_suppress_count;
+           poll_suppress_count = 1;
+           poll_for_input_1 ();
+           poll_suppress_count = old_poll_suppress_count;
          }
       }
     FRAME_SAMPLE_VISIBILITY (f);
@@ -9539,6 +9950,7 @@ x_wm_set_icon_position (f, icon_x, icon_y)
 #endif
 }
 
+
 \f
 /***********************************************************************
                            Initialization
@@ -9546,6 +9958,47 @@ x_wm_set_icon_position (f, icon_x, icon_y)
 
 static int w32_initialized = 0;
 
+void
+w32_initialize_display_info (display_name)
+     Lisp_Object display_name;
+{
+  struct w32_display_info *dpyinfo = &one_w32_display_info;
+
+  bzero (dpyinfo, sizeof (*dpyinfo));
+
+  /* Put it on w32_display_name_list.  */
+  w32_display_name_list = Fcons (Fcons (display_name, Qnil),
+                                 w32_display_name_list);
+  dpyinfo->name_list_element = XCAR (w32_display_name_list);
+  
+  dpyinfo->w32_id_name
+    = (char *) xmalloc (XSTRING (Vinvocation_name)->size
+                       + XSTRING (Vsystem_name)->size
+                       + 2);
+  sprintf (dpyinfo->w32_id_name, "%s@%s",
+          XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
+
+  /* Default Console mode values - overridden when running in GUI mode
+     with values obtained from system metrics.  */
+  dpyinfo->resx = 1;
+  dpyinfo->resy = 1;
+  dpyinfo->height_in = 1;
+  dpyinfo->width_in = 1;
+  dpyinfo->n_planes = 1;
+  dpyinfo->n_cbits = 4;
+  dpyinfo->n_fonts = 0;
+  dpyinfo->smallest_font_height = 1;
+  dpyinfo->smallest_char_width = 1;
+
+  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_face_id = DEFAULT_FACE_ID;
+  dpyinfo->mouse_face_window = Qnil;
+
+  /* TODO: dpyinfo->gray */
+
+}
+
 struct w32_display_info *
 w32_term_init (display_name, xrm_option, resource_name)
      Lisp_Object display_name;
@@ -9576,31 +10029,10 @@ w32_term_init (display_name, xrm_option, resource_name)
       }
   }
   
-  dpyinfo = &one_w32_display_info;
-  
-  /* Put this display on the chain.  */
-  dpyinfo->next = NULL;
-  
-  /* Put it on w32_display_name_list as well, to keep them parallel.  */ 
-  w32_display_name_list = Fcons (Fcons (display_name, Qnil),
-                                 w32_display_name_list);
-  dpyinfo->name_list_element = XCAR (w32_display_name_list);
-  
-  dpyinfo->w32_id_name
-    = (char *) xmalloc (XSTRING (Vinvocation_name)->size
-                       + XSTRING (Vsystem_name)->size
-                       + 2);
-  sprintf (dpyinfo->w32_id_name, "%s@%s",
-          XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
+  w32_initialize_display_info (display_name);
 
-#if 0
-  xrdb = x_load_resources (dpyinfo->display, xrm_option,
-                          resource_name, EMACS_CLASS);
+  dpyinfo = &one_w32_display_info;
   
-  /* Put the rdb where we can find it in a way that works on
-     all versions.  */
-  dpyinfo->xrdb = xrdb;
-#endif
   hdc = GetDC (GetDesktopWindow ());
 
   dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
@@ -9611,35 +10043,10 @@ w32_term_init (display_name, xrm_option, resource_name)
   dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
   dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
   dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
-  dpyinfo->grabbed = 0;
-  dpyinfo->reference_count = 0;
-  dpyinfo->font_table = NULL;
-  dpyinfo->n_fonts = 0;
-  dpyinfo->font_table_size = 0;
-  dpyinfo->bitmaps = 0;
-  dpyinfo->bitmaps_size = 0;
-  dpyinfo->bitmaps_last = 0;
-  dpyinfo->scratch_cursor_gc = NULL;
-  dpyinfo->mouse_face_mouse_frame = 0;
-  dpyinfo->mouse_face_deferred_gc = 0;
-  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_face_id = DEFAULT_FACE_ID;
-  dpyinfo->mouse_face_window = Qnil;
-  dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
-  dpyinfo->mouse_face_defer = 0;
-  dpyinfo->w32_focus_frame = 0;
-  dpyinfo->w32_focus_event_frame = 0;
-  dpyinfo->w32_highlight_frame = 0;
   dpyinfo->image_cache = make_image_cache ();
   dpyinfo->height_in = dpyinfo->height / dpyinfo->resx;
   dpyinfo->width_in = dpyinfo->width / dpyinfo->resy;
   ReleaseDC (GetDesktopWindow (), hdc);
-  /* NTEMACS_TODO: dpyinfo->gray */
-  /* Determine if there is a middle mouse button, to allow parse_button
-     to decide whether right mouse events should be mouse-2 or
-     mouse-3. */
-  XSETINT (Vw32_num_mouse_buttons, GetSystemMetrics (SM_CMOUSEBUTTONS));
 
   /* initialise palette with white and black */
   {
@@ -9648,6 +10055,16 @@ w32_term_init (display_name, xrm_option, resource_name)
     w32_defined_color (0, "black", &color, 1);
   }
 
+  /* Create Row Bitmaps and store them for later use.  */
+  left_bmp = CreateBitmap (left_width, left_height, 1, 1, left_bits);
+  ov_bmp = CreateBitmap (ov_width, ov_height, 1, 1, ov_bits);
+  right_bmp = CreateBitmap (right_width, right_height, 1, 1, right_bits);
+  continued_bmp = CreateBitmap (continued_width, continued_height, 1,
+                                1, continued_bits);
+  continuation_bmp = CreateBitmap (continuation_width, continuation_height,
+                                   1, 1, continuation_bits);
+  zv_bmp = CreateBitmap (zv_width, zv_height, 1, 1, zv_bits);
+
 #ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
 #ifdef F_SETOWN_SOCK_NEG
@@ -9687,8 +10104,7 @@ x_delete_display (dpyinfo)
       tail = w32_display_name_list;
       while (CONSP (tail) && CONSP (XCDR (tail)))
        {
-         if (EQ (XCAR (XCDR (tail)),
-                 dpyinfo->name_list_element))
+         if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
            {
              XCDR (tail) = XCDR (XCDR (tail));
              break;
@@ -9706,7 +10122,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)
@@ -9714,6 +10130,14 @@ x_delete_display (dpyinfo)
   }
   xfree (dpyinfo->font_table);
   xfree (dpyinfo->w32_id_name);
+
+  /* Destroy row bitmaps.  */
+  DeleteObject (left_bmp);
+  DeleteObject (ov_bmp);
+  DeleteObject (right_bmp);
+  DeleteObject (continued_bmp);
+  DeleteObject (continuation_bmp);
+  DeleteObject (zv_bmp);
 }
 \f
 /* Set up use of W32.  */
@@ -9736,6 +10160,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
 };
@@ -9825,8 +10250,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
 
@@ -9847,8 +10272,6 @@ w32_initialize ()
 void
 syms_of_w32term ()
 {
-  Lisp_Object codepage;
-
   staticpro (&w32_display_name_list);
   w32_display_name_list = Qnil;
 
@@ -9899,69 +10322,15 @@ NT uses Unicode internally anyway, so this flag will probably have no\n\
 affect on NT machines.");
   w32_enable_unicode_output = 1;
 
-  DEFVAR_LISP ("w32-charset-to-codepage-alist",
-               &Vw32_charset_to_codepage_alist,
-               "Alist linking character sets to Windows Codepages.");
-  Vw32_charset_to_codepage_alist = Qnil;
-  /* Initialise the alist with some defaults.  */
-  XSETFASTINT (codepage, 936);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("gb2312"), codepage);
-  XSETFASTINT (codepage, 950);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("big5"), codepage);
-  XSETFASTINT (codepage, 949);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("ksc5601.1987"), codepage);
-  XSETFASTINT (codepage, 1361);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("ksc5601.1992"), codepage);
-  XSETFASTINT (codepage, 932);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("jisx0208-sjis"), codepage);
-  XSETFASTINT (codepage, 874);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("tis620"), codepage);
-  XSETFASTINT (codepage, 20866);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("koi8-r"), codepage);
-  /* iso8859-13 is not yet officially adopted, but it is conveniently
-     covered by CP 1257.  */
-  XSETFASTINT (codepage, 1257);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-13"), codepage);
-  XSETFASTINT (codepage, 1254);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-9"), codepage);
-  XSETFASTINT (codepage, 1255);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-8"), codepage);
-  XSETFASTINT (codepage, 28597);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-7"), codepage);
-  XSETFASTINT (codepage, 28596);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-6"), codepage);
-  XSETFASTINT (codepage, 28595);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-5"), codepage);
-  XSETFASTINT (codepage, 28594);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-4"), codepage);
-  XSETFASTINT (codepage, 28593);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-3"), codepage);
-  XSETFASTINT (codepage, 28592);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-2"), codepage);
-  XSETFASTINT (codepage, 1252);
-  store_in_alist (&Vw32_charset_to_codepage_alist,
-                  build_string ("iso8859-1"), codepage);
-
-  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\