Merge from emacs--devo--0
[bpt/emacs.git] / src / w32term.c
index b3bf9a0..93e81b7 100644 (file)
@@ -25,25 +25,21 @@ Boston, MA 02110-1301, USA.  */
 #include <stdio.h>
 #include <stdlib.h>
 #include "lisp.h"
-#include "charset.h"
 #include "blockinput.h"
-
-#include "w32heap.h"
 #include "w32term.h"
-#include "w32bdf.h"
-#include <shellapi.h>
 
 #include "systty.h"
 #include "systime.h"
-#include "atimer.h"
-#include "keymap.h"
 
 #include <ctype.h>
 #include <errno.h>
 #include <setjmp.h>
 #include <sys/stat.h>
 
-#include "keyboard.h"
+#include "charset.h"
+#include "character.h"
+#include "coding.h"
+#include "ccl.h"
 #include "frame.h"
 #include "dispextern.h"
 #include "fontset.h"
@@ -54,11 +50,19 @@ Boston, MA 02110-1301, USA.  */
 #include "disptab.h"
 #include "buffer.h"
 #include "window.h"
+#include "keyboard.h"
 #include "intervals.h"
-#include "composite.h"
-#include "coding.h"
+#include "process.h"
+#include "atimer.h"
+#include "keymap.h"
 
-#define abs(x) ((x) < 0 ? -(x) : (x))
+#include "w32heap.h"
+#include "w32bdf.h"
+#include <shellapi.h>
+
+#ifdef USE_FONT_BACKEND
+#include "font.h"
+#endif /* USE_FONT_BACKEND */
 
 \f
 /* Fringe bitmaps.  */
@@ -121,6 +125,31 @@ struct w32_display_info *x_display_list;
    FONT-LIST-CACHE records previous values returned by x-list-fonts.  */
 Lisp_Object w32_display_name_list;
 
+
+#ifndef GLYPHSET
+/* Pre Windows 2000, this was not available, but define it here so
+   that Emacs compiled on such a platform will run on newer versions.  */
+
+typedef struct tagWCRANGE
+{
+  WCHAR wcLow;
+  USHORT cGlyphs;
+} WCRANGE;
+
+typedef struct tagGLYPHSET 
+{
+  DWORD cbThis;
+  DWORD flAccel;
+  DWORD cGlyphsSupported;
+  DWORD cRanges;
+  WCRANGE ranges[1];
+} GLYPHSET;  
+
+#endif
+
+/* Dynamic linking to GetFontUnicodeRanges (not available on 95, 98, ME).  */
+DWORD (PASCAL *pfnGetFontUnicodeRanges) (HDC device, GLYPHSET *ranges);
+
 /* Frame being updated by update_frame.  This is declared in term.c.
    This is set by update_begin and looked at by all the
    w32 functions.  It is zero while not inside an update.
@@ -218,10 +247,9 @@ extern int errno;
 extern EMACS_INT extra_keyboard_modifiers;
 
 static void x_update_window_end P_ ((struct window *, int, int));
-void w32_delete_display P_ ((struct w32_display_info *));
 static void w32_handle_tool_bar_click P_ ((struct frame *,
                                           struct input_event *));
-void w32_define_cursor P_ ((Window, Cursor));
+static void w32_define_cursor P_ ((Window, Cursor));
 
 void x_lower_frame P_ ((struct frame *));
 void x_scroll_bar_clear P_ ((struct frame *));
@@ -230,14 +258,14 @@ void x_raise_frame P_ ((struct frame *));
 void x_set_window_size P_ ((struct frame *, int, int, int));
 void x_wm_set_window_state P_ ((struct frame *, int));
 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
-void w32_initialize P_ ((void));
+static void w32_initialize P_ ((void));
 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
 int x_compute_min_glyph_bounds P_ ((struct frame *));
 static void x_update_end P_ ((struct frame *));
 static void w32_frame_up_to_date P_ ((struct frame *));
-static void w32_set_terminal_modes P_ ((void));
-static void w32_reset_terminal_modes P_ ((void));
-static void x_clear_frame P_ ((void));
+static void w32_set_terminal_modes P_ ((struct terminal *));
+static void w32_reset_terminal_modes P_ ((struct terminal *));
+static void x_clear_frame P_ ((struct frame *));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
 static void x_new_focus_frame P_ ((struct w32_display_info *,
@@ -683,6 +711,60 @@ w32_draw_fringe_bitmap (w, row, p)
 
   hdc = get_frame_dc (f);
 
+  if (!p->overlay_p)
+    {
+      int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
+
+      /* If the fringe is adjacent to the left (right) scroll bar of a
+        leftmost (rightmost, respectively) window, then extend its
+        background to the gap between the fringe and the bar.  */
+      if ((WINDOW_LEFTMOST_P (w)
+          && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
+         || (WINDOW_RIGHTMOST_P (w)
+             && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
+       {
+         int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
+
+         if (sb_width > 0)
+           {
+             int left = WINDOW_SCROLL_BAR_AREA_X (w);
+             int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
+                          * FRAME_COLUMN_WIDTH (f));
+
+             if (bx < 0)
+               {
+                 /* Bitmap fills the fringe.  */
+                 if (left + width == p->x)
+                   bx = left + sb_width;
+                 else if (p->x + p->wd == left)
+                   bx = left;
+                 if (bx >= 0)
+                   {
+                     int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+
+                     nx = width - sb_width;
+                     by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
+                                                           row->y));
+                     ny = row->visible_height;
+                   }
+               }
+             else
+               {
+                 if (left + width == bx)
+                   {
+                     bx = left + sb_width;
+                     nx += width - sb_width;
+                   }
+                 else if (bx + nx == left)
+                   nx += width - sb_width;
+               }
+           }
+       }
+
+      if (bx >= 0 && nx > 0)
+       w32_fill_area (f, hdc, face->background, bx, by, nx, ny);
+    }
+
   /* Must clip because of partially visible lines.  */
   rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
   if (p->y < rowY)
@@ -700,12 +782,6 @@ w32_draw_fringe_bitmap (w, row, p)
   else
     w32_clip_to_row (w, row, -1, hdc);
 
-  if (p->bx >= 0 && !p->overlay_p)
-    {
-      w32_fill_area (f, hdc, face->background,
-                    p->bx, p->by, p->nx, p->ny);
-    }
-
   if (p->which && p->which < max_fringe_bmp)
     {
       HBITMAP pixmap = fringe_bmp[p->which];
@@ -801,7 +877,7 @@ w32_destroy_fringe_bitmap (which)
    rarely happens).  */
 
 static void
-w32_set_terminal_modes (void)
+w32_set_terminal_modes (struct terminal *term)
 {
 }
 
@@ -809,7 +885,7 @@ w32_set_terminal_modes (void)
    the W32 windows go away, and suspending requires no action. */
 
 static void
-w32_reset_terminal_modes (void)
+w32_reset_terminal_modes (struct terminal *term)
 {
 }
 
@@ -822,7 +898,8 @@ w32_reset_terminal_modes (void)
 /* Function prototypes of this page.  */
 
 XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, int));
-static int w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
+static int w32_encode_char P_ ((int, wchar_t *, struct font_info *,
+                               struct charset *, int *));
 
 
 /* Get metrics of character CHAR2B in FONT.  Value is always non-null.
@@ -947,8 +1024,8 @@ w32_native_per_char_metric (font, char2b, font_type, pcm)
 
       if (retval)
        {
-         pcm->width = sz.cx - font->tm.tmOverhang;
-         pcm->rbearing = sz.cx;
+         pcm->width = sz.cx;
+         pcm->rbearing = sz.cx + font->tm.tmOverhang;
          pcm->lbearing = 0;
          pcm->ascent = FONT_BASE (font);
          pcm->descent = FONT_DESCENT (font);
@@ -1029,9 +1106,9 @@ w32_cache_char_metrics (font)
         {
           /* 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.width = FONT_WIDTH (font);
           font->max_bounds.lbearing = -font->bdf->llx;
-          font->max_bounds.rbearing = FONT_MAX_WIDTH (font) - font->bdf->urx;
+          font->max_bounds.rbearing = FONT_WIDTH (font) - font->bdf->urx;
           font->max_bounds.ascent = FONT_BASE (font);
           font->max_bounds.descent = FONT_DESCENT (font);
         }
@@ -1066,7 +1143,8 @@ w32_cache_char_metrics (font)
 
 
 /* Determine if a font is double byte. */
