]> code.delx.au - gnu-emacs/blobdiff - src/w32term.c
Merge from emacs--devo--0
[gnu-emacs] / src / w32term.c
index f0ef42f798b85915e3e074dbcd3d92c2bd65d632..0a7007cc8f45b4334867ed64b3bcc30d7330356b 100644 (file)
@@ -24,25 +24,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"
@@ -53,9 +49,15 @@ 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"
+
+#include "w32heap.h"
+#include "w32bdf.h"
+#include <shellapi.h>
 
 #define abs(x) ((x) < 0 ? -(x) : (x))
 
@@ -116,6 +118,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.
@@ -146,32 +173,6 @@ HANDLE hWindowsThread = NULL;
 DWORD dwMainThreadId = 0;
 HANDLE hMainThread = NULL;
 
-#ifndef SIF_ALL
-/* These definitions are new with Windows 95. */
-#define SIF_RANGE           0x0001
-#define SIF_PAGE            0x0002
-#define SIF_POS             0x0004
-#define SIF_DISABLENOSCROLL 0x0008
-#define SIF_TRACKPOS        0x0010
-#define SIF_ALL             (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
-
-typedef struct tagSCROLLINFO
-{
-    UINT    cbSize;
-    UINT    fMask;
-    int     nMin;
-    int     nMax;
-    UINT    nPage;
-    int     nPos;
-    int     nTrackPos;
-}   SCROLLINFO, FAR *LPSCROLLINFO;
-typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
-#endif /* SIF_ALL */
-
-/* Dynamic linking to new proportional scroll bar functions. */
-int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
-BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
-
 int vertical_scroll_bar_min_handle;
 int vertical_scroll_bar_top_border;
 int vertical_scroll_bar_bottom_border;
@@ -843,7 +844,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.
@@ -1107,13 +1109,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;
@@ -1121,29 +1123,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.  */
@@ -1152,49 +1164,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;
+          int code = (int) (*char2b);
 
-          ENCODE_SJIS (XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b),
-                       sjis1, sjis2);
-          STORE_XCHAR2B (char2b, sjis1, sjis2);
-        }
-    }
-  codepage = font_info->codepage;
-
-  /* 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)
@@ -1213,6 +1201,143 @@ 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;
+
+  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)
+       char_table_set_range (table, min_byte2, max_byte2, 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)
+                   {
+                     char_table_set_range (table, from, i - 1, Qt);
+                     from = -1;
+                   }
+               }
+             else if (from < 0)
+               from = i;
+           }
+         if (from >= 0)
+           char_table_set_range (table, from, i - 1, Qt);
+       }
+    }
+  else
+    {
+      if (! font->per_char || font->all_chars_exist == True)
+       {
+         int i;
+
+         for (i = min_byte1; i <= max_byte1; i++)
+           char_table_set_range (table,
+                                 (i << 8) | min_byte2, (i << 8) | max_byte2,
+                                 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)
+                       {
+                         char_table_set_range (table, (i << 8) | from,
+                                               (i << 8) | (j - 1), Qt);
+                         from = -1;
+                       }
+                   }
+                 else if (from < 0)
+                   from = j;
+               }
+             if (from >= 0)
+               char_table_set_range (table, (i << 8) | from,
+                                     (i << 8) | (j - 1), Qt);
+           }
+       }
+    }
+#endif
+  return table;
+}
+
 \f
 /***********************************************************************
                            Glyph display
@@ -1342,9 +1467,9 @@ 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);
 
@@ -2389,20 +2514,29 @@ x_draw_stretch_glyph_string (s)
     {
       /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
         as wide as the stretch glyph.  */
-      int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
+      int width, background_width = s->background_width;
+      int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
+
+      if (x < left_x)
+       {
+         background_width -= left_x - x;
+         x = left_x;
+       }
+      width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
 
       /* Draw cursor.  */
-      x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
+      x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
 
       /* Clear rest using the GC of the original non-cursor face.  */
-      if (width < s->background_width)
+      if (width < background_width)
        {
          XGCValues *gc = s->face->gc;
-         int x = s->x + width, y = s->y;
-         int w = s->background_width - width, h = s->height;
+         int y = s->y;
+         int w = background_width - width, h = s->height;
          RECT r;
           HDC hdc = s->hdc;
 
+         x += width;
          if (s->row->mouse_face_p
              && cursor_in_mouse_face_p (s->w))
            {
@@ -2431,8 +2565,18 @@ x_draw_stretch_glyph_string (s)
         }
     }
   else if (!s->background_filled_p)
-    x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
-                                s->height);
+    {
+      int background_width = s->background_width;
+      int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
+
+      if (x < left_x)
+       {
+         background_width -= left_x - x;
+         x = left_x;
+       }
+      if (background_width > 0)
+       x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
+    }
 
   s->background_filled_p = 1;
 }