-int w32_font_is_double_byte (XFontStruct *font)
+static int
+w32_font_is_double_byte (XFontStruct *font)
 {
   return font->double_byte_p;
 }
@@ -1086,13 +1164,13 @@ w32_use_unicode_for_codepage (codepage)
    the two-byte form of C.  Encoding is returned in *CHAR2B.  */
 
 static int /* enum w32_char_font_type */
-w32_encode_char (c, char2b, font_info, two_byte_p)
+w32_encode_char (c, char2b, font_info, charset, two_byte_p)
      int c;
      wchar_t *char2b;
      struct font_info *font_info;
+     struct charset *charset;
      int * two_byte_p;
 {
-  int charset = CHAR_CHARSET (c);
   int codepage;
   int unicode_p = 0;
   int internal_two_byte_p = 0;
@@ -1100,29 +1178,39 @@ w32_encode_char (c, char2b, font_info, two_byte_p)
   XFontStruct *font = font_info->font;
 
   internal_two_byte_p = w32_font_is_double_byte (font);
+  codepage = font_info->codepage;
+
+  /* If font can output unicode, use the original unicode character.  */
+  if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
+       && c >= 0x100)
+    {
+      *char2b = c;
+      unicode_p = 1;
+      internal_two_byte_p = 1;
+    }
 
   /* 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.  */
-  if (font_info->font_encoder)
+  else if (font_info->font_encoder)
     {
       /* It's a program.  */
       struct ccl_program *ccl = font_info->font_encoder;
 
       if (CHARSET_DIMENSION (charset) == 1)
        {
-         ccl->reg[0] = charset;
+         ccl->reg[0] = CHARSET_ID (charset);
          ccl->reg[1] = XCHAR2B_BYTE2 (char2b);
          ccl->reg[2] = -1;
        }
       else
        {
-         ccl->reg[0] = charset;
+         ccl->reg[0] = CHARSET_ID (charset);
          ccl->reg[1] = XCHAR2B_BYTE1 (char2b);
          ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
        }
 
-      ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
+      ccl_driver (ccl, NULL, NULL, 0, 0, Qnil);
 
       /* We assume that MSBs are appropriately set/reset by CCL
         program.  */
@@ -1131,49 +1219,25 @@ w32_encode_char (c, char2b, font_info, two_byte_p)
       else
        STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
     }
-  else if (font_info->encoding[charset])
+  else if (font_info->encoding_type)
     {
       /* Fixed encoding scheme.  See fontset.h for the meaning of the
         encoding numbers.  */
-      int enc = font_info->encoding[charset];
+      unsigned char enc = font_info->encoding_type;
 
       if ((enc == 1 || enc == 2)
          && CHARSET_DIMENSION (charset) == 2)
        STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b) | 0x80, XCHAR2B_BYTE2 (char2b));
 
-      if (enc == 1 || enc == 3
-          || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
+      if (enc == 1 || enc == 3          || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
        STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b) | 0x80);
       else if (enc == 4)
         {
-          int sjis1, sjis2;
-
-          ENCODE_SJIS (XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b),
-                       sjis1, sjis2);
-          STORE_XCHAR2B (char2b, sjis1, sjis2);
-        }
-    }
-  codepage = font_info->codepage;
+          int code = (int) (*char2b);
 
-  /* If charset is not ASCII or Latin-1, may need to move it into
-     Unicode space.  */
-  if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
-       && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1
-       && charset != CHARSET_8_BIT_CONTROL && charset != CHARSET_8_BIT_GRAPHIC)
-    {
-      char temp[3];
-      temp[0] = XCHAR2B_BYTE1 (char2b);
-      temp[1] = XCHAR2B_BYTE2 (char2b);
-      temp[2] = '\0';
-      if (codepage != CP_UNICODE)
-        {
-          if (temp[0])
-            MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
-          else
-            MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
+         JIS_TO_SJIS (code);
+          STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
         }
-      unicode_p = 1;
-      internal_two_byte_p = 1;
     }
 
   if (two_byte_p)
@@ -1192,6 +1256,207 @@ w32_encode_char (c, char2b, font_info, two_byte_p)
 }
 
 
+/* Return a char-table whose elements are t if the font FONT_INFO
+   contains a glyph for the corresponding character, and nil if not.
+
+   Fixme: For the moment, this function works only for fonts whose
+   glyph encoding is the same as Unicode (e.g. ISO10646-1 fonts).  */
+
+Lisp_Object
+x_get_font_repertory (f, font_info)
+     FRAME_PTR f;
+     struct font_info *font_info;
+{
+  XFontStruct *font = (XFontStruct *) font_info->font;
+  Lisp_Object table;
+  int min_byte1, max_byte1, min_byte2, max_byte2;
+  int c;
+  struct charset *charset = CHARSET_FROM_ID (font_info->charset);
+  int offset = CHARSET_OFFSET (charset);
+
+  table = Fmake_char_table (Qnil, Qnil);
+
+  if (!font->bdf && pfnGetFontUnicodeRanges)
+    {
+      GLYPHSET *glyphset;
+      DWORD glyphset_size;
+      HDC display = get_frame_dc (f);
+      HFONT prev_font;
+      int i;
+
+      prev_font = SelectObject (display, font->hfont);
+
+      /* First call GetFontUnicodeRanges to find out how big a structure
+        we need.  */
+      glyphset_size = pfnGetFontUnicodeRanges (display, NULL);
+      if (glyphset_size)
+       {
+         glyphset = (GLYPHSET *) alloca (glyphset_size);
+         glyphset->cbThis = glyphset_size;
+
+         /* Now call it again to get the ranges.  */
+         glyphset_size = pfnGetFontUnicodeRanges (display, glyphset);
+
+         if (glyphset_size)
+           {
+             /* Store the ranges in TABLE.  */
+             for (i = 0; i < glyphset->cRanges; i++)
+               {
+                 int from = glyphset->ranges[i].wcLow;
+                 int to = from + glyphset->ranges[i].cGlyphs - 1;
+                 char_table_set_range (table, from, to, Qt);
+               }
+           }
+       }
+
+      SelectObject (display, prev_font);
+      release_frame_dc (f, display);
+
+      /* If we got the information we wanted above, then return it.  */
+      if (glyphset_size)
+       return table;
+    }
+
+#if 0 /* TODO: Convert to work on Windows so BDF and older platforms work.  */
+  /* When GetFontUnicodeRanges is not available or does not work,
+     work it out manually.  */
+  min_byte1 = font->min_byte1;
+  max_byte1 = font->max_byte1;
+  min_byte2 = font->min_char_or_byte2;
+  max_byte2 = font->max_char_or_byte2;
+  if (min_byte1 == 0 && max_byte1 == 0)
+    {
+      if (! font->per_char || font->all_chars_exist == True)
+        {
+          if (offset >= 0)
+            char_table_set_range (table, offset + min_byte2,
+                                  offset + max_byte2, Qt);
+          else
+            for (; min_byte2 <= max_byte2; min_byte2++)
+              {
+                c = DECODE_CHAR (charset, min_byte2);
+                CHAR_TABLE_SET (table, c, Qt);
+              }
+        }
+      else
+       {
+         XCharStruct *pcm = font->per_char;
+         int from = -1;
+         int i;
+
+         for (i = min_byte2; i <= max_byte2; i++, pcm++)
+           {
+             if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
+               {
+                 if (from >= 0)
+                   {
+                      if (offset >= 0)
+                        char_table_set_range (table, offset + from,
+                                              offset + i - 1, Qt);
+                      else
+                        for (; from < i; from++)
+                          {
+                            c = DECODE_CHAR (charset, from);
+                            CHAR_TABLE_SET (table, c, Qt);
+                          }
+                     from = -1;
+                   }
+               }
+             else if (from < 0)
+               from = i;
+           }
+         if (from >= 0)
+            {
+              if (offset >= 0)
+                char_table_set_range (table, offset + from, offset + i - 1,
+                                      Qt);
+              else
+                for (; from < i; from++)
+                  {
+                    c = DECODE_CHAR (charset, from);
+                    CHAR_TABLE_SET (table, c, Qt);
+                  }
+            }
+       }
+    }
+  else
+    {
+      if (! font->per_char || font->all_chars_exist == True)
+       {
+         int i, j;
+
+          if (offset >= 0)
+            for (i = min_byte1; i <= max_byte1; i++)
+              char_table_set_range
+                (table, offset + ((i << 8) | min_byte2),
+                 offset + ((i << 8) | max_byte2), Qt);
+          else
+            for (i = min_byte1; i <= max_byte1; i++)
+              for (j = min_byte2; j <= max_byte2; j++)
+                {
+                  unsiged code = (i << 8) | j;
+                  c = DECODE_CHAR (charset, code);
+                  CHAR_TABLE_SET (table, c, Qt);
+                }
+       }
+      else
+       {
+         XCharStruct *pcm = font->per_char;
+         int i;
+
+         for (i = min_byte1; i <= max_byte1; i++)
+           {
+             int from = -1;
+             int j;
+
+             for (j = min_byte2; j <= max_byte2; j++, pcm++)
+               {
+                 if (pcm->width == 0 && pcm->rbearing == pcm->lbearing)
+                   {
+                     if (from >= 0)
+                       {
+                          if (offset >= 0)
+                            char_table_set_range
+                              (table, offset + ((i << 8) | from),
+                               offset + ((i << 8) | (j - 1)), Qt);
+                          else
+                            {
+                              for (; from < j; from++)
+                                {
+                                  unsigned code = (i << 8) | from;
+                                  c = ENCODE_CHAR (charset, code);
+                                  CHAR_TABLE_SET (table, c, Qt);
+                                }
+                            }
+                         from = -1;
+                       }
+                   }
+                 else if (from < 0)
+                   from = j;
+               }
+             if (from >= 0)
+                {
+                  if (offset >= 0)
+                    char_table_set_range
+                      (table, offset + ((i << 8) | from),
+                       offset + ((i << 8) | (j - 1)), Qt);
+                  else
+                    {
+                      for (; from < j; from++)
+                        {
+                          unsigned code = (i << 8) | from;
+                          c = DECODE_CHAR (charset, code);
+                          CHAR_TABLE_SET (table, c, Qt);
+                        }
+                    }
+                }
+           }
+       }
+    }
+#endif
+  return table;
+}
+
 \f
 /***********************************************************************
                            Glyph display
@@ -1321,15 +1586,20 @@ x_set_mouse_face_gc (s)
     face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
 
   if (s->first_glyph->type == CHAR_GLYPH)
-    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+    face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch, -1, Qnil);
   else
-    face_id = FACE_FOR_CHAR (s->f, face, 0);
+    face_id = FACE_FOR_CHAR (s->f, face, 0, -1, Qnil);
   s->face = FACE_FROM_ID (s->f, face_id);
   PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
 
   /* If font in this face is same as S->font, use it.  */
   if (s->font == s->face->font)
     s->gc = s->face->gc;
+#ifdef USE_FONT_BACKEND
+  else if (enable_font_backend)
+    /* No need of setting a font for s->gc.  */
+    s->gc = s->face->gc;
+#endif /* USE_FONT_BACKEND */
   else
     {
       /* Otherwise construct scratch_cursor_gc with values from FACE
@@ -1423,11 +1693,68 @@ static INLINE void
 x_set_glyph_string_clipping (s)
      struct glyph_string *s;
 {
-  RECT r;
-  get_glyph_string_clip_rect (s, &r);
-  w32_set_clip_rectangle (s->hdc, &r);
+#ifdef USE_FONT_BACKEND
+  RECT *r = s->clip;
+#else
+  RECT r[2];
+#endif
+  int n = get_glyph_string_clip_rects (s, r, 2);
+
+  if (n == 1)
+    w32_set_clip_rectangle (s->hdc, r);
+  else if (n > 1)
+    {
+      HRGN full_clip, clip1, clip2;
+      clip1 = CreateRectRgnIndirect (r);
+      clip2 = CreateRectRgnIndirect (r + 1);
+      if (CombineRgn (full_clip, clip1, clip2, RGN_OR) != ERROR)
+        {
+          SelectClipRgn (s->hdc, full_clip);
+        }
+      DeleteObject (clip1);
+      DeleteObject (clip2);
+      DeleteObject (full_clip);
+    }
+#ifdef USE_FONT_BACKEND
+    s->num_clips = n;
+#endif /* USE_FONT_BACKEND */
 }
 
+/* Set SRC's clipping for output of glyph string DST.  This is called
+   when we are drawing DST's left_overhang or right_overhang only in
+   the area of SRC.  */
+
+static void
+x_set_glyph_string_clipping_exactly (src, dst)
+     struct glyph_string *src, *dst;
+{
+  RECT r;
+
+#ifdef USE_FONT_BACKEND
+  if (enable_font_backend)
+    {
+      r.left = src->x;
+      r.right = r.left + src->width;
+      r.top = src->y;
+      r.bottom = r.top + src->height;
+      dst->clip[0] = r;
+      dst->num_clips = 1;
+    }
+  else
+    {
+#endif /* USE_FONT_BACKEND */
+  struct glyph_string *clip_head = src->clip_head;
+  struct glyph_string *clip_tail = src->clip_tail;
+
+  /* This foces clipping just this glyph string.  */
+  src->clip_head = src->clip_tail = src;
+  get_glyph_string_clip_rect (src, &r);
+  src->clip_head = clip_head, src->clip_tail = clip_tail;
+#ifdef USE_FONT_BACKEND
+    }
+#endif /* USE_FONT_BACKEND */
+  w32_set_clip_rectangle (dst->hdc, &r);
+}
 
 /* RIF:
    Compute left and right overhang of glyph string S.  If S is a glyph
@@ -1543,7 +1870,7 @@ x_draw_glyph_string_foreground (s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
+    x = s->x + eabs (s->face->box_line_width);
   else
     x = s->x;
 
@@ -1572,6 +1899,26 @@ x_draw_glyph_string_foreground (s)
           x += g->pixel_width;
         }
     }
+#ifdef USE_FONT_BACKEND
+  else if (enable_font_backend)
+    {
+      int boff = s->font_info->baseline_offset;
+      struct font *font = (struct font *) s->font_info;
+      int y;
+
+      if (s->font_info->vertical_centering)
+       boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
+
+      y = s->ybase - boff;
+      if (s->for_overlaps
+         || (s->background_filled_p && s->hl != DRAW_CURSOR))
+       font->driver->draw (s, 0, s->nchars, x, y, 0);
+      else
+       font->driver->draw (s, 0, s->nchars, x, y, 1);
+      if (s->face->overstrike)
+       font->driver->draw (s, 0, s->nchars, x + 1, y, 0);
+    }
+#endif /* USE_FONT_BACKEND */
   else
     {
       char *char1b = (char *) s->char2b;
@@ -1608,14 +1955,14 @@ static void
 x_draw_composite_glyph_string_foreground (s)
      struct glyph_string *s;
 {
-  int i, x;
+  int i, j, 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.  */
-  if (s->face->box != FACE_NO_BOX
+  if (s->face && s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
+    x = s->x + eabs (s->face->box_line_width);
   else
     x = s->x;
 
@@ -1640,18 +1987,76 @@ x_draw_composite_glyph_string_foreground (s)
         w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
                             s->height - 1);
     }
-  else
+#ifdef USE_FONT_BACKEND
+  else if (enable_font_backend)
     {
-      for (i = 0; i < s->nchars; i++, ++s->gidx)
+      struct font *font = (struct font *) s->font_info;
+      int y = s->ybase;
+      int width = 0;
+
+      if (s->cmp->method == COMPOSITION_WITH_GLYPH_STRING)
        {
-         w32_text_out (s, x + s->cmp->offsets[s->gidx * 2],
-                       s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
-                       s->char2b + i, 1);
-         if (s->face->overstrike)
-           w32_text_out (s, x + s->cmp->offsets[s->gidx * 2] + 1,
-                         s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
-                         s->char2b + i, 1);
+         Lisp_Object gstring = AREF (XHASH_TABLE (composition_hash_table)
+                                     ->key_and_value,
+                                     s->cmp->hash_index * 2);
+         int from;
+
+         for (i = from = 0; i < s->nchars; i++)
+           {
+             Lisp_Object g = LGSTRING_GLYPH (gstring, i);
+             Lisp_Object adjustment = LGLYPH_ADJUSTMENT (g);
+             int xoff, yoff, wadjust;
+
+             if (! VECTORP (adjustment))
+               {
+                 width += XINT (LGLYPH_WIDTH (g));
+                 continue;
+               }
+             if (from < i)
+               {
+                 font->driver->draw (s, from, i, x, y, 0);
+                 x += width;
+               }
+             xoff = XINT (AREF (adjustment, 0));
+             yoff = XINT (AREF (adjustment, 1));
+             wadjust = XINT (AREF (adjustment, 2));
+
+             font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
+             x += XINT (LGLYPH_WIDTH (g)) + wadjust;
+             from = i + 1;
+             width = 0;
+           }
+         if (from < i)
+           font->driver->draw (s, from, i, x, y, 0);
        }
+      else
+       {
+         for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
+           if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
+             {
+               int xx = x + s->cmp->offsets[j * 2];
+               int yy = y - s->cmp->offsets[j * 2 + 1];
+
+               font->driver->draw (s, j, j + 1, xx, yy, 0);
+               if (s->face->overstrike)
+                 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
+             }
+       }
+    }
+#endif /* USE_FONT_BACKEND */
+  else
+    {
+      for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
+       if (s->face)
+          {
+            w32_text_out (s, x + s->cmp->offsets[j * 2],
+                          s->ybase - s->cmp->offsets[j * 2 + 1],
+                          s->char2b + j, 1);
+            if (s->face->overstrike)
+           w32_text_out (s, x + s->cmp->offsets[j * 2] + 1,
+                         s->ybase - s->cmp->offsets[j + 1],
+                         s->char2b + j, 1);
+          }
     }
 
   if (s->font && s->font->hfont)
@@ -1945,7 +2350,7 @@ x_draw_glyph_string_box (s)
                ? s->first_glyph
                : s->first_glyph + s->nchars - 1);
 
-  width = abs (s->face->box_line_width);
+  width = eabs (s->face->box_line_width);
   raised_p = s->face->box == FACE_RAISED_BOX;
   left_x = s->x;
   right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
@@ -1991,7 +2396,7 @@ x_draw_image_foreground (s)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += abs (s->face->box_line_width);
+    x += eabs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -2084,7 +2489,7 @@ x_draw_image_relief (s)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += abs (s->face->box_line_width);
+    x += eabs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -2101,7 +2506,7 @@ x_draw_image_relief (s)
     }
   else
     {
-      thick = abs (s->img->relief);
+      thick = eabs (s->img->relief);
       raised_p = s->img->relief > 0;
     }
 