@@ -3131,8 +3275,10 @@ construct_mouse_wheel (result, msg, f)
   result->modifiers = (msg->dwModifiers
                        | ((delta < 0 ) ? down_modifier : up_modifier));
 
-  p.x = LOWORD (msg->msg.lParam);
-  p.y = HIWORD (msg->msg.lParam);
+  /* With multiple monitors, we can legitimately get negative
+     coordinates, so cast to short to interpret them correctly.  */
+  p.x = (short) LOWORD (msg->msg.lParam);
+  p.y = (short) HIWORD (msg->msg.lParam);
   ScreenToClient (msg->msg.hwnd, &p);
   XSETINT (result->x, p.x);
   XSETINT (result->y, p.y);
@@ -3466,6 +3612,7 @@ w32_set_scroll_bar_thumb (bar, portion, position, whole)
   double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
   int sb_page, sb_pos;
   BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
+  SCROLLINFO si;
 
   if (whole)
     {
@@ -3490,24 +3637,17 @@ w32_set_scroll_bar_thumb (bar, portion, position, whole)
 
   BLOCK_INPUT;
 
-  if (pfnSetScrollInfo)
-    {
-      SCROLLINFO si;
-
-      si.cbSize = sizeof (si);
-      /* Only update page size if currently dragging, to reduce
-         flicker effects.  */
-      if (draggingp)
-        si.fMask = SIF_PAGE;
-      else
-        si.fMask = SIF_PAGE | SIF_POS;
-      si.nPage = sb_page;
-      si.nPos = sb_pos;
-
-      pfnSetScrollInfo (w, SB_CTL, &si, !draggingp);
-    }
+  si.cbSize = sizeof (si);
+  /* Only update page size if currently dragging, to reduce
+     flicker effects.  */
+  if (draggingp)
+    si.fMask = SIF_PAGE;
   else
-    SetScrollPos (w, SB_CTL, sb_pos, !draggingp);
+    si.fMask = SIF_PAGE | SIF_POS;
+  si.nPage = sb_page;
+  si.nPos = sb_pos;
+
+  SetScrollInfo (w, SB_CTL, &si, !draggingp);
 
   UNBLOCK_INPUT;
 }
@@ -3596,6 +3736,7 @@ x_scroll_bar_create (w, top, left, width, height)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   HWND hwnd;
+  SCROLLINFO si;
   struct scroll_bar *bar
     = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
 
@@ -3614,26 +3755,15 @@ x_scroll_bar_create (w, top, left, width, height)
 
   hwnd = my_create_scrollbar (f, bar);
 