@@ -2138,7 +2543,7 @@ w32_draw_image_foreground_1 (s, pixmap)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += abs (s->face->box_line_width);
+    x += eabs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -2250,7 +2655,7 @@ x_draw_image_glyph_string (s)
      struct glyph_string *s;
 {
   int x, y;
-  int box_line_hwidth = abs (s->face->box_line_width);
+  int box_line_hwidth = eabs (s->face->box_line_width);
   int box_line_vwidth = max (s->face->box_line_width, 0);
   int height;
   HBITMAP pixmap = 0;
@@ -2364,7 +2769,6 @@ x_draw_stretch_glyph_string (s)
      struct glyph_string *s;
 {
   xassert (s->first_glyph->type == STRETCH_GLYPH);
-  s->stippled_p = s->face->stipple != 0;
 
   if (s->hl == DRAW_CURSOR
       && !x_stretch_cursor_p)
@@ -2454,10 +2858,19 @@ x_draw_glyph_string (s)
      This makes S->next use XDrawString instead of XDrawImageString.  */
   if (s->next && s->right_overhang && !s->for_overlaps)
     {
-      xassert (s->next->img == NULL);
-      x_set_glyph_string_gc (s->next);
-      x_set_glyph_string_clipping (s->next);
-      x_draw_glyph_string_background (s->next, 1);
+      int width;
+      struct glyph_string *next;
+      for (width = 0, next = s->next; next;
+           width += next->width, next = next->next)
+        if (next->first_glyph->type != IMAGE_GLYPH)
+          {
+            x_set_glyph_string_gc (next);
+            x_set_glyph_string_clipping (next);
+            x_draw_glyph_string_background (next, 1);
+#ifdef USE_FONT_BACKEND
+            next->num_clips = 0;
+#endif /* USE_FONT_BACKEND */
+          }
     }
 
   /* Set up S->gc, set clipping and draw S.  */
@@ -2477,6 +2890,12 @@ x_draw_glyph_string (s)
       x_set_glyph_string_clipping (s);
       relief_drawn_p = 1;
     }
+  else if ((s->prev && s->prev->hl != s->hl && s->left_overhang)
+          || (s->next && s->next->hl != s->hl && s->right_overhang))
+    /* We must clip just this glyph.  left_overhang part has already
+       drawn when s->prev was drawn, and right_overhang part will be
+       drawn later when s->next is drawn. */
+    x_set_glyph_string_clipping_exactly (s, s);
   else
     x_set_glyph_string_clipping (s);
 
@@ -2516,41 +2935,64 @@ x_draw_glyph_string (s)
       if (s->face->underline_p
           && (s->font->bdf || !s->font->tm.tmUnderlined))
         {
-          unsigned long h = 1;
-          unsigned long dy = 0;
+          unsigned long h;
+          int y;
+         /* Get the underline thickness.  Default is 1 pixel.  */
+#ifdef USE_FONT_BACKEND
+         if (enable_font_backend)
+           /* In the future, we must use information of font.  */
+           h = 1;
+         else
+#endif /* USE_FONT_BACKEND */
+            h = 1;
 
-          if (x_underline_at_descent_line)
-            dy = s->height - h;
-          else
+#ifdef USE_FONT_BACKEND
+         if (enable_font_backend)
+           {
+             if (s->face->font)
+               /* In the future, we must use information of font.  */
+               y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
+             else
+               y = s->y + s->height - h;
+           }
+         else
+#endif
             {
-              /* TODO: Use font information for positioning and thickness of
-                 underline.  See OUTLINETEXTMETRIC, and xterm.c.  Note: If
-                 you make this work, don't forget to change the doc string of
-                 x-use-underline-position-properties below.  */
-              dy = s->height - h;
+                y = s->y + s->height - h;
+                /* TODO: Use font information for positioning and
+                   thickness of underline.  See OUTLINETEXTMETRIC,
+                   and xterm.c.  Note: If you make this work,
+                   don't forget to change the doc string of
+                   x-use-underline_color-position-properties
+                   below.  */
+#if 0
+              if (!x_underline_at_descent_line)
+                {
+                  ...
+                }
+#endif
             }
           if (s->face->underline_defaulted_p)
             {
               w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
-                             s->y + dy, s->background_width, 1);
+                             y, s->background_width, 1);
             }
           else
             {
               w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
-                             s->y + dy, s->background_width, 1);
+                             y, s->background_width, 1);
             }
         }
-
       /* Draw overline.  */
       if (s->face->overline_p)
         {
           unsigned long dy = 0, h = 1;
 
           if (s->face->overline_color_defaulted_p)
-        {
-          w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
-                         s->y + dy, s->background_width, h);
-        }
+            {
+              w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
+                             s->y + dy, s->background_width, h);
+            }
           else
             {
               w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
@@ -2572,18 +3014,75 @@ x_draw_glyph_string (s)
             }
           else
             {
-              w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
+              w32_fill_area (s->f, s->hdc, s->face->strike_through_color, s->x,
                              s->y + dy, s->width, h);
             }
         }
 
-      /* Draw relief.  */
+      /* Draw relief if not yet drawn.  */
       if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
         x_draw_glyph_string_box (s);
+
+      if (s->prev)
+        {
+          struct glyph_string *prev;
+
+          for (prev = s->prev; prev; prev = prev->prev)
+            if (prev->hl != s->hl
+                && prev->x + prev->width + prev->right_overhang > s->x)
+              {
+                /* As prev was drawn while clipped to its own area, we
+                   must draw the right_overhang part using s->hl now.  */
+               enum draw_glyphs_face save = prev->hl;
+
+               prev->hl = s->hl;
+               x_set_glyph_string_gc (prev);
+               x_set_glyph_string_clipping_exactly (s, prev);
+               if (prev->first_glyph->type == CHAR_GLYPH)
+                 x_draw_glyph_string_foreground (prev);
+               else
+                 x_draw_composite_glyph_string_foreground (prev);
+                w32_set_clip_rectangle (prev->hdc, NULL);
+               prev->hl = save;
+#ifdef USE_FONT_BACKEND
+               prev->num_clips = 0;
+#endif /* USE_FONT_BACKEND */
+             }
+       }
+
+      if (s->next)
+       {
+         struct glyph_string *next;
+
+         for (next = s->next; next; next = next->next)
+           if (next->hl != s->hl
+               && next->x - next->left_overhang < s->x + s->width)
+             {
+               /* As next will be drawn while clipped to its own area,
+                  we must draw the left_overhang part using s->hl now.  */
+               enum draw_glyphs_face save = next->hl;
+
+               next->hl = s->hl;
+               x_set_glyph_string_gc (next);
+               x_set_glyph_string_clipping_exactly (s, next);
+               if (next->first_glyph->type == CHAR_GLYPH)
+                 x_draw_glyph_string_foreground (next);
+               else
+                 x_draw_composite_glyph_string_foreground (next);
+                w32_set_clip_rectangle (next->hdc, NULL);
+               next->hl = save;
+#ifdef USE_FONT_BACKEND
+               next->num_clips = 0;
+#endif /* USE_FONT_BACKEND */
+             }
+       }
     }
 
   /* Reset clipping.  */
   w32_set_clip_rectangle (s->hdc, NULL);
+#ifdef USE_FONT_BACKEND
+  s->num_clips = 0;
+#endif /* USE_FONT_BACKEND */
 }
 
 
@@ -2608,16 +3107,10 @@ w32_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
    for X frames.  */
 
 static void