-  if (pfnSetScrollInfo)
-    {
-      SCROLLINFO si;
-
-      si.cbSize = sizeof (si);
-      si.fMask = SIF_ALL;
-      si.nMin = 0;
-      si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
-       + VERTICAL_SCROLL_BAR_MIN_HANDLE;
-      si.nPage = si.nMax;
-      si.nPos = 0;
+  si.cbSize = sizeof (si);
+  si.fMask = SIF_ALL;
+  si.nMin = 0;
+  si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
+    + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+  si.nPage = si.nMax;
+  si.nPos = 0;
 
-      pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
-    }
-  else
-    {
-      SetScrollRange (hwnd, SB_CTL, 0,
-                      VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
-      SetScrollPos (hwnd, SB_CTL, 0, FALSE);
-    }
+  SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
 
   SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
 
@@ -3742,6 +3872,8 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
       else
         {
           HDC hdc;
+         SCROLLINFO si;
+
           BLOCK_INPUT;
          if (width && height)
            {
@@ -3761,21 +3893,15 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
           MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
                      top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
                      max (height, 1), TRUE);
-          if (pfnSetScrollInfo)
-            {
-              SCROLLINFO si;
 
-              si.cbSize = sizeof (si);
-              si.fMask = SIF_RANGE;
-              si.nMin = 0;
-              si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
-                + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+         si.cbSize = sizeof (si);
+         si.fMask = SIF_RANGE;
+         si.nMin = 0;
+         si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
+           + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+
+         SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
 
-              pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
-            }
-          else
-            SetScrollRange (hwnd, SB_CTL, 0,
-                            VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
           my_show_window (f, hwnd, SW_NORMAL);
           /* InvalidateRect (w, NULL, FALSE);  */
 
@@ -3927,19 +4053,13 @@ w32_scroll_bar_handle_click (bar, msg, emacs_event)
     int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
     int y;
     int dragging = !NILP (bar->dragging);
+    SCROLLINFO si;
 
-    if (pfnGetScrollInfo)
-      {
-       SCROLLINFO si;
+    si.cbSize = sizeof (si);
+    si.fMask = SIF_POS;
 
-       si.cbSize = sizeof (si);
-       si.fMask = SIF_POS;
-
-       pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
-       y = si.nPos;
-      }
-    else
-      y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
+    GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
+    y = si.nPos;
 
     bar->dragging = Qnil;
 
@@ -3976,21 +4096,18 @@ w32_scroll_bar_handle_click (bar, msg, emacs_event)
        emacs_event->part = scroll_bar_handle;
 
        /* "Silently" update current position.  */
-       if (pfnSetScrollInfo)
-         {
-           SCROLLINFO si;
+       {
+         SCROLLINFO si;
 
-           si.cbSize = sizeof (si);
-           si.fMask = SIF_POS;
-           si.nPos = y;
-           /* Remember apparent position (we actually lag behind the real
-              position, so don't set that directly.  */
-           last_scroll_bar_drag_pos = y;
+         si.cbSize = sizeof (si);
+         si.fMask = SIF_POS;
+         si.nPos = y;
+         /* Remember apparent position (we actually lag behind the real
+            position, so don't set that directly.  */
+         last_scroll_bar_drag_pos = y;
 
-           pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
-         }
-       else
-         SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
+         SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
+       }
        break;
       case SB_ENDSCROLL:
        /* If this is the end of a drag sequence, then reset the scroll
@@ -3998,20 +4115,15 @@ w32_scroll_bar_handle_click (bar, msg, emacs_event)
           nothing.  */
        if (dragging)
          {
-           if (pfnSetScrollInfo)
-             {
-               SCROLLINFO si;
-               int start = XINT (bar->start);
-               int end = XINT (bar->end);
-
-               si.cbSize = sizeof (si);
-               si.fMask = SIF_PAGE | SIF_POS;
-                si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
-               si.nPos = last_scroll_bar_drag_pos;
-               pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
-             }
-           else
-             SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
+           SCROLLINFO si;
+           int start = XINT (bar->start);
+           int end = XINT (bar->end);
+
+           si.cbSize = sizeof (si);
+           si.fMask = SIF_PAGE | SIF_POS;
+           si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
+           si.nPos = last_scroll_bar_drag_pos;
+           SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
          }
        /* fall through */
       default:
@@ -4042,25 +4154,19 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
   FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   int pos;
   int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+  SCROLLINFO si;
 
   BLOCK_INPUT;
 
   *fp = f;
   *bar_window = bar->window;
 
-  if (pfnGetScrollInfo)
-    {
-      SCROLLINFO si;
+  si.cbSize = sizeof (si);
+  si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
 
-      si.cbSize = sizeof (si);
-      si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
-
-      pfnGetScrollInfo (w, SB_CTL, &si);
-      pos = si.nPos;
-      top_range = si.nMax - si.nPage + 1;
-    }
-  else
-    pos = GetScrollPos (w, SB_CTL);
+  GetScrollInfo (w, SB_CTL, &si);
+  pos = si.nPos;
+  top_range = si.nMax - si.nPage + 1;
 
   switch (LOWORD (last_mouse_scroll_bar_pos))
   {
@@ -4929,7 +5035,7 @@ x_draw_hollow_cursor (w, row)
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   HDC hdc;
   RECT rect;
-  int h;
+  int left, top, h;
   struct glyph *cursor_glyph;
   HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
 
@@ -4940,8 +5046,9 @@ x_draw_hollow_cursor (w, row)
     return;
 
   /* Compute frame-relative coordinates for phys cursor.  */
-  rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
-  rect.top = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
+  get_phys_cursor_geometry (w, row, cursor_glyph, &left, &top, &h);
+  rect.left = left;
+  rect.top = top;
   rect.bottom = rect.top + h;
   rect.right = rect.left + w->phys_cursor_width;
 
@@ -5260,11 +5367,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;
@@ -5298,37 +5410,49 @@ 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);
 }
 
 \f
@@ -6390,18 +6514,21 @@ w32_initialize ()
   /* Dynamically link to optional system components. */
   {
     HANDLE user_lib = LoadLibrary ("user32.dll");
+    HANDLE gdi_lib = LoadLibrary ("gdi32.dll");
     UINT smoothing_type;
     BOOL smoothing_enabled;
 
-#define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
+#define LOAD_PROC(lib, fn) pfn##fn = (void *) GetProcAddress (lib, #fn)
 
     /* New proportional scroll bar functions. */
-    LOAD_PROC (SetScrollInfo);
-    LOAD_PROC (GetScrollInfo);
-
+    LOAD_PROC (user_lib, SetScrollInfo);
+    LOAD_PROC (user_lib, GetScrollInfo);
+    LOAD_PROC (gdi_lib, GetFontUnicodeRanges);
+    
 #undef LOAD_PROC
 
     FreeLibrary (user_lib);
+    FreeLibrary (gdi_lib);
 
     /* If using proportional scroll bars, ensure handle is at least 5 pixels;
        otherwise use the fixed height.  */