-x_delete_glyphs (n)
+x_delete_glyphs (f, n)
+     struct frame *f;
      register int n;
 {
-  struct frame *f;
-
-  if (updating_frame)
-    f = updating_frame;
-  else
-    f = SELECTED_FRAME ();
-
   if (! FRAME_W32_P (f))
     return;
 
@@ -2629,15 +3122,8 @@ x_delete_glyphs (n)
    frame.  Otherwise clear the selected frame.  */
 
 static void
-x_clear_frame ()
+x_clear_frame (struct frame *f)
 {
-  struct frame *f;
-
-  if (updating_frame)
-    f = updating_frame;
-  else
-    f = SELECTED_FRAME ();
-
   if (! FRAME_W32_P (f))
     return;
 
@@ -2664,18 +3150,14 @@ x_clear_frame ()
 /* Make audible bell.  */
 
 static void
-w32_ring_bell (void)
+w32_ring_bell (struct frame *f)
 {
-  struct frame *f;
-
-  f = SELECTED_FRAME ();
-
   BLOCK_INPUT;
 
   if (FRAME_W32_P (f) && visible_bell)
     {
       int i;
-      HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
+      HWND hwnd = FRAME_W32_WINDOW (f);
 
       for (i = 0; i < 5; i++)
        {
@@ -2685,7 +3167,7 @@ w32_ring_bell (void)
       FlashWindow (hwnd, FALSE);
     }
   else
-      w32_sys_ring_bell ();
+      w32_sys_ring_bell (f);
 
   UNBLOCK_INPUT;
 }
@@ -2712,16 +3194,10 @@ w32_set_terminal_window (n)
    lines or deleting -N lines at vertical position VPOS.  */
 
 static void
-x_ins_del_lines (vpos, n)
+x_ins_del_lines (f, vpos, n)
+     struct frame *f;
      int vpos, n;
 {
-  struct frame *f;
-
-  if (updating_frame)
-    f = updating_frame;
-  else
-    f = SELECTED_FRAME ();
-
   if (! FRAME_W32_P (f))
     return;
 
@@ -2882,9 +3358,9 @@ x_focus_changed (type, state, dpyinfo, frame, bufp)
 
           /* Don't stop displaying the initial startup message
              for a switch-frame event we don't need.  */
-          if (GC_NILP (Vterminal_frame)
-              && GC_CONSP (Vframe_list)
-              && !GC_NILP (XCDR (Vframe_list)))
+          if (NILP (Vterminal_frame)
+              && CONSP (Vframe_list)
+              && !NILP (XCDR (Vframe_list)))
             {
               bufp->kind = FOCUS_IN_EVENT;
               XSETFRAME (bufp->frame_or_window, frame);
@@ -2970,7 +3446,7 @@ x_frame_rehighlight (dpyinfo)
   if (dpyinfo->w32_focus_frame)
     {
       dpyinfo->x_highlight_frame
-       = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
+       = ((FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
           ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
           : dpyinfo->w32_focus_frame);
       if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
@@ -3126,7 +3602,8 @@ construct_mouse_wheel (result, msg, f)
   POINT p;
   int delta;
 
-  result->kind = WHEEL_EVENT;
+  result->kind = msg->msg.message == WM_MOUSEHWHEEL ? HORIZ_WHEEL_EVENT
+                                                    : WHEEL_EVENT;
   result->code = 0;
   result->timestamp = msg->msg.time;
 
@@ -3228,6 +3705,9 @@ note_mouse_movement (frame, msg)
   memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
   XSETFRAME (last_mouse_motion_frame, frame);
 
+  if (!FRAME_X_OUTPUT (frame))
+    return 0;
+
   if (msg->hwnd != FRAME_W32_WINDOW (frame))
     {
       frame->mouse_moved = 1;
@@ -3278,7 +3758,7 @@ redo_mouse_highlight ()
                          HIWORD (last_mouse_motion_event.lParam));
 }
 
-void
+static void
 w32_define_cursor (window, cursor)
      Window window;
      Cursor cursor;
@@ -3435,15 +3915,13 @@ x_window_to_scroll_bar (window_id)
 {
   Lisp_Object tail;
 
-  for (tail = Vframe_list;
-       XGCTYPE (tail) == Lisp_Cons;
-       tail = XCDR (tail))
+  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
     {
       Lisp_Object frame, bar, condemned;
 
       frame = XCAR (tail);
       /* All elements of Vframe_list should be frames.  */
-      if (! GC_FRAMEP (frame))
+      if (! FRAMEP (frame))
        abort ();
 
       /* Scan this frame's scroll bar list for a scroll bar with the
@@ -3452,9 +3930,9 @@ x_window_to_scroll_bar (window_id)
       for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
           /* This trick allows us to search both the ordinary and
              condemned scroll bar lists with one loop.  */
-          ! GC_NILP (bar) || (bar = condemned,
+          ! NILP (bar) || (bar = condemned,
                               condemned = Qnil,
-                              ! GC_NILP (bar));
+                              ! NILP (bar));
           bar = XSCROLL_BAR (bar)->next)
        if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
          return XSCROLL_BAR (bar);
@@ -3545,7 +4023,7 @@ w32_set_scroll_bar_thumb (bar, portion, position, whole)
                         Scroll bars, general
  ************************************************************************/
 
-HWND
+static HWND
 my_create_scrollbar (f, bar)
      struct frame * f;
      struct scroll_bar * bar;
@@ -3638,6 +4116,7 @@ x_scroll_bar_create (w, top, left, width, height)
   XSETINT (bar->start, 0);
   XSETINT (bar->end, 0);
   bar->dragging = Qnil;
+  bar->fringe_extended_p = Qnil;
 
   /* Requires geometry to be set before call to create the real window */
 
@@ -3701,6 +4180,7 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
   struct scroll_bar *bar;
   int top, height, left, sb_left, width, sb_width;
   int window_y, window_height;
+  int fringe_extended_p;
 
   /* Get window dimensions.  */
   window_box (w, -1, 0, &window_y, 0, &window_height);
@@ -3720,9 +4200,20 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
 
   /* Compute the left edge of the scroll bar.  */
   if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
-    sb_left = left + width - sb_width - (width - sb_width) / 2;
+    sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
   else
-    sb_left = left + (width - sb_width) / 2;
+    sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
+
+  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
+    fringe_extended_p = (WINDOW_LEFTMOST_P (w)
+                        && WINDOW_LEFT_FRINGE_WIDTH (w)
+                        && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                            || WINDOW_LEFT_MARGIN_COLS (w) == 0));
+  else
+    fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
+                        && WINDOW_RIGHT_FRINGE_WIDTH (w)
+                        && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                            || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
 
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
@@ -3732,7 +4223,10 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
       if (width > 0 && height > 0)
        {
          hdc = get_frame_dc (f);
-         w32_clear_area (f, hdc, left, top, width, height);
+         if (fringe_extended_p)
+           w32_clear_area (f, hdc, sb_left, top, sb_width, height);
+         else
+           w32_clear_area (f, hdc, left, top, width, height);
          release_frame_dc (f, hdc);
        }
       UNBLOCK_INPUT;
@@ -3751,7 +4245,8 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
       if ( XINT (bar->left) == sb_left
            && XINT (bar->top) == top
            && XINT (bar->width) ==  sb_width
-           && XINT (bar->height) == height )
+           && XINT (bar->height) == height
+          && !NILP (bar->fringe_extended_p) == fringe_extended_p )
         {
           /* Redraw after clear_frame. */
           if (!my_show_window (f, hwnd, SW_NORMAL))
@@ -3768,11 +4263,10 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
              hdc = get_frame_dc (f);
              /* Since Windows scroll bars are smaller than the space reserved
                 for them on the frame, we have to clear "under" them.  */
-             w32_clear_area (f, hdc,
-                             left,
-                             top,
-                             width,
-                             height);
+             if (fringe_extended_p)
+               w32_clear_area (f, hdc, sb_left, top, sb_width, height);
+             else
+               w32_clear_area (f, hdc, left, top, width, height);
              release_frame_dc (f, hdc);
            }
           /* Make sure scroll bar is "visible" before moving, to ensure the
@@ -3802,6 +4296,8 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
           UNBLOCK_INPUT;
         }
     }
+  bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
+
   w32_set_scroll_bar_thumb (bar, portion, position, whole);
 
   XSETVECTOR (w->vertical_scroll_bar, bar);
@@ -3926,10 +4422,10 @@ w32_scroll_bar_handle_click (bar, msg, emacs_event)
      W32Msg *msg;
      struct input_event *emacs_event;
 {
-  if (! GC_WINDOWP (bar->window))
+  if (! WINDOWP (bar->window))
     abort ();
 
-  emacs_event->kind = W32_SCROLL_BAR_CLICK_EVENT;
+  emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
   emacs_event->code = 0;
   /* not really meaningful to distinguish up/down */
   emacs_event->modifiers = msg->dwModifiers;
@@ -4141,7 +4637,7 @@ static short temp_buffer[100];
 
    Some of these messages are reposted back to the message queue since the
    system calls the windows proc directly in a context where we cannot return
-   the data nor can we guarantee the state we are in.  So if we dispatch  them
+   the data nor can we guarantee the state we are in.  So if we dispatch them
    we will get into an infinite loop.  To prevent this from ever happening we
    will set a variable to indicate we are in the read_socket call and indicate
    which message we are processing since the windows proc gets called
@@ -4296,6 +4792,29 @@ w32_read_socket (sd, expected, hold_quit)
            }
          break;
 
+        case WM_APPCOMMAND:
+         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+
+         if (f && !f->iconified)
+           {
+             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+                 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
+               {
+                 clear_mouse_face (dpyinfo);
+                 dpyinfo->mouse_face_hidden = 1;
+               }
+
+             if (temp_index == sizeof temp_buffer / sizeof (short))
+               temp_index = 0;
+             temp_buffer[temp_index++] = msg.msg.wParam;
+             inev.kind = MULTIMEDIA_KEY_EVENT;
+             inev.code = GET_APPCOMMAND_LPARAM(msg.msg.lParam);
+             inev.modifiers = msg.dwModifiers;
+             XSETFRAME (inev.frame_or_window, f);
+             inev.timestamp = msg.msg.time;
+           }
+         break;
+          
        case WM_MOUSEMOVE:
          /* Ignore non-movement.  */
          {
@@ -4336,10 +4855,16 @@ w32_read_socket (sd, expected, hold_quit)
                  /* Window will be selected only when it is not
                     selected now and last mouse movement event was
                     not in it.  Minibuffer window will be selected
-                    iff it is active.  */
+                    only when it is active.  */
                  if (WINDOWP(window)
                      && !EQ (window, last_window)
-                     && !EQ (window, selected_window))
+                     && !EQ (window, selected_window)
+                     /* For click-to-focus window managers
+                        create event iff we don't leave the
+                        selected frame.  */
+                     && (focus_follows_mouse
+                         || (EQ (XWINDOW (window)->frame,
+                                 XWINDOW (selected_window)->frame))))
                    {
                      inev.kind = SELECT_WINDOW_EVENT;
                      inev.frame_or_window = window;
@@ -4444,6 +4969,7 @@ w32_read_socket (sd, expected, hold_quit)
          }
 
        case WM_MOUSEWHEEL:
+        case WM_MOUSEHWHEEL:
          {
            if (dpyinfo->grabbed && last_mouse_frame
                && FRAME_LIVE_P (last_mouse_frame))
@@ -5255,11 +5781,16 @@ x_new_font (f, fontname)
      register char *fontname;
 {
   struct font_info *fontp
-    = FS_LOAD_FONT (f, 0, fontname, -1);
+    = FS_LOAD_FONT (f, fontname);
 
   if (!fontp)
     return Qnil;
 
+  if (FRAME_FONT (f) == (XFontStruct *) (fontp->font))
+    /* This font is already set in frame F.  There's nothing more to
+       do.  */
+    return build_string (fontp->full_name);
+
   FRAME_FONT (f) = (XFontStruct *) (fontp->font);
   FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
   FRAME_FONTSET (f) = -1;
@@ -5293,38 +5824,112 @@ x_new_font (f, fontname)
   return build_string (fontp->full_name);
 }
 \f
-/* Give frame F the fontset named FONTSETNAME as its default font, and
-   return the full name of that fontset.  FONTSETNAME may be a wildcard
-   pattern; in that case, we choose some fontset that fits the pattern.
-   The return value shows which fontset we chose.  */
+/* Give frame F the fontset named FONTSETNAME as its default fontset,
+   and return the full name of that fontset.  FONTSETNAME may be a
+   wildcard pattern; in that case, we choose some fontset that fits
+   the pattern.  FONTSETNAME may be a font name for ASCII characters;
+   in that case, we create a fontset from that font name.
+
+   The return value shows which fontset we chose.
+   If FONTSETNAME specifies the default fontset, return Qt.
+   If an ASCII font in the specified fontset can't be loaded, return
+   Qnil.  */
 
 Lisp_Object
 x_new_fontset (f, fontsetname)
      struct frame *f;
-     char *fontsetname;
+     Lisp_Object fontsetname;
 {
-  int fontset = fs_query_fontset (build_string (fontsetname), 0);
+  int fontset = fs_query_fontset (fontsetname, 0);
   Lisp_Object result;
 
-  if (fontset < 0)
-    return Qnil;
-
-  if (FRAME_FONTSET (f) == fontset)
+  if (fontset > 0 && FRAME_FONTSET(f) == fontset)
     /* This fontset is already set in frame F.  There's nothing more
        to do.  */
     return fontset_name (fontset);
+  else if (fontset == 0)
+    /* The default fontset can't be the default font.   */
+    return Qt;
 
-  result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
+  if (fontset > 0)
+    result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
+  else
+    result = x_new_font (f, SDATA (fontsetname));
 
   if (!STRINGP (result))
     /* Can't load ASCII font.  */
     return Qnil;
 
+  if (fontset < 0)
+    fontset = new_fontset_from_font_name (result);
+
   /* Since x_new_font doesn't update any fontset information, do it now.  */
   FRAME_FONTSET(f) = fontset;
 
-  return build_string (fontsetname);
+  return fontset_name (fontset);
+}
+
+#ifdef USE_FONT_BACKEND
+Lisp_Object
+x_new_fontset2 (f, fontset, font_object)
+     struct frame *f;
+     int fontset;
+     Lisp_Object font_object;
+{
+  struct font *font = XSAVE_VALUE (font_object)->pointer;
+
+  if (FRAME_FONT_OBJECT (f) == font)
+    /* This font is already set in frame F.  There's nothing more to
+       do.  */
+    return fontset_name (fontset);
+
+  BLOCK_INPUT;
+
+  FRAME_FONT_OBJECT (f) = font;
+  FRAME_FONT (f) = font->font.font;
+  FRAME_BASELINE_OFFSET (f) = font->font.baseline_offset;
+  FRAME_FONTSET (f) = fontset;
+
+  FRAME_COLUMN_WIDTH (f) = font->font.average_width;
+  FRAME_SPACE_WIDTH (f) = font->font.space_width;
+  FRAME_LINE_HEIGHT (f) = font->font.height;
+
+  compute_fringe_widths (f, 1);
+
+  /* Compute the scroll bar width in character columns.  */
+  if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
+    {
+      int wid = FRAME_COLUMN_WIDTH (f);
+      FRAME_CONFIG_SCROLL_BAR_COLS (f)
+       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
+    }
+  else
+    {
+      int wid = FRAME_COLUMN_WIDTH (f);
+      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
+    }
+
+  /* Now make the frame display the given font.  */
+  if (FRAME_X_WINDOW (f) != 0)
+    {
+      /* Don't change the size of a tip frame; there's no point in
+        doing it because it's done in Fx_show_tip, and it leads to
+        problems because the tip frame has no widget.  */
+      if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+       x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+    }
+
+#ifdef HAVE_X_I18N
+  if (FRAME_XIC (f)
+      && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
+    xic_set_xfontset (f, SDATA (fontset_ascii (fontset)));
+#endif
+
+  UNBLOCK_INPUT;
+
+  return fontset_name (fontset);
 }
+#endif /* USE_FONT_BACKEND */
 
 \f
 /***********************************************************************
@@ -5515,7 +6120,22 @@ x_set_window_size (f, change_gravity, cols, rows)
                       SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
   }
 
-  /* Now, strictly speaking, we can't be sure that this is accurate,
+#if 0
+  /* The following mirrors what is done in xterm.c. It appears to be
+     for informing lisp of the new size immediately, while the actual
+     resize will happen asynchronously. But on Windows, the menu bar
+     automatically wraps when the frame is too narrow to contain it,
+     and that causes any calculations made here to come out wrong. The
+     end is some nasty buggy behaviour, including the potential loss
+     of the minibuffer.
+
+     Disabling this code is either not sufficient to fix the problems
+     completely, or it causes fresh problems, but at least it removes
+     the most problematic symptom of the minibuffer becoming unusable.
+
+     -----------------------------------------------------------------
+
+     Now, strictly speaking, we can't be sure that this is accurate,
      but the window manager will get around to dealing with the size
      change request eventually, and we'll hear how it went when the
      ConfigureNotify event gets here.
@@ -5546,6 +6166,7 @@ x_set_window_size (f, change_gravity, cols, rows)
      Actually checking whether it is outside is a pain in the neck,
      so don't try--just let the highlighting be done afresh with new size.  */
   cancel_mouse_face (f);
+#endif
 
   UNBLOCK_INPUT;
 }
@@ -5865,13 +6486,22 @@ x_free_frame_resources (f)
 
   BLOCK_INPUT;
 
+#ifdef USE_FONT_BACKEND
+      /* We must free faces before destroying windows because some
+        font-driver (e.g. xft) access a window while finishing a
+        face.  */
+      if (enable_font_backend
+         && FRAME_FACE_CACHE (f))
+       free_frame_faces (f);
+#endif /* USE_FONT_BACKEND */
+
   if (FRAME_W32_WINDOW (f))
     my_destroy_window (f, FRAME_W32_WINDOW (f));
 
   free_frame_menubar (f);
 
-  unload_color (f, f->output_data.x->foreground_pixel);
-  unload_color (f, f->output_data.x->background_pixel);
+  unload_color (f, FRAME_FOREGROUND_PIXEL (f));
+  unload_color (f, FRAME_BACKGROUND_PIXEL (f));
   unload_color (f, f->output_data.w32->cursor_pixel);
   unload_color (f, f->output_data.w32->cursor_foreground_pixel);
   unload_color (f, f->output_data.w32->border_pixel);
@@ -5910,14 +6540,13 @@ x_free_frame_resources (f)
 
 
 /* Destroy the window of frame F.  */
-
+void
 x_destroy_window (f)
      struct frame *f;
 {
   struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
 
   x_free_frame_resources (f);
-
   dpyinfo->reference_count--;
 }
 
@@ -6018,7 +6647,7 @@ x_font_min_bounds (font, w, h)
    * average and maximum width, and maximum height.
    */
   *h = FONT_HEIGHT (font);
-  *w = FONT_WIDTH (font);
+  *w = FONT_AVG_WIDTH (font);
 }
 
 
@@ -6124,7 +6753,7 @@ w32_initialize_display_info (display_name)
 
 /* Create an xrdb-style database of resources to supercede registry settings.
    The database is just a concatenation of C strings, finished by an additional
-   \0.  The string are submitted to some basic normalization, so
+   \0.  The strings are submitted to some basic normalization, so
 
      [ *]option[ *]:[ *]value...
 
@@ -6177,6 +6806,133 @@ w32_make_rdb (xrm_option)
   return buffer;
 }
 
+void
+x_flush (struct frame * f)
+{ /* Nothing to do */ }
+
+
+extern frame_parm_handler w32_frame_parm_handlers[];
+
+static struct redisplay_interface w32_redisplay_interface =
+{
+  w32_frame_parm_handlers,
+  x_produce_glyphs,
+  x_write_glyphs,
+  x_insert_glyphs,
+  x_clear_end_of_line,
+  x_scroll_run,
+  x_after_update_window_line,
+  x_update_window_begin,
+  x_update_window_end,
+  x_cursor_to,
+  x_flush,
+  0,  /* flush_display_optional */
+  x_clear_window_mouse_face,
+  w32_get_glyph_overhangs,
+  x_fix_overlapping_area,
+  w32_draw_fringe_bitmap,
+  w32_define_fringe_bitmap,
+  w32_destroy_fringe_bitmap,
+  w32_per_char_metric,
+  w32_encode_char,
+  NULL, /* w32_compute_glyph_string_overhangs */
+  x_draw_glyph_string,
+  w32_define_frame_cursor,
+  w32_clear_frame_area,
+  w32_draw_window_cursor,
+  w32_draw_vertical_window_border,
+  w32_shift_glyphs_for_insert
+};
+
+static void x_delete_terminal (struct terminal *term);
+
+static struct terminal *
+w32_create_terminal (struct w32_display_info *dpyinfo)
+{
+  struct terminal *terminal;
+
+  terminal = create_terminal ();
+
+  terminal->type = output_w32;
+  terminal->display_info.w32 = dpyinfo;
+  dpyinfo->terminal = terminal;
+
+  /* MSVC does not type K&R functions with no arguments correctly, and
+     so we must explicitly cast them.  */
+  terminal->clear_frame_hook = x_clear_frame;
+  terminal->ins_del_lines_hook = x_ins_del_lines;
+  terminal->delete_glyphs_hook = x_delete_glyphs;
+  terminal->ring_bell_hook = w32_ring_bell;
+  terminal->reset_terminal_modes_hook = w32_reset_terminal_modes;
+  terminal->set_terminal_modes_hook = w32_set_terminal_modes;
+  terminal->update_begin_hook = x_update_begin;
+  terminal->update_end_hook = x_update_end;
+  terminal->set_terminal_window_hook = w32_set_terminal_window;
+  terminal->read_socket_hook = w32_read_socket;
+  terminal->frame_up_to_date_hook = w32_frame_up_to_date;
+  terminal->mouse_position_hook = w32_mouse_position;
+  terminal->frame_rehighlight_hook = w32_frame_rehighlight;
+  terminal->frame_raise_lower_hook = w32_frame_raise_lower;
+  //  terminal->fullscreen_hook = XTfullscreen_hook;
+  terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
+  terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars;
+  terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar;
+  terminal->judge_scroll_bars_hook = w32_judge_scroll_bars;
+
+  terminal->delete_frame_hook = x_destroy_window;
+  terminal->delete_terminal_hook = x_delete_terminal;
+
+  terminal->rif = &w32_redisplay_interface;
+  terminal->scroll_region_ok = 1;    /* We'll scroll partial frames. */
+  terminal->char_ins_del_ok = 1;
+  terminal->line_ins_del_ok = 1;         /* We'll just blt 'em. */
+  terminal->fast_clear_end_of_line = 1;  /* X does this well. */
+  terminal->memory_below_frame = 0;   /* We don't remember what scrolls
+                                        off the bottom. */
+
+#ifdef MULTI_KBOARD
+  /* We don't yet support separate terminals on W32, so don't try to share
+     keyboards between virtual terminals that are on the same physical
+     terminal like X does.  */
+  terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
+  init_kboard (terminal->kboard);
+  terminal->kboard->Vwindow_system = intern ("w32");
+  terminal->kboard->next_kboard = all_kboards;
+  all_kboards = terminal->kboard;
+  /* Don't let the initial kboard remain current longer than necessary.
+     That would cause problems if a file loaded on startup tries to
+     prompt in the mini-buffer.  */
+  if (current_kboard == initial_kboard)
+    current_kboard = terminal->kboard;
+  terminal->kboard->reference_count++;
+#endif
+
+  return terminal;
+}
+
+static void
+x_delete_terminal (struct terminal *terminal)
+{
+  struct w32_display_info *dpyinfo = terminal->display_info.w32;
+  int i;
+
+  /* Protect against recursive calls.  Fdelete_frame in
+     delete_terminal calls us back when it deletes our last frame.  */
+  if (!terminal->name)
+    return;
+
+  BLOCK_INPUT;
+  /* Free the fonts in the font table.  */
+  for (i = 0; i < dpyinfo->n_fonts; i++)
+    if (dpyinfo->font_table[i].name)
+      {
+        DeleteObject (((XFontStruct*)(dpyinfo->font_table[i].font))->hfont);
+      }
+
+  x_delete_display (dpyinfo);
+  UNBLOCK_INPUT;
+}
+
 struct w32_display_info *
 w32_term_init (display_name, xrm_option, resource_name)
      Lisp_Object display_name;
@@ -6184,6 +6940,7 @@ w32_term_init (display_name, xrm_option, resource_name)
      char *resource_name;
 {
   struct w32_display_info *dpyinfo;
+  struct terminal *terminal;
   HDC hdc;
 
   BLOCK_INPUT;
@@ -6197,6 +6954,12 @@ w32_term_init (display_name, xrm_option, resource_name)
   w32_initialize_display_info (display_name);
 
   dpyinfo = &one_w32_display_info;
+  terminal = w32_create_terminal (dpyinfo);
+
+  /* Set the name of the terminal. */
+  terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
+  strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
+  terminal->name[SBYTES (display_name)] = 0;
 
   dpyinfo->xrdb = xrm_option ? w32_make_rdb (xrm_option) : NULL;
 
@@ -6226,6 +6989,9 @@ w32_term_init (display_name, xrm_option, resource_name)
     w32_defined_color (0, "black", &color, 1);
   }
 
+  /* Add the default keyboard.  */
+  add_keyboard_wait_descriptor (0);
+
   /* Create Fringe Bitmaps and store them for later use.
 
      On W32, bitmaps are all unsigned short, as Windows requires
@@ -6233,7 +6999,7 @@ w32_term_init (display_name, xrm_option, resource_name)
      horizontally reflected compared to how they appear on X, so we
      need to bitswap and convert to unsigned shorts before creating
      the bitmaps.  */
-  w32_init_fringe ();
+  w32_init_fringe (terminal->rif);
 
 #ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
@@ -6257,7 +7023,6 @@ w32_term_init (display_name, xrm_option, resource_name)
 }
 \f
 /* Get rid of display DPYINFO, assuming all frames are already gone.  */
-
 void
 x_delete_display (dpyinfo)
      struct w32_display_info *dpyinfo;
@@ -6308,73 +7073,9 @@ x_delete_display (dpyinfo)
 
 DWORD WINAPI w32_msg_worker (void * arg);
 
-void
-x_flush (struct frame * f)
-{ /* Nothing to do */ }
-
-extern frame_parm_handler w32_frame_parm_handlers[];
-
-static struct redisplay_interface w32_redisplay_interface =
-{
-  w32_frame_parm_handlers,
-  x_produce_glyphs,
-  x_write_glyphs,
-  x_insert_glyphs,
-  x_clear_end_of_line,
-  x_scroll_run,
-  x_after_update_window_line,
-  x_update_window_begin,
-  x_update_window_end,
-  x_cursor_to,
-  x_flush,
-  0,  /* flush_display_optional */
-  x_clear_window_mouse_face,
-  w32_get_glyph_overhangs,
-  x_fix_overlapping_area,
-  w32_draw_fringe_bitmap,
-  w32_define_fringe_bitmap,
-  w32_destroy_fringe_bitmap,
-  w32_per_char_metric,
-  w32_encode_char,
-  NULL, /* w32_compute_glyph_string_overhangs */
-  x_draw_glyph_string,
-  w32_define_frame_cursor,
-  w32_clear_frame_area,
-  w32_draw_window_cursor,
-  w32_draw_vertical_window_border,
-  w32_shift_glyphs_for_insert
-};
-
-void
+static void
 w32_initialize ()
 {
-  rif = &w32_redisplay_interface;
-
-  /* MSVC does not type K&R functions with no arguments correctly, and
-     so we must explicitly cast them.  */
-  clear_frame_hook = (void (*)(void)) x_clear_frame;
-  ring_bell_hook = (void (*)(void)) w32_ring_bell;
-  update_begin_hook = x_update_begin;
-  update_end_hook = x_update_end;
-
-  read_socket_hook = w32_read_socket;
-
-  frame_up_to_date_hook = w32_frame_up_to_date;
-
-  mouse_position_hook = w32_mouse_position;
-  frame_rehighlight_hook = w32_frame_rehighlight;
-  frame_raise_lower_hook = w32_frame_raise_lower;
-  set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
-  condemn_scroll_bars_hook = w32_condemn_scroll_bars;
-  redeem_scroll_bar_hook = w32_redeem_scroll_bar;
-  judge_scroll_bars_hook = w32_judge_scroll_bars;
-
-  scroll_region_ok = 1;         /* we'll scroll partial frames */
-  char_ins_del_ok = 1;
-  line_ins_del_ok = 1;          /* we'll just blt 'em */
-  fast_clear_end_of_line = 1;   /* X does this well */
-  memory_below_frame = 0;       /* we don't remember what scrolls
-                                  off the bottom */
   baud_rate = 19200;
 
   w32_system_caret_hwnd = NULL;
@@ -6429,13 +7130,22 @@ w32_initialize ()
   AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
 #endif
 
-  /* Load system settings.  */
+  /* Dynamically link to optional system components.  */
   {
     UINT smoothing_type;
     BOOL smoothing_enabled;
 
-    /* If using proportional scroll bars, ensure handle is at least 5 pixels;
-       otherwise use the fixed height.  */
+    HANDLE gdi_lib = LoadLibrary ("gdi32.dll");
+
+#define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
+
+    LOAD_PROC (gdi_lib, GetFontUnicodeRanges);
+    
+#undef LOAD_PROC
+
+    FreeLibrary (gdi_lib);
+
+    /* Ensure scrollbar handle is at least 5 pixels.  */
     vertical_scroll_bar_min_handle = 5;
 
     /* For either kind of scroll bar, take account of the arrows; these
@@ -6476,8 +7186,7 @@ syms_of_w32term ()
   staticpro (&last_mouse_scroll_bar);
   last_mouse_scroll_bar = Qnil;
 
-  staticpro (&Qvendor_specific_keysyms);
-  Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
+  DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
 
   DEFVAR_INT ("w32-num-mouse-buttons",
              &w32_num_mouse_buttons,
@@ -6517,7 +7226,7 @@ interpreted normally.  */);
 Unicode output may prevent some third party applications for displaying
 Far-East Languages on Windows 95/98 from working properly.
 NT uses Unicode internally anyway, so this flag will probably have no
-affect on NT machines.  */);
+effect on NT machines.  */);
   w32_enable_unicode_output = 1;
 
   DEFVAR_BOOL ("w32-use-visible-system-caret",