]> code.delx.au - gnu-emacs/blobdiff - src/w32term.c
2002-08-10 Andrew Choi <akochoi@shaw.ca>
[gnu-emacs] / src / w32term.c
index 1fe99c75acc79dcb411a8191d848d2ffea43f040..c9628277a470470b1c5a4c29fa05d5d05e96bcac 100644 (file)
@@ -62,11 +62,11 @@ Boston, MA 02111-1307, USA.  */
 #define BETWEEN(X, LOWER, UPPER)  ((X) >= (LOWER) && (X) < (UPPER))
 
 \f
-/* Bitmaps for truncated lines.  */
+/* Fringe bitmaps.  */
 
-enum bitmap_type
+enum fringe_bitmap_type
 {
-  NO_BITMAP,
+  NO_FRINGE_BITMAP,
   LEFT_TRUNCATION_BITMAP,
   RIGHT_TRUNCATION_BITMAP,
   OVERLAY_ARROW_BITMAP,
@@ -84,9 +84,17 @@ enum bitmap_type
    `indicate-empty-lines' is non-nil.  */
 
 #define zv_width 8
-#define zv_height 8
+#define zv_height 72
+#define zv_period 3
 static unsigned short zv_bits[] = {
-   0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00};
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
 static HBITMAP zv_bmp;
 
 /* An arrow like this: `<-'.  */
@@ -162,6 +170,10 @@ static Lisp_Object previous_help_echo;
 
 static int any_help_event_p;
 
+/* Non-zero means autoselect window with the mouse cursor.  */
+
+int mouse_autoselect_window;
+
 /* Non-zero means draw block and hollow cursor as wide as the glyph
    under it.  For example, if a block cursor is over a tab, it will be
    drawn as wide as that tab on the display.  */
@@ -176,8 +188,6 @@ extern unsigned int msh_mousewheel;
 
 extern void free_frame_menubar ();
 
-extern void w32_menu_display_help (HMENU menu, UINT menu_item, UINT flags);
-
 extern int w32_codepage_for_font (char *fontname);
 
 extern glyph_metric *w32_BDF_TextMetric(bdffont *fontp,
@@ -214,6 +224,13 @@ struct frame *pending_autoraise_frame;
 
 struct cursor_pos output_cursor;
 
+/* The handle of the frame that currently owns the system caret.  */
+HWND w32_system_caret_hwnd;
+int w32_system_caret_height;
+int w32_system_caret_x;
+int w32_system_caret_y;
+int w32_use_visible_system_caret;
+
 /* Flag to enable Unicode output in case users wish to use programs
    like Twinbridge on '95 rather than installed system level support
    for Far East languages.  */
@@ -316,7 +333,7 @@ extern int errno;
 
 /* A mask of extra modifier bits to put into every keyboard char.  */
 
-extern int extra_keyboard_modifiers;
+extern EMACS_INT extra_keyboard_modifiers;
 
 /* Enumeration for overriding/changing the face to use for drawing
    glyphs in x_draw_glyphs.  */
@@ -375,12 +392,13 @@ static void x_clear_frame P_ ((void));
 static void x_clear_cursor P_ ((struct window *));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
-static void w32_new_focus_frame P_ ((struct w32_display_info *,
-                                     struct frame *));
+static void x_new_focus_frame P_ ((struct w32_display_info *,
+                                  struct frame *));
 static void w32_frame_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct w32_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
-static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
+static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
+                                  enum text_cursor_kinds));
 static void expose_frame P_ ((struct frame *, int, int, int, int));
 static int expose_window_tree P_ ((struct window *, RECT *));
 static int expose_window P_ ((struct window *, RECT *));
@@ -394,13 +412,17 @@ static void x_update_window_cursor P_ ((struct window *, int));
 static void x_erase_phys_cursor P_ ((struct window *));
 void x_display_cursor P_ ((struct window *w, int, int, int, int, int));
 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
-static void w32_draw_bitmap P_ ((struct window *, HDC hdc, struct glyph_row *, 
-                                 enum bitmap_type));
+static void w32_draw_fringe_bitmap P_ ((struct window *, HDC hdc,
+                                       struct glyph_row *, 
+                                       enum fringe_bitmap_type, int left_p));
 static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
                                  HDC, int));
 static int x_phys_cursor_in_rect_p P_ ((struct window *, RECT *));
-static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
-static void note_overwritten_text_cursor P_ ((struct window *, int, int));
+static void x_draw_row_fringe_bitmaps P_ ((struct window *,
+                                          struct glyph_row *));
+static void notice_overwritten_cursor P_ ((struct window *,
+                                          enum glyph_row_area,
+                                          int, int, int, int));
 
 static Lisp_Object Qvendor_specific_keysyms;
 
@@ -576,6 +598,10 @@ x_update_window_begin (w)
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
 
+  /* Hide the system caret during an update.  */
+  if (w32_use_visible_system_caret)
+    SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
+
   updated_window = w;
   set_output_cursor (&w->cursor);
 
@@ -643,7 +669,7 @@ x_draw_vertical_border (w)
 
       window_box_edges (w, -1, (int *) &r.left, (int *) &r.top,
                        (int *) &r.right, (int *) &r.bottom);
-      r.left = r.right + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
+      r.left = r.right + FRAME_X_RIGHT_FRINGE_WIDTH (f);
       r.right = r.left + 1;
       r.bottom -= 1;
 
@@ -697,6 +723,12 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
       dpyinfo->mouse_face_window = Qnil;
     }
 
+  /* Unhide the caret.  This won't actually show the cursor, unless it
+     was visible before the corresponding call to HideCaret in
+     x_update_window_begin.  */
+  if (w32_use_visible_system_caret)
+    SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
+
   updated_window = NULL;
 }
 
@@ -743,9 +775,9 @@ w32_frame_up_to_date (f)
 
 
 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
-   arrow bitmaps, or clear the areas where they would be displayed
+   arrow bitmaps, or clear the fringes if no bitmaps are required
    before DESIRED_ROW is made current.  The window being updated is
-   found in updated_window.  This function It is called from
+   found in updated_window.  This function is called from
    update_window_line only if it is known that there are differences
    between bitmaps to be drawn between current row and DESIRED_ROW.  */
 
@@ -754,55 +786,69 @@ x_after_update_window_line (desired_row)
      struct glyph_row *desired_row;
 {
   struct window *w = updated_window;
-  
+  struct frame *f;
+  int width, height;
+
   xassert (w);
   
   if (!desired_row->mode_line_p && !w->pseudo_window_p)
     {
-      struct frame *f;
-      int width;
+      BLOCK_INPUT;
+      x_draw_row_fringe_bitmaps (w, desired_row);
+      UNBLOCK_INPUT;
+    }
+
+  /* When a window has disappeared, make sure that no rest of
+     full-width rows stays visible in the internal border.  Could
+     check here if updated_window is the leftmost/rightmost window,
+     but I guess it's not worth doing since vertically split windows
+     are almost never used, internal border is rarely set, and the
+     overhead is very small.  */
+  if (windows_or_buffers_changed
+      && desired_row->full_width_p
+      && (f = XFRAME (w->frame),
+         width = FRAME_INTERNAL_BORDER_WIDTH (f),
+         width != 0)
+      && (height = desired_row->visible_height,
+         height > 0))
+    {
+      int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
+      /* Internal border is drawn below the tool bar.  */
+      if (WINDOWP (f->tool_bar_window)
+         && w == XWINDOW (f->tool_bar_window))
+       y -= width;
 
       BLOCK_INPUT;
-      x_draw_row_bitmaps (w, desired_row);
-
-      /* When a window has disappeared, make sure that no rest of
-        full-width rows stays visible in the internal border.  */
-      if (windows_or_buffers_changed
-          && (f = XFRAME (w->frame),
-              width = FRAME_INTERNAL_BORDER_WIDTH (f),
-              width != 0))
-       {
-         int height = desired_row->visible_height;
-         int x = (window_box_right (w, -1)
-                   + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
-         int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
-          HDC hdc = get_frame_dc (f);
-
-          w32_clear_area (f, hdc, x, y, width, height);
-          release_frame_dc (f, hdc);
-       }
-      
+      {
+       HDC hdc = get_frame_dc (f);
+       w32_clear_area (f, hdc, 0, y, width, height);
+       w32_clear_area (f, hdc, f->output_data.w32->pixel_width - width,
+                       y, width, height);
+       release_frame_dc (f, hdc);
+      }
       UNBLOCK_INPUT;
     }
 }
 
 
-/* Draw the bitmap WHICH in one of the areas to the left or right of
+/* Draw the bitmap WHICH in one of the left or right fringes of
    window W.  ROW is the glyph row for which to display the bitmap; it
    determines the vertical position at which the bitmap has to be
    drawn.  */
 
 static void
-w32_draw_bitmap (w, hdc, row, which)
+w32_draw_fringe_bitmap (w, hdc, row, which, left_p)
      struct window *w;
      HDC hdc;
      struct glyph_row *row;
-     enum bitmap_type which;
+     enum fringe_bitmap_type which;
+     int left_p;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   Window window = FRAME_W32_WINDOW (f);
   HDC compat_hdc;
   int x, y, wd, h, dy;
+  int b1, b2;
   HBITMAP pixmap;
   HANDLE horig_obj;
   struct face *face;
@@ -810,71 +856,118 @@ w32_draw_bitmap (w, hdc, row, which)
   /* Must clip because of partially visible lines.  */
   w32_clip_to_row (w, row, hdc, 1);
 
+  /* Convert row to frame coordinates.  */
+  y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+
   switch (which)
     {
+    case NO_FRINGE_BITMAP:
+      wd = 0;
+      h = 0;
+      break;
+
     case LEFT_TRUNCATION_BITMAP:
       wd = left_width;
       h = left_height;
       pixmap = left_bmp;
-      x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
-          - wd
-          - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
       break;
       
     case OVERLAY_ARROW_BITMAP:
       wd = ov_width;
       h = ov_height;
       pixmap = ov_bmp;
-      x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
-          - wd
-          - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
       break;
       
     case RIGHT_TRUNCATION_BITMAP:
       wd = right_width;
       h = right_height;
       pixmap = right_bmp;
-      x = window_box_right (w, -1);
-      x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
       break;
 
     case CONTINUED_LINE_BITMAP:
       wd = continued_width;
       h = continued_height;
       pixmap = continued_bmp;
-      x = window_box_right (w, -1);
-      x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
       break;
       
     case CONTINUATION_LINE_BITMAP:
       wd = continuation_width;
       h = continuation_height;
       pixmap = continuation_bmp;
-      x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
-          - wd
-          - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
       break;
 
     case ZV_LINE_BITMAP:
       wd = zv_width;
-      h = zv_height;
+      h = zv_height - (y % zv_period);
       pixmap = zv_bmp;
-      x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
-          - wd
-          - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
       break;
 
     default:
       abort ();
     }
 
-  /* Convert to frame coordinates.  Set dy to the offset in the row to
-     start drawing the bitmap.  */
-  y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+  /* Clip bitmap if too high.  */
+  if (h > row->height)
+    h = row->height;
+
+  /* Set dy to the offset in the row to start drawing the bitmap.  */
   dy = (row->height - h) / 2;
 
   /* Draw the bitmap.  */
-  face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
+  face = FACE_FROM_ID (f, FRINGE_FACE_ID);
+  PREPARE_FACE_FOR_DISPLAY (f, face);
+
+  /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
+     the fringe.  */
+  b1 = -1;
+  if (left_p)
+    {
+      if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
+       wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
+      x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
+          - wd
+          - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
+      if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
+       {
+         /* If W has a vertical border to its left, don't draw over it.  */
+         int border = ((XFASTINT (w->left) > 0
+                        && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+                       ? 1 : 0);
+         b1 = (window_box_left (w, -1)
+               - FRAME_X_LEFT_FRINGE_WIDTH (f)
+               + border);
+         b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
+       }
+    }
+  else
+    {
+      if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
+       wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+      x = (window_box_right (w, -1)
+          + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
+      /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
+        the fringe.  */
+      if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
+       {
+         b1 = window_box_right (w, -1);
+         b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+       }
+    }
+
+  if (b1 >= 0)
+    {
+      int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+      
+      w32_fill_area (f, hdc, face->background,
+                     b1,
+                     WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
+                                                      row->y)),
+                     b2,
+                     row->visible_height);
+    }
+
+  if (which == NO_FRINGE_BITMAP)
+    return;
 
   compat_hdc = CreateCompatibleDC (hdc);
   SaveDC (hdc);
@@ -883,7 +976,9 @@ w32_draw_bitmap (w, hdc, row, which)
   SetTextColor (hdc, face->background);
   SetBkColor (hdc, face->foreground);
 
-  BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, SRCCOPY);
+  BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0,
+         (which == ZV_LINE_BITMAP ? (row->y % zv_period) : 0),
+         SRCCOPY);
 
   SelectObject (compat_hdc, horig_obj);
   DeleteDC (compat_hdc);
@@ -891,18 +986,16 @@ w32_draw_bitmap (w, hdc, row, which)
 }
 
 
-/* Draw flags bitmaps for glyph row ROW on window W.  Call this
+/* Draw fringe bitmaps for glyph row ROW on window W.  Call this
    function with input blocked.  */
 
 static void
-x_draw_row_bitmaps (w, row)
+x_draw_row_fringe_bitmaps (w, row)
      struct window *w;
      struct glyph_row *row;
 {
   struct frame *f = XFRAME (w->frame);
-  enum bitmap_type bitmap;
-  struct face *face;
-  int header_line_height = -1;
+  enum fringe_bitmap_type bitmap;
   HDC hdc;
 
   xassert (interrupt_input_blocked);
@@ -912,81 +1005,40 @@ x_draw_row_bitmaps (w, row)
   if (row->visible_height <= 0)
     return;
 
-  face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
-  PREPARE_FACE_FOR_DISPLAY (f, face);
-
-  /* Decide which bitmap to draw at the left side.  */
-  if (row->overlay_arrow_p)
-    bitmap = OVERLAY_ARROW_BITMAP;
-  else if (row->truncated_on_left_p)
-    bitmap = LEFT_TRUNCATION_BITMAP;
-  else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
-    bitmap = CONTINUATION_LINE_BITMAP;
-  else if (row->indicate_empty_line_p)
-    bitmap = ZV_LINE_BITMAP;
-  else
-    bitmap = NO_BITMAP;
-
   hdc = get_frame_dc (f);
 
-  /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
-     the flags area.  */
-  if (bitmap == NO_BITMAP
-      || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
-      || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
-    {
-      /* If W has a vertical border to its left, don't draw over it.  */
-      int border = ((XFASTINT (w->left) > 0
-                    && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
-                   ? 1 : 0);
-      int left = window_box_left (w, -1);
+  if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
+    {
+      /* Decide which bitmap to draw in the left fringe.  */
+      if (row->overlay_arrow_p)
+       bitmap = OVERLAY_ARROW_BITMAP;
+      else if (row->truncated_on_left_p)
+       bitmap = LEFT_TRUNCATION_BITMAP;
+      else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
+       bitmap = CONTINUATION_LINE_BITMAP;
+      else if (row->indicate_empty_line_p)
+       bitmap = ZV_LINE_BITMAP;
+      else
+       bitmap = NO_FRINGE_BITMAP;
 
-      if (header_line_height < 0)
-       header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
-      
-      w32_fill_area (f, hdc, face->background,
-                     left - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) + border,
-                     WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
-                                                      row->y)),
-                     FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
-                     row->visible_height);
+      w32_draw_fringe_bitmap (w, hdc, row, bitmap, 1);
     }
 
-  /* Draw the left bitmap.  */
-  if (bitmap != NO_BITMAP)
-    w32_draw_bitmap (w, hdc, row, bitmap);
-
-  /* Decide which bitmap to draw at the right side.  */
-  if (row->truncated_on_right_p)
-    bitmap = RIGHT_TRUNCATION_BITMAP;
-  else if (row->continued_p)
-    bitmap = CONTINUED_LINE_BITMAP;
-  else
-    bitmap = NO_BITMAP;
-
-  /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
-     the flags area.  */
-  if (bitmap == NO_BITMAP
-      || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
-      || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
+  if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
     {
-      int right = window_box_right (w, -1);
-
-      if (header_line_height < 0)
-       header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+      /* Decide which bitmap to draw in the right fringe.  */
+      if (row->truncated_on_right_p)
+       bitmap = RIGHT_TRUNCATION_BITMAP;
+      else if (row->continued_p)
+       bitmap = CONTINUED_LINE_BITMAP;
+      else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
+       bitmap = ZV_LINE_BITMAP;
+      else
+       bitmap = NO_FRINGE_BITMAP;
 
-      w32_fill_area (f, hdc, face->background,
-                     right,
-                     WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
-                                                      row->y)),
-                     FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
-                     row->visible_height);
+      w32_draw_fringe_bitmap (w, hdc, row, bitmap, 0);
     }
 
-  /* Draw the right bitmap.  */
-  if (bitmap != NO_BITMAP)
-    w32_draw_bitmap (w, hdc, row, bitmap);
-
   release_frame_dc (f, hdc);
 }
 
@@ -1173,9 +1225,24 @@ w32_native_per_char_metric (font, char2b, font_type, pcm)
 
       if (retval)
        {
+#if 0
+         /* Disabled until we can find a way to get the right results
+            on all versions of Windows.  */
+
+         /* Don't trust the ABC widths.  For synthesized fonts they are
+            wrong, and so is the result of GetCharWidth()!  */
+         int real_width;
+         GetCharWidth (hdc, *char2b, *char2b, &real_width);
+#endif
          pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
+#if 0
+         /* As far as I can tell, this is the best way to determine what
+            ExtTextOut will do with the broken font.  */
+         if (pcm->width != real_width)
+           pcm->width = (pcm->width + real_width) / 2;
+#endif
          pcm->lbearing = char_widths.abcA;
-         pcm->rbearing = pcm->width - char_widths.abcC;
+         pcm->rbearing = char_widths.abcA + char_widths.abcB;
          pcm->ascent = FONT_BASE (font);
          pcm->descent = FONT_DESCENT (font);
        }
@@ -1778,7 +1845,7 @@ x_append_stretch_glyph (it, object, width, height, ascent)
    4. `:height HEIGHT' specifies that the height of the stretch produced
    should be HEIGHT, measured in canonical character units.
 
-   5. `:relative-height FACTOR' specifies that the height of the the
+   5. `:relative-height FACTOR' specifies that the height of the
    stretch should be FACTOR times the height of the characters having
    the glyph property.
 
@@ -2669,7 +2736,8 @@ struct glyph_string
 
 /* Encapsulate the different ways of displaying text under W32.  */
 
-void W32_TEXTOUT (s, x, y,chars,nchars)
+static void
+w32_text_out (s, x, y,chars,nchars)
      struct glyph_string * s;
      int x, y;
      wchar_t * chars;
@@ -2683,8 +2751,8 @@ void W32_TEXTOUT (s, x, y,chars,nchars)
   else if (s->first_glyph->w32_font_type == UNICODE_FONT)
     ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
   else
-    ExtTextOut (s->hdc, x, y, 0, NULL, (char *) chars,
-                nchars * charset_dim, NULL);
+    ExtTextOutA (s->hdc, x, y, 0, NULL, (char *) chars,
+                nchars * charset_dim, NULL);
 }
 
 #if GLYPH_DEBUG
@@ -2735,7 +2803,7 @@ static void w32_init_glyph_string P_ ((struct glyph_string *, HDC hdc,
                                        enum draw_glyphs_face));
 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
                              enum glyph_row_area, int, int,
-                             enum draw_glyphs_face, int *, int *, int));
+                             enum draw_glyphs_face, int));
 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
@@ -3417,7 +3485,7 @@ x_draw_glyph_string_foreground (s)
           char1b[i] = BYTE2 (s->char2b[i]);
 
       /* Draw text with TextOut and friends. */
-      W32_TEXTOUT (s, x, s->ybase - boff, s->char2b, s->nchars);
+      w32_text_out (s, x, s->ybase - boff, s->char2b, s->nchars);
     }
   if (s->font && s->font->hfont)
     SelectObject (s->hdc, old_font);
@@ -3464,7 +3532,7 @@ x_draw_composite_glyph_string_foreground (s)
   else
     {
       for (i = 0; i < s->nchars; i++, ++s->gidx)
-          W32_TEXTOUT (s, x + s->cmp->offsets[s->gidx * 2],
+          w32_text_out (s, x + s->cmp->offsets[s->gidx * 2],
                        s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
                        s->char2b + i, 1);
     }
@@ -3612,6 +3680,10 @@ x_setup_relief_colors (s)
 
   if (s->face->use_box_color_for_shadows_p)
     color = s->face->box_color;
+  else if (s->first_glyph->type == IMAGE_GLYPH
+          && s->img->pixmap
+          && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
+    color = IMAGE_BACKGROUND  (s->img, s->f, 0);
   else
     color = s->gc->background;
 
@@ -3657,14 +3729,14 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   for (i = 0; i < width; ++i)
     w32_fill_area (f, hdc, gc.foreground,
                   left_x + i * left_p, top_y + i,
-                  (right_x + 1 - i * right_p) - (left_x + i * left_p), 1);
+                  right_x - left_x - i * (left_p + right_p ) + 1, 1);
 
   /* Left.  */
   if (left_p)
     for (i = 0; i < width; ++i)
       w32_fill_area (f, hdc, gc.foreground,
                     left_x + i, top_y + i, 1,
-                    (bottom_y - i + 1) - (top_y + i));
+                    bottom_y - top_y - 2 * i + 1);
 
   if (raised_p)
     gc.foreground = f->output_data.w32->black_relief.gc->foreground;
@@ -3675,14 +3747,14 @@ w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
   for (i = 0; i < width; ++i)
     w32_fill_area (f, hdc, gc.foreground, 
                   left_x + i * left_p, bottom_y - i,
-                  (right_x + 2 - i * right_p) - (left_x + i * left_p), 1);
+                  right_x - left_x - i * (left_p + right_p) + 1, 1);
 
   /* Right.  */
   if (right_p)
     for (i = 0; i < width; ++i)
       w32_fill_area (f, hdc, gc.foreground,
                     right_x - i, top_y + i + 1, 1,
-                    (bottom_y - i) - (top_y + i + 1));
+                    bottom_y - top_y - 2 * i - 1);
 
   w32_set_clip_rectangle (hdc, NULL);
   
@@ -3747,7 +3819,7 @@ x_draw_glyph_string_box (s)
   if (s->row->full_width_p
       && !s->w->pseudo_window_p)
     {
-      last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
+      last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
       if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
        last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
     }
@@ -3875,8 +3947,12 @@ x_draw_image_foreground (s)
             the image.  I believe it's looking better if we do
             nothing here for mouse-face.  */
          if (s->hl == DRAW_CURSOR)
-            w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width - 1,
-                                s->img->height - 1);
+           {
+             int r = s->img->relief;
+             if (r < 0) r = -r;
+             w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
+                                 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+           }
           w32_set_clip_rectangle (s->hdc, NULL);
        }
     }
@@ -3916,7 +3992,7 @@ x_draw_image_relief (s)
   if (s->hl == DRAW_IMAGE_SUNKEN
       || s->hl == DRAW_IMAGE_RAISED)
     {
-      thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
+      thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
       raised_p = s->hl == DRAW_IMAGE_RAISED;
     }
   else
@@ -4016,8 +4092,12 @@ w32_draw_image_foreground_1 (s, pixmap)
             the image.  I believe it's looking better if we do
             nothing here for mouse-face.  */
          if (s->hl == DRAW_CURSOR)
-            w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
-                                s->img->height - 1);
+           {
+             int r = s->img->relief;
+             if (r < 0) r = -r;
+             w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
+                                 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
+           }
        }
     }
   else
@@ -4640,7 +4720,9 @@ x_set_glyph_string_background_width (s, start, last_x)
               || s->face->background != default_face->background
               || s->face->stipple != default_face->stipple
               || s->row->mouse_face_p))
-         || s->hl == DRAW_MOUSE_FACE))
+         || s->hl == DRAW_MOUSE_FACE
+         || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
+             && s->row->fill_line_p)))
     s->extends_to_end_of_line_p = 1;
   
   /* If S extends its face to the end of the line, set its
@@ -4842,27 +4924,19 @@ x_set_glyph_string_background_width (s, start, last_x)
    DRAW_IMAGE_SUNKEN   draw an image with a sunken relief around it
    DRAW_IMAGE_RAISED   draw an image with a raised relief around it
 
-   If REAL_START is non-null, return in *REAL_START the real starting
-   position for display.  This can be different from START in case
-   overlapping glyphs must be displayed.  If REAL_END is non-null,
-   return in *REAL_END the real end position for display.  This can be
-   different from END in case overlapping glyphs must be displayed.
-
    If OVERLAPS_P is non-zero, draw only the foreground of characters
    and clip to the physical height of ROW.
 
    Value is the x-position reached, relative to AREA of W.  */
      
 static int
-x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
-               overlaps_p)
+x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
      struct window *w;
      int x;
      struct glyph_row *row;
      enum glyph_row_area area;
      int start, end;
      enum draw_glyphs_face hl;
-     int *real_start, *real_end;
      int overlaps_p;
 {
   struct glyph_string *head, *tail;
@@ -4876,19 +4950,14 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
   end = min (end, row->used[area]);
   start = max (0, start);
   start = min (end, start);
-  if (real_start)
-    *real_start = start;
-  if (real_end)
-    *real_end = end;
 
   /* Translate X to frame coordinates.  Set last_x to the right
      end of the drawing area.  */
   if (row->full_width_p)
     {
       /* X is relative to the left edge of W, without scroll bars
-        or flag areas.  */
+        or fringes.  */
       struct frame *f = XFRAME (WINDOW_FRAME (w));
-      /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
       int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
 
       x += window_left_x;
@@ -4951,8 +5020,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
                               DRAW_NORMAL_TEXT, dummy_x, last_x,
                                overlaps_p);
          start = i;
-         if (real_start)
-           *real_start = start;
          x_compute_overhangs_and_x (t, head->x, 1);
          x_prepend_glyph_string_lists (&head, &tail, h, t);
        }
@@ -4972,8 +5039,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
                                overlaps_p);
          for (s = h; s; s = s->next)
            s->background_filled_p = 1;
-         if (real_start)
-           *real_start = i;
          x_compute_overhangs_and_x (t, head->x, 1);
          x_prepend_glyph_string_lists (&head, &tail, h, t);
        }
@@ -4990,8 +5055,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
                                overlaps_p);
          x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
          x_append_glyph_string_lists (&head, &tail, h, t);
-         if (real_end)
-           *real_end = i;
        }
 
       /* Append glyph strings for glyphs following the last glyph
@@ -5009,8 +5072,6 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
            s->background_filled_p = 1;
          x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
          x_append_glyph_string_lists (&head, &tail, h, t);
-         if (real_end)
-           *real_end = i;
        }
     }
 
@@ -5018,6 +5079,30 @@ x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
   for (s = head; s; s = s->next)
     x_draw_glyph_string (s);
 
+  if (area == TEXT_AREA
+      && !row->full_width_p
+      /* When drawing overlapping rows, only the glyph strings'
+        foreground is drawn, which doesn't erase a cursor
+        completely. */
+      && !overlaps_p)
+    {
+      int x0 = head ? head->x : x;
+      int x1 = tail ? tail->x + tail->background_width : x;
+      
+      x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
+      x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
+      
+      if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
+       {
+         int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
+         x0 -= left_area_width;
+         x1 -= left_area_width;
+       }
+
+      notice_overwritten_cursor (w, area, x0, x1,
+                                row->y, MATRIX_ROW_BOTTOM_Y (row));
+    }
+
   /* Value is the x-position up to which drawn, relative to AREA of W.
      This doesn't include parts drawn because of overhangs.  */
   x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
@@ -5070,8 +5155,7 @@ x_fix_overlapping_area (w, row, area)
                 && row->glyphs[area][i].overlaps_vertically_p);
 
          x_draw_glyphs (w, start_x, row, area, start, i,
-                        DRAW_NORMAL_TEXT,
-                        NULL, NULL, 1);
+                        DRAW_NORMAL_TEXT, 1);
        }
       else
        {
@@ -5095,7 +5179,7 @@ x_write_glyphs (start, len)
      struct glyph *start;
      int len;
 {
-  int x, hpos, real_start, real_end;
+  int x, hpos;
 
   xassert (updated_window && updated_row);
   BLOCK_INPUT;
@@ -5106,12 +5190,7 @@ x_write_glyphs (start, len)
   x = x_draw_glyphs (updated_window, output_cursor.x,
                     updated_row, updated_area,
                     hpos, hpos + len,
-                    DRAW_NORMAL_TEXT,
-                    &real_start, &real_end, 0);
-
-  /* If we drew over the cursor, note that it is not visible any more.  */
-  note_overwritten_text_cursor (updated_window, real_start,
-                               real_end - real_start);
+                    DRAW_NORMAL_TEXT, 0);
 
   UNBLOCK_INPUT;
   
@@ -5133,7 +5212,7 @@ x_insert_glyphs (start, len)
   int line_height, shift_by_width, shifted_region_width;
   struct glyph_row *row;
   struct glyph *glyph;
-  int frame_x, frame_y, hpos, real_start, real_end;
+  int frame_x, frame_y, hpos;
   HDC hdc;
 
   xassert (updated_window && updated_row);
@@ -5166,9 +5245,8 @@ x_insert_glyphs (start, len)
   /* Write the glyphs.  */
   hpos = start - row->glyphs[updated_area];
   x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
-                DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
-  note_overwritten_text_cursor (w, real_start, real_end - real_start);
-  
+                DRAW_NORMAL_TEXT, 0);
+
   /* Advance the output cursor.  */
   output_cursor.hpos += len;
   output_cursor.x += shift_by_width;
@@ -5242,10 +5320,13 @@ x_clear_end_of_line (to_x)
   
   /* Notice if the cursor will be cleared by this operation.  */
   if (!updated_row->full_width_p)
-    note_overwritten_text_cursor (w, output_cursor.hpos, -1);
+    notice_overwritten_cursor (w, updated_area,
+                              output_cursor.x, -1,
+                              updated_row->y,
+                              MATRIX_ROW_BOTTOM_Y (updated_row));
 
   from_x = output_cursor.x;
-     
+
   /* Translate to frame coordinates.  */
   if (updated_row->full_width_p)
     {
@@ -5390,14 +5471,15 @@ x_scroll_run (w, run)
 {
   struct frame *f = XFRAME (w->frame);
   int x, y, width, height, from_y, to_y, bottom_y;
-  HDC hdc = get_frame_dc (f);
+  HWND hwnd = FRAME_W32_WINDOW (f);
+  HRGN expect_dirty;
 
   /* Get frame-relative bounding box of the text display area of W,
-     without mode lines.  Include in this box the flags areas to the
-     left and right of W.  */
+     without mode lines.  Include in this box the left and right
+     fringes of W.  */
   window_box (w, -1, &x, &y, &width, &height);
-  width += FRAME_X_FLAGS_AREA_WIDTH (f);
-  x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
+  width += FRAME_X_FRINGE_WIDTH (f);
+  x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
 
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
@@ -5411,6 +5493,7 @@ x_scroll_run (w, run)
        height = bottom_y - from_y;
       else
        height = run->height;
+      expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
     }
   else
     {
@@ -5420,6 +5503,7 @@ x_scroll_run (w, run)
        height = bottom_y - to_y;
       else
        height = run->height;
+      expect_dirty = CreateRectRgn (x, y, x + width, to_y);
     }
 
   BLOCK_INPUT;
@@ -5428,10 +5512,32 @@ x_scroll_run (w, run)
   updated_window = w;
   x_clear_cursor (w);
 
-  BitBlt (hdc, x, to_y, width, height, hdc, x, from_y, SRCCOPY);
-  
+  {
+    RECT from;
+    RECT to;
+    HRGN dirty = CreateRectRgn (0, 0, 0, 0);
+    HRGN combined = CreateRectRgn (0, 0, 0, 0);
+
+    from.left = to.left = x;
+    from.right = to.right = x + width;
+    from.top = from_y;
+    from.bottom = from_y + height;
+    to.top = y;
+    to.bottom = bottom_y;
+
+    ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
+                   NULL, SW_INVALIDATE);
+
+    /* Combine this with what we expect to be dirty. This covers the
+       case where not all of the region we expect is actually dirty.  */
+    CombineRgn (combined, dirty, expect_dirty, RGN_OR);
+
+    /* If the dirty region is not what we expected, redraw the entire frame.  */
+    if (!EqualRgn (combined, expect_dirty))
+      SET_FRAME_GARBAGED (f);
+  }
+
   UNBLOCK_INPUT;
-  release_frame_dc (f, hdc);
 }
 
 
@@ -5568,8 +5674,7 @@ expose_area (w, row, r, area)
     /* If row extends face to end of line write the whole line.  */
     x_draw_glyphs (w, 0, row, area,
                   0, row->used[area],
-                  DRAW_NORMAL_TEXT,
-                  NULL, NULL, 0);
+                  DRAW_NORMAL_TEXT, 0);
   else
     {
       /* Set START_X to the window-relative start position for drawing glyphs of
@@ -5607,8 +5712,7 @@ expose_area (w, row, r, area)
         x_draw_glyphs (w, first_x - start_x, row, area,
                        first - row->glyphs[area],
                        last - row->glyphs[area],
-                       DRAW_NORMAL_TEXT,
-                       NULL, NULL, 0);
+                       DRAW_NORMAL_TEXT, 0);
     }
 }
 
@@ -5627,7 +5731,7 @@ expose_line (w, row, r)
   
   if (row->mode_line_p || w->pseudo_window_p)
     x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
-                  DRAW_NORMAL_TEXT, NULL, NULL, 0);
+                  DRAW_NORMAL_TEXT, 0);
   else
     {
       if (row->used[LEFT_MARGIN_AREA])
@@ -5636,7 +5740,7 @@ expose_line (w, row, r)
        expose_area (w, row, r, TEXT_AREA);
       if (row->used[RIGHT_MARGIN_AREA])
        expose_area (w, row, r, RIGHT_MARGIN_AREA);
-      x_draw_row_bitmaps (w, row);
+      x_draw_row_fringe_bitmaps (w, row);
     }
 
   return row->mouse_face_p;
@@ -5997,9 +6101,13 @@ glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
   return success_p;
 }
 
+/* Parse a button MESSAGE. The button index is returned in PBUTTON, and
+   the state in PUP. XBUTTON provides extra information for extended mouse
+   button messages. Returns FALSE if unable to parse the message.  */
 BOOL 
-parse_button (message, pbutton, pup)
+parse_button (message, xbutton, pbutton, pup)
      int message;
+     int xbutton;
      int * pbutton;
      int * pup;
 {
@@ -6044,6 +6152,14 @@ parse_button (message, pbutton, pup)
        button = 1;
       up = 1;
       break;
+    case WM_XBUTTONDOWN:
+      button = xbutton + 2;
+      up = 0;
+      break;
+    case WM_XBUTTONUP:
+      button = xbutton + 2;
+      up = 1;
+      break;
     default:
       return (FALSE);
     }
@@ -6069,11 +6185,12 @@ construct_mouse_click (result, msg, f)
   int button;
   int up;
 
-  parse_button (msg->msg.message, &button, &up);
+  parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
+               &button, &up);
 
-  /* Make the event type no_event; we'll change that when we decide
+  /* Make the event type NO_EVENT; we'll change that when we decide
      otherwise.  */
-  result->kind = mouse_click;
+  result->kind = MOUSE_CLICK_EVENT;
   result->code = button;
   result->timestamp = msg->msg.time;
   result->modifiers = (msg->dwModifiers
@@ -6095,7 +6212,7 @@ construct_mouse_wheel (result, msg, f)
      struct frame *f;
 {
   POINT p;
-  result->kind = mouse_wheel;
+  result->kind = MOUSE_WHEEL_EVENT;
   result->code = (short) HIWORD (msg->msg.wParam);
   result->timestamp = msg->msg.time;
   result->modifiers = msg->dwModifiers;
@@ -6123,7 +6240,7 @@ construct_drag_n_drop (result, msg, f)
   char *name;
   int i, len;
 
-  result->kind = drag_n_drop;
+  result->kind = DRAG_N_DROP_EVENT;
   result->code = 0;
   result->timestamp = msg->msg.time;
   result->modifiers = msg->dwModifiers;
@@ -6150,7 +6267,7 @@ construct_drag_n_drop (result, msg, f)
        continue;
       name = alloca (len + 1);
       DragQueryFile (hdrop, i, name, len + 1);
-      files = Fcons (build_string (name), files);
+      files = Fcons (DECODE_FILE (build_string (name)), files);
     }
 
   DragFinish (hdrop);
@@ -6187,6 +6304,28 @@ note_mouse_movement (frame, msg)
   memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
   XSETFRAME (last_mouse_motion_frame, frame);
 
+#if 0 /* Calling Lisp asynchronously is not safe.  */
+  if (mouse_autoselect_window)
+    {
+      int area;
+      Lisp_Object window;
+      static Lisp_Object last_window;
+
+      window = window_from_coordinates (frame, mouse_x, mouse_y, &area, 0);
+
+      /* 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.  */
+      if (!EQ (window, last_window)
+         && !EQ (window, selected_window)
+         && (!MINI_WINDOW_P (XWINDOW (window))
+             || (EQ (window, minibuf_window) && minibuf_level > 0)))
+       Fselect_window (window);
+
+      last_window=window;
+    }
+#endif
+
   if (msg->hwnd != FRAME_W32_WINDOW (frame))
     {
       frame->mouse_moved = 1;
@@ -6211,11 +6350,6 @@ note_mouse_movement (frame, msg)
     }
 }
 
-/* This is used for debugging, to turn off note_mouse_highlight.  */
-
-int disable_mouse_highlight;
-
-
 \f
 /************************************************************************
                              Mouse Face
@@ -6335,7 +6469,7 @@ frame_to_window_pixel_xy (w, x, y)
 /* Take proper action when mouse has moved to the mode or header line of
    window W, x-position X.  MODE_LINE_P non-zero means mouse is on the
    mode line.  X is relative to the start of the text display area of
-   W, so the width of bitmap areas and scroll bars must be subtracted
+   W, so the width of fringes and scroll bars must be subtracted
    to get a position relative to the start of the mode line.  */
 
 static void
@@ -6363,7 +6497,7 @@ note_mode_line_highlight (w, x, mode_line_p)
       glyph = row->glyphs[TEXT_AREA];
       end = glyph + row->used[TEXT_AREA];
       x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
-             + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
+             + FRAME_X_LEFT_FRINGE_WIDTH (f));
       
       while (glyph < end
             && x >= x0 + glyph->pixel_width)
@@ -6374,9 +6508,9 @@ note_mode_line_highlight (w, x, mode_line_p)
 
       if (glyph < end
          && STRINGP (glyph->object)
-         && XSTRING (glyph->object)->intervals
+         && STRING_INTERVALS (glyph->object)
          && glyph->charpos >= 0
-         && glyph->charpos < XSTRING (glyph->object)->size)
+         && glyph->charpos < SCHARS (glyph->object))
        {
          /* If we're on a string with `help-echo' text property,
             arrange for the help to be displayed.  This is done by
@@ -6432,7 +6566,7 @@ note_mouse_highlight (f, x, y)
   if (popup_activated ())
     return;
 
-  if (disable_mouse_highlight
+  if (NILP (Vmouse_highlight)
       || !f->glyphs_initialized_p)
     return;
 
@@ -6460,6 +6594,9 @@ note_mouse_highlight (f, x, y)
   if (!WINDOWP (window))
     return;
 
+  /* Reset help_echo. It will get recomputed below.  */
+  help_echo = Qnil;
+
   /* Convert to window-relative pixel coordinates.  */
   w = XWINDOW (window);
   frame_to_window_pixel_xy (w, &x, &y);
@@ -6692,7 +6829,7 @@ note_mouse_highlight (f, x, y)
              if (NILP (b))
                b = make_number (0);
              if (NILP (e))
-               e = make_number (XSTRING (object)->size - 1);
+               e = make_number (SCHARS (object) - 1);
              fast_find_string_pos (w, XINT (b), object,
                                    &dpyinfo->mouse_face_beg_col,
                                    &dpyinfo->mouse_face_beg_row,
@@ -6728,7 +6865,7 @@ note_mouse_highlight (f, x, y)
                {
                  Lisp_Object before = Foverlay_start (overlay);
                  Lisp_Object after = Foverlay_end (overlay);
-                 Lisp_Object ignore;
+                 int ignore;
 
                  /* Note that we might not be able to find position
                     BEFORE in the glyph matrix if the overlay is
@@ -6790,7 +6927,7 @@ note_mouse_highlight (f, x, y)
            /* Try text properties.  */
            if (STRINGP (object)
                && charpos >= 0
-               && charpos < XSTRING (object)->size)
+               && charpos < SCHARS (object))
              {
                help = Fget_text_property (make_number (charpos),
                                           Qhelp_echo, object);
@@ -6938,7 +7075,7 @@ w32_handle_tool_bar_click (f, button_event)
   if (NILP (enabled_p))
     return;
   
-  if (button_event->kind == mouse_click)
+  if (button_event->modifiers & down_modifier)
     {
       /* Show item in pressed state.  */
       show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
@@ -6965,7 +7102,8 @@ w32_handle_tool_bar_click (f, button_event)
       event.kind = TOOL_BAR_EVENT;
       event.frame_or_window = frame;
       event.arg = key;
-      event.modifiers = button_event->modifiers;
+      /* The keyboard buffer doesn't like the up modifier being set.  */
+      event.modifiers = button_event->modifiers & ~up_modifier;
       kbd_buffer_store_event (&event);
       last_tool_bar_item = -1;
     }
@@ -7092,7 +7230,7 @@ fast_find_position (w, charpos, hpos, vpos, x, y, stop)
   int i, past_end = 0;
 
   first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-  row = row_containing_pos (w, charpos, first, NULL);
+  row = row_containing_pos (w, charpos, first, NULL, 0);
   if (row == NULL)
     {
       if (charpos < MATRIX_ROW_START_CHARPOS (first))
@@ -7242,7 +7380,7 @@ fast_find_position (w, pos, hpos, vpos, x, y, stop)
 #endif /* not 0 */
 
 
-/* Find the position of the the glyph for position POS in OBJECT in
+/* Find the position of the glyph for position POS in OBJECT in
    window W's current matrix, and return in *X/*Y the pixel
    coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
 
@@ -7334,81 +7472,61 @@ show_mouse_face (dpyinfo, draw)
 {
   struct window *w = XWINDOW (dpyinfo->mouse_face_window);
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  int i;
-  int cursor_off_p = 0;
-  struct cursor_pos saved_cursor;
-
-  saved_cursor = output_cursor;
   
-  /* If window is in the process of being destroyed, don't bother
-     to do anything.  */
-  if (w->current_matrix == NULL)
-    goto set_x_cursor;
-
-  /* Recognize when we are called to operate on rows that don't exist
-     anymore.  This can happen when a window is split.  */
-  if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
-    goto set_x_cursor;
-
-  set_output_cursor (&w->phys_cursor);
-
-  /* Note that mouse_face_beg_row etc. are window relative.  */
-  for (i = dpyinfo->mouse_face_beg_row;
-       i <= dpyinfo->mouse_face_end_row;
-       i++)
-    {
-      int start_hpos, end_hpos, start_x;
-      struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
+  if (/* If window is in the process of being destroyed, don't bother
+        to do anything.  */
+      w->current_matrix != NULL
+      /* Don't update mouse highlight if hidden */
+      && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
+      /* Recognize when we are called to operate on rows that don't exist
+        anymore.  This can happen when a window is split.  */
+      && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
+    {
+      int phys_cursor_on_p = w->phys_cursor_on_p;
+      struct glyph_row *row, *first, *last;
+
+      first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
+      last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
+      
+      for (row = first; row <= last && row->enabled_p; ++row)
+       {
+         int start_hpos, end_hpos, start_x;
 
-      /* Don't do anything if row doesn't have valid contents.  */
-      if (!row->enabled_p)
-       continue;
+         /* For all but the first row, the highlight starts at column 0.  */
+         if (row == first)
+           {
+             start_hpos = dpyinfo->mouse_face_beg_col;
+             start_x = dpyinfo->mouse_face_beg_x;
+           }
+         else
+           {
+             start_hpos = 0;
+             start_x = 0;
+           }
 
-      /* For all but the first row, the highlight starts at column 0.  */
-      if (i == dpyinfo->mouse_face_beg_row)
-       {
-         start_hpos = dpyinfo->mouse_face_beg_col;
-         start_x = dpyinfo->mouse_face_beg_x;
-       }
-      else
-       {
-         start_hpos = 0;
-         start_x = 0;
-       }
+         if (row == last)
+           end_hpos = dpyinfo->mouse_face_end_col;
+         else
+           end_hpos = row->used[TEXT_AREA];
 
-      if (i == dpyinfo->mouse_face_end_row)
-       end_hpos = dpyinfo->mouse_face_end_col;
-      else
-       end_hpos = row->used[TEXT_AREA];
+         if (end_hpos > start_hpos)
+           {
+             x_draw_glyphs (w, start_x, row, TEXT_AREA, 
+                            start_hpos, end_hpos, draw, 0);
 
-      /* If the cursor's in the text we are about to rewrite, turn the
-        cursor off.  */
-      if (!w->pseudo_window_p
-         && i == output_cursor.vpos
-         && output_cursor.hpos >= start_hpos - 1
-         && output_cursor.hpos <= end_hpos)
-       {
-         x_update_window_cursor (w, 0);
-         cursor_off_p = 1;
+             row->mouse_face_p
+               = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
+           }
        }
 
-      if (end_hpos > start_hpos)
-        {
-          x_draw_glyphs (w, start_x, row, TEXT_AREA,
-                         start_hpos, end_hpos, draw, NULL, NULL, 0);
-          row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
-        }
+      /* When we've written over the cursor, arrange for it to
+        be displayed again.  */
+      if (phys_cursor_on_p && !w->phys_cursor_on_p)
+       x_display_cursor (w, 1,
+                         w->phys_cursor.hpos, w->phys_cursor.vpos,
+                         w->phys_cursor.x, w->phys_cursor.y);
     }
 
-  /* If we turned the cursor off, turn it back on.  */
-  if (cursor_off_p)
-    x_display_cursor (w, 1,
-                     output_cursor.hpos, output_cursor.vpos,
-                     output_cursor.x, output_cursor.y);
-
-  output_cursor = saved_cursor;
-
- set_x_cursor:
 #if 0 /* TODO: mouse cursor */
   /* Change the mouse cursor.  */
   if (draw == DRAW_NORMAL_TEXT)
@@ -7421,7 +7539,6 @@ show_mouse_face (dpyinfo, draw)
     XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                   f->output_data.x->nontext_cursor);
 #endif
-  ;
 }
 
 /* Clear out the mouse-highlighted active region.
@@ -7488,6 +7605,8 @@ cancel_mouse_face (f)
 \f
 static struct scroll_bar *x_window_to_scroll_bar ();
 static void x_scroll_bar_report_motion ();
+static void x_check_fullscreen P_ ((struct frame *));
+static void x_check_fullscreen_move P_ ((struct frame *));
 static int glyph_rect P_ ((struct frame *f, int, int, RECT *));
 
 
@@ -7503,7 +7622,7 @@ glyph_rect (f, x, y, rect)
      RECT *rect;
 {
   Lisp_Object window;
-  int part, found = 0;
+  int part;
 
   window = window_from_coordinates (f, x, y, &part, 0);
   if (!NILP (window))
@@ -7511,34 +7630,51 @@ glyph_rect (f, x, y, rect)
       struct window *w = XWINDOW (window);
       struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
       struct glyph_row *end = r + w->current_matrix->nrows - 1;
-      int area;
 
       frame_to_window_pixel_xy (w, &x, &y);
-      
-      for (; !found && r < end && r->enabled_p; ++r)
-       if (r->y + r->height >= y)
+
+      for (; r < end && r->enabled_p; ++r)
+       if (r->y <= y && r->y + r->height > y)
          {
+           /* Found the row at y.  */
            struct glyph *g = r->glyphs[TEXT_AREA];
            struct glyph *end = g + r->used[TEXT_AREA];
            int gx;
-             
-           for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
-             if (gx + g->pixel_width >= x)
+
+           rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
+           rect->bottom = rect->top + r->height;
+
+           if (x < r->x)
+             {
+               /* x is to the left of the first glyph in the row.  */
+               rect->left = XINT (w->left);
+               rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
+               return 1;
+             }
+
+           for (gx = r->x; g < end; gx += g->pixel_width, ++g)
+             if (gx <= x && gx + g->pixel_width > x)
                {
+                 /* x is on a glyph.  */
                  rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
-                 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
                  rect->right = rect->left + g->pixel_width;
-                 rect->bottom = rect->top + r->height;
-                 found = 1;
+                 return 1;
                }
+
+           /* x is to the right of the last glyph in the row.  */
+           rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
+           rect->right = XINT (w->left) + XINT (w->width);
+           return 1;
          }
     }
 
-  return found;
+  /* The y is not on any row.  */
+  return 0;
 }
 
 /* Record the position of the mouse in last_mouse_glyph.  */
-static void remember_mouse_glyph (f1, gx, gy)
+static void
+remember_mouse_glyph (f1, gx, gy)
      struct frame * f1;
      int gx, gy;
 {
@@ -7805,7 +7941,7 @@ my_create_scrollbar (f, bar)
                             (LPARAM) bar);
 }
 
-//#define ATTACH_THREADS
+/*#define ATTACH_THREADS*/
 
 BOOL
 my_show_window (FRAME_PTR f, HWND hwnd, int how)
@@ -7993,7 +8129,7 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
     {
       HDC hdc;
       BLOCK_INPUT;
-      if (width && height)
+      if (width > 0 && height > 0)
        {
          hdc = get_frame_dc (f);
          w32_clear_area (f, hdc, left, top, width, height);
@@ -8059,7 +8195,7 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
             SetScrollRange (hwnd, SB_CTL, 0,
                             VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
           my_show_window (f, hwnd, SW_NORMAL);
-          //  InvalidateRect (w, NULL, FALSE);
+          /* InvalidateRect (w, NULL, FALSE);  */
 
           /* Remember new settings.  */
           XSETINT (bar->left, sb_left);
@@ -8183,7 +8319,7 @@ w32_judge_scroll_bars (f)
 }
 
 /* Handle a mouse click on the scroll bar BAR.  If *EMACS_EVENT's kind
-   is set to something other than no_event, it is enqueued.
+   is set to something other than NO_EVENT, it is enqueued.
 
    This may be called from a signal handler, so we have to ignore GC
    mark bits.  */
@@ -8197,7 +8333,7 @@ w32_scroll_bar_handle_click (bar, msg, emacs_event)
   if (! GC_WINDOWP (bar->window))
     abort ();
 
-  emacs_event->kind = w32_scroll_bar_click;
+  emacs_event->kind = W32_SCROLL_BAR_CLICK_EVENT;
   emacs_event->code = 0;
   /* not really meaningful to distinguish up/down */
   emacs_event->modifiers = msg->dwModifiers;
@@ -8297,7 +8433,7 @@ w32_scroll_bar_handle_click (bar, msg, emacs_event)
          }
        /* fall through */
       default:
-       emacs_event->kind = no_event;
+       emacs_event->kind = NO_EVENT;
        return FALSE;
       }
 
@@ -8411,12 +8547,6 @@ x_scroll_bar_clear (f)
 \f
 /* The main W32 event-reading loop - w32_read_socket.  */
 
-/* Time stamp of enter window event.  This is only used by w32_read_socket,
-   but we have to put it out here, since static variables within functions
-   sometimes don't work.  */
-
-static Time enter_timestamp;
-
 /* Record the last 100 characters stored
    to help debug the loss-of-chars-during-GC problem.  */
 
@@ -8472,7 +8602,7 @@ w32_read_socket (sd, bufp, numchars, expected)
   if (numchars <= 0)
     abort ();                   /* Don't think this happens. */
 
-  /* TODO: tooltips, tool-bars, ghostscript integration, mouse
+  /* TODO: tool-bars, ghostscript integration, mouse
      cursors. */
   while (get_next_msg (&msg, FALSE))
     {
@@ -8489,7 +8619,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                  /* We may get paint messages even though the client
                     area is clipped - these are not expose events. */
                  DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
-                            XSTRING (f->name)->data));
+                            SDATA (f->name)));
                }
              else if (f->async_visible != 1)
                {
@@ -8498,13 +8628,13 @@ w32_read_socket (sd, bufp, numchars, expected)
                  f->async_iconified = 0;
                  SET_FRAME_GARBAGED (f);
                  DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
-                            XSTRING (f->name)->data));
+                            SDATA (f->name)));
 
                  /* WM_PAINT serves as MapNotify as well, so report
                     visibility changes properly.  */
                  if (f->iconified)
                    {
-                     bufp->kind = deiconify_event;
+                     bufp->kind = DEICONIFY_EVENT;
                      XSETFRAME (bufp->frame_or_window, f);
                      bufp->arg = Qnil;
                      bufp++;
@@ -8542,7 +8672,7 @@ w32_read_socket (sd, bufp, numchars, expected)
              if (numchars == 0)
                abort ();
          
-             bufp->kind = language_change_event;
+             bufp->kind = LANGUAGE_CHANGE_EVENT;
              XSETFRAME (bufp->frame_or_window, f);
              bufp->arg = Qnil;
              bufp->code = msg.msg.wParam;
@@ -8559,10 +8689,16 @@ w32_read_socket (sd, bufp, numchars, expected)
          
          if (f && !f->iconified)
            {
+             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+               {
+                 dpyinfo->mouse_face_hidden = 1;
+                 clear_mouse_face (dpyinfo);
+               }
+
              if (temp_index == sizeof temp_buffer / sizeof (short))
                temp_index = 0;
              temp_buffer[temp_index++] = msg.msg.wParam;
-             bufp->kind = non_ascii_keystroke;
+             bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
              bufp->code = msg.msg.wParam;
              bufp->modifiers = msg.dwModifiers;
              XSETFRAME (bufp->frame_or_window, f);
@@ -8580,10 +8716,16 @@ w32_read_socket (sd, bufp, numchars, expected)
          
          if (f && !f->iconified)
            {
+             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+               {
+                 dpyinfo->mouse_face_hidden = 1;
+                 clear_mouse_face (dpyinfo);
+               }
+
              if (temp_index == sizeof temp_buffer / sizeof (short))
                temp_index = 0;
              temp_buffer[temp_index++] = msg.msg.wParam;
-             bufp->kind = ascii_keystroke;
+             bufp->kind = ASCII_KEYSTROKE_EVENT;
              bufp->code = msg.msg.wParam;
              bufp->modifiers = msg.dwModifiers;
              XSETFRAME (bufp->frame_or_window, f);
@@ -8606,6 +8748,12 @@ w32_read_socket (sd, bufp, numchars, expected)
          else
            f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
          
+         if (dpyinfo->mouse_face_hidden)
+           {
+             dpyinfo->mouse_face_hidden = 0;
+             clear_mouse_face (dpyinfo);
+           }
+
          if (f)
            note_mouse_movement (f, &msg.msg);
          else
@@ -8641,6 +8789,8 @@ w32_read_socket (sd, bufp, numchars, expected)
        case WM_MBUTTONUP:
        case WM_RBUTTONDOWN:
        case WM_RBUTTONUP:
+       case WM_XBUTTONDOWN:
+       case WM_XBUTTONUP:
          {
             /* If we decide we want to generate an event to be seen
                by the rest of Emacs, we put it here.  */
@@ -8649,7 +8799,7 @@ w32_read_socket (sd, bufp, numchars, expected)
            int button;
            int up;
 
-            emacs_event.kind = no_event;
+            emacs_event.kind = NO_EVENT;
            
            if (dpyinfo->grabbed && last_mouse_frame
                && FRAME_LIVE_P (last_mouse_frame))
@@ -8666,13 +8816,14 @@ w32_read_socket (sd, bufp, numchars, expected)
                     && XFASTINT (XWINDOW (f->tool_bar_window)->height))
                   {
                     Lisp_Object window;
-                    int p;
+                    int p, x, y;
+
+                   x = XFASTINT (emacs_event.x);
+                   y = XFASTINT (emacs_event.y);
 
                     /* Set x and y.  */
-                    window = window_from_coordinates (f,
-                                                      emacs_event.x,
-                                                      emacs_event.y,
-                                                      &p, 1);
+                    window = window_from_coordinates (f, x, y, &p, 1);
+
                     if (EQ (window, f->tool_bar_window))
                       {
                         w32_handle_tool_bar_click (f, &emacs_event);
@@ -8692,8 +8843,9 @@ w32_read_socket (sd, bufp, numchars, expected)
                     }
              }
            
-           parse_button (msg.msg.message, &button, &up);
-           
+           parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
+                         &button, &up);
+
            if (up)
              {
                dpyinfo->grabbed &= ~ (1 << button);
@@ -8736,16 +8888,6 @@ w32_read_socket (sd, bufp, numchars, expected)
             }
          break;
 
-        case WM_MENUSELECT:
-          {
-            HMENU menu = (HMENU) msg.msg.lParam;
-            UINT menu_item = (UINT) LOWORD (msg.msg.wParam);
-            UINT flags = (UINT) HIWORD (msg.msg.wParam);
-
-            w32_menu_display_help (menu, menu_item, flags);
-          }
-          break;
-
        case WM_DROPFILES:
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
 
@@ -8776,8 +8918,22 @@ w32_read_socket (sd, bufp, numchars, expected)
          }
          
        case WM_WINDOWPOSCHANGED:
+         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+         if (f)
+           {
+             x_check_fullscreen_move(f);
+             if (f->output_data.w32->want_fullscreen & FULLSCREEN_WAIT)
+               f->output_data.w32->want_fullscreen &=
+                 ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
+           }
+         check_visibility = 1;
+         break;
+
        case WM_ACTIVATE:
        case WM_ACTIVATEAPP:
+         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+         if (f)
+           x_check_fullscreen (f);
          check_visibility = 1;
          break;
 
@@ -8797,6 +8953,15 @@ w32_read_socket (sd, bufp, numchars, expected)
          break;
 
        case WM_SHOWWINDOW:
+         /* wParam non-zero means Window is about to be shown, 0 means
+            about to be hidden.  */
+         /* Redo the mouse-highlight after the tooltip has gone.  */
+         if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
+           {
+             tip_window = NULL;
+             redo_mouse_highlight ();
+           }
+
          /* If window has been obscured or exposed by another window
             being maximised or minimised/restored, then recheck
             visibility of all frames.  Direct changes to our own
@@ -8826,7 +8991,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                  f->async_visible = 0;
                  f->async_iconified = 1;
                  
-                 bufp->kind = iconify_event;
+                 bufp->kind = ICONIFY_EVENT;
                  XSETFRAME (bufp->frame_or_window, f);
                  bufp->arg = Qnil;
                  bufp++;
@@ -8856,7 +9021,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                       f->output_data.w32->left_pos = x;
                       f->output_data.w32->top_pos = y;
 
-                     bufp->kind = deiconify_event;
+                     bufp->kind = DEICONIFY_EVENT;
                      XSETFRAME (bufp->frame_or_window, f);
                      bufp->arg = Qnil;
                      bufp++;
@@ -8912,6 +9077,36 @@ w32_read_socket (sd, bufp, numchars, expected)
          check_visibility = 1;
          break;
 
+       case WM_MOUSELEAVE:
+         f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
+         if (f)
+           {
+             if (f == dpyinfo->mouse_face_mouse_frame)
+               {
+                 /* If we move outside the frame, then we're
+                    certainly no longer on any text in the frame.  */
+                 clear_mouse_face (dpyinfo);
+                 dpyinfo->mouse_face_mouse_frame = 0;
+               }
+
+             /* Generate a nil HELP_EVENT to cancel a help-echo.
+                Do it only if there's something to cancel.
+                Otherwise, the startup message is cleared when
+                the mouse leaves the frame.  */
+             if (any_help_event_p)
+               {
+                 Lisp_Object frame;
+                 int n;
+
+                 XSETFRAME (frame, f);
+                 help_echo = Qnil;
+                 n = gen_help_event (bufp, numchars,
+                                     Qnil, frame, Qnil, Qnil, 0);
+                 bufp += n, count += n, numchars -= n;
+               }
+           }
+         break;
+             
        case WM_SETFOCUS:
          f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
 
@@ -8974,7 +9169,7 @@ w32_read_socket (sd, bufp, numchars, expected)
              if (numchars == 0)
                abort ();
              
-             bufp->kind = delete_window_event;
+             bufp->kind = DELETE_WINDOW_EVENT;
              XSETFRAME (bufp->frame_or_window, f);
              bufp->arg = Qnil;
              bufp++;
@@ -8991,7 +9186,7 @@ w32_read_socket (sd, bufp, numchars, expected)
              if (numchars == 0)
                abort ();
          
-             bufp->kind = menu_bar_activate_event;
+             bufp->kind = MENU_BAR_ACTIVATE_EVENT;
              XSETFRAME (bufp->frame_or_window, f);
              bufp->arg = Qnil;
              bufp++;
@@ -9076,6 +9271,11 @@ w32_read_socket (sd, bufp, numchars, expected)
       FOR_EACH_FRAME (tail, frame)
        {
          FRAME_PTR f = XFRAME (frame);
+         /* The tooltip has been drawn already.  Avoid the
+            SET_FRAME_GARBAGED below.  */
+         if (EQ (frame, tip_frame))
+           continue;
+
          /* Check "visible" frames and mark each as obscured or not.
             Note that async_visible is nonzero for unobscured and
             obscured frames, but zero for hidden and iconified frames.  */
@@ -9108,7 +9308,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                  if (!FRAME_OBSCURED_P (f))
                    {
                      DebPrint (("frame %p (%s) obscured\n", f,
-                                XSTRING (f->name)->data));
+                                SDATA (f->name)));
                    }
                }
              else
@@ -9120,7 +9320,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                    {
                      SET_FRAME_GARBAGED (f);
                      DebPrint (("obscured frame %p (%s) found to be visible\n", f,
-                                XSTRING (f->name)->data));
+                                SDATA (f->name)));
 
                      /* Force a redisplay sooner or later.  */
                      record_asynch_buffer_change ();
@@ -9141,21 +9341,24 @@ w32_read_socket (sd, bufp, numchars, expected)
                             Text Cursor
  ***********************************************************************/
 
-/* Note if the text cursor of window W has been overwritten by a
-   drawing operation that outputs N glyphs starting at HPOS in the
-   line given by output_cursor.vpos.  N < 0 means all the rest of the
-   line after HPOS has been written.  */
+/* Notice if the text cursor of window W has been overwritten by a
+   drawing operation that outputs glyphs starting at START_X and
+   ending at END_X in the line given by output_cursor.vpos.
+   Coordinates are area-relative.  END_X < 0 means all the rest
+   of the line after START_X has been written.  */
 
 static void
-note_overwritten_text_cursor (w, hpos, n)
+notice_overwritten_cursor (w, area, x0, x1, y0, y1)
      struct window *w;
-     int hpos, n;
-{
-  if (updated_area == TEXT_AREA
-      && output_cursor.vpos == w->phys_cursor.vpos
-      && hpos <= w->phys_cursor.hpos
-      && (n < 0
-         || hpos + n > w->phys_cursor.hpos))
+     enum glyph_row_area area;
+     int x0, x1, y0, y1;
+{
+  if (area == TEXT_AREA
+      && w->phys_cursor_on_p
+      && y0 <= w->phys_cursor.y
+      && y1 >= w->phys_cursor.y + w->phys_cursor_height
+      && x0 <= w->phys_cursor.x
+      && (x1 < 0 || x1 > w->phys_cursor.x))
     w->phys_cursor_on_p = 0;
 }
 
@@ -9192,8 +9395,8 @@ w32_clip_to_row (w, row, hdc, whole_line_p)
      the rectangle to the left and increase its width.  */
   if (whole_line_p)
     {
-      clip_rect.left -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
-      clip_rect.right += FRAME_X_FLAGS_AREA_WIDTH (f);
+      clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
+      clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
     }
 
   w32_set_clip_rectangle (hdc, &clip_rect);
@@ -9219,7 +9422,7 @@ x_draw_hollow_cursor (w, row)
   rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
   rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
               + row->ascent - w->phys_cursor_ascent);
-  rect.bottom = rect.top + row->height - 1;
+  rect.bottom = rect.top + row->height;
 
   /* Get the glyph the cursor is on.  If we can't tell because
      the current matrix is invalid or such, give up.  */
@@ -9231,7 +9434,7 @@ x_draw_hollow_cursor (w, row)
      glyph, and `x-stretch-block-cursor' is nil, don't draw a
      rectangle as wide as the glyph, but use a canonical character
      width instead.  */
-  wd = cursor_glyph->pixel_width - 1;
+  wd = cursor_glyph->pixel_width;
   if (cursor_glyph->type == STRETCH_GLYPH
       && !x_stretch_cursor_p)
     wd = min (CANON_X_UNIT (f), wd);
@@ -9253,10 +9456,11 @@ x_draw_hollow_cursor (w, row)
    --gerd.  */
 
 static void
-x_draw_bar_cursor (w, row, width)
+x_draw_bar_cursor (w, row, width, kind)
      struct window *w;
      struct glyph_row *row;
      int width;
+     enum text_cursor_kinds kind;
 {
   struct frame *f = XFRAME (w->frame);
   struct glyph *cursor_glyph;
@@ -9281,17 +9485,38 @@ x_draw_bar_cursor (w, row, width)
     }
   else
     {
+      COLORREF cursor_color = f->output_data.w32->cursor_pixel;
+      struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
+
       if (width < 0)
         width = f->output_data.w32->cursor_width;
+      width = min (cursor_glyph->pixel_width, width);
+
+      /* If the glyph's background equals the color we normally draw
+        the bar cursor in, the bar cursor in its normal color is
+        invisible.  Use the glyph's foreground color instead in this
+        case, on the assumption that the glyph's colors are chosen so
+        that the glyph is legible.  */
+      if (face->background == cursor_color)
+       cursor_color = face->foreground;
 
       x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
       hdc = get_frame_dc (f);
       w32_clip_to_row (w, row, hdc, 0);
-      w32_fill_area (f, hdc, f->output_data.w32->cursor_pixel,
-                     x,
-                     WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
-                     min (cursor_glyph->pixel_width, width),
-                     row->height);
+
+      if (kind == BAR_CURSOR)
+       {
+         w32_fill_area (f, hdc, cursor_color, x,
+                        WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+                        width, row->height);
+       }
+      else
+       {
+         w32_fill_area (f, hdc, cursor_color, x,
+                        WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
+                                                 row->height - width),
+                        cursor_glyph->pixel_width, width);
+       }
       release_frame_dc (f, hdc);
     }
 }
@@ -9324,9 +9549,11 @@ x_draw_phys_cursor_glyph (w, row, hl)
      glyphs and mini-buffer.  */
   if (w->phys_cursor.hpos < row->used[TEXT_AREA])
     {
+      int on_p = w->phys_cursor_on_p;
       x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
                      w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
-                     hl, 0, 0, 0);
+                     hl, 0);
+      w->phys_cursor_on_p = on_p;
 
       /* When we erase the cursor, and ROW is overlapped by other
         rows, make sure that these overlapping parts of other rows
@@ -9377,6 +9604,12 @@ x_erase_phys_cursor (w)
   if (!cursor_row->enabled_p)
     goto mark_cursor_off;
   
+  /* If row is completely invisible, don't attempt to delete a cursor which
+     isn't there.  This may happen if cursor is at top of window, and
+     we switch to a buffer with a header line in that window.  */
+  if (cursor_row->visible_height <= 0)
+    goto mark_cursor_off;
+  
   /* This can happen when the new row is shorter than the old one.
      In this case, either x_draw_glyphs or clear_end_of_line
      should have cleared the cursor.  Note that we wouldn't be
@@ -9426,8 +9659,6 @@ x_erase_phys_cursor (w)
   /* Erase the cursor by redrawing the character underneath it.  */
   if (mouse_face_here_p)
     hl = DRAW_MOUSE_FACE;
-  else if (cursor_row->inverse_p)
-    hl = DRAW_INVERSE_VIDEO;
   else
     hl = DRAW_NORMAL_TEXT;
   x_draw_phys_cursor_glyph (w, cursor_row, hl);
@@ -9483,6 +9714,8 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
   struct glyph_matrix *current_glyphs;
   struct glyph_row *glyph_row;
   struct glyph *glyph;
+  int cursor_non_selected;
+  int active_cursor = 1;
 
   /* This is pointless on invisible frames, and dangerous on garbaged
      windows and frames; in the latter case, the frame or window may
@@ -9518,6 +9751,9 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
      the cursor type given by the frame parameter.  If explicitly
      marked off, draw no cursor.  In all other cases, we want a hollow
      box cursor.  */
+  cursor_non_selected 
+    = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
+                                 w->buffer));
   new_cursor_width = -1;
   if (cursor_in_echo_area
       && FRAME_HAS_MINIBUF_P (f)
@@ -9526,24 +9762,28 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
       if (w == XWINDOW (echo_area_window))
        new_cursor_type = FRAME_DESIRED_CURSOR (f);
       else
-       new_cursor_type = HOLLOW_BOX_CURSOR;
+       {
+         if (cursor_non_selected)
+           new_cursor_type = HOLLOW_BOX_CURSOR;
+         else
+           new_cursor_type = NO_CURSOR;
+         active_cursor = 0;
+       }
     }
   else
     {
       if (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame
           || w != XWINDOW (f->selected_window))
         {
-         extern int cursor_in_non_selected_windows;
+         active_cursor = 0;
 
           if (MINI_WINDOW_P (w) 
-              || !cursor_in_non_selected_windows
+              || !cursor_non_selected
               || NILP (XBUFFER (w->buffer)->cursor_type))
             new_cursor_type = NO_CURSOR;
           else
             new_cursor_type = HOLLOW_BOX_CURSOR;
         }
-      else if (w->cursor_off_p)
-        new_cursor_type = NO_CURSOR;
       else
         {
          struct buffer *b = XBUFFER (w->buffer);
@@ -9553,6 +9793,15 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
          else
            new_cursor_type = x_specified_cursor_type (b->cursor_type, 
                                                       &new_cursor_width);
+         if (w->cursor_off_p)
+           {
+             if (new_cursor_type == FILLED_BOX_CURSOR)
+               new_cursor_type = HOLLOW_BOX_CURSOR;
+             else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)
+               new_cursor_width = 1;
+             else
+               new_cursor_type = NO_CURSOR;
+           }
        }
     }
 
@@ -9563,7 +9812,9 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
       && (!on
          || w->phys_cursor.x != x
          || w->phys_cursor.y != y
-         || new_cursor_type != w->phys_cursor_type))
+         || new_cursor_type != w->phys_cursor_type
+         || (new_cursor_type == BAR_CURSOR
+             && new_cursor_width != w->phys_cursor_width)))
     x_erase_phys_cursor (w);
 
   /* If the cursor is now invisible and we want it to be visible,
@@ -9579,9 +9830,50 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
       w->phys_cursor.y = glyph_row->y;
       w->phys_cursor.hpos = hpos;
       w->phys_cursor.vpos = vpos;
-      w->phys_cursor_type = new_cursor_type;
+
+      /* If the user wants to use the system caret, make sure our own
+        cursor remains invisible.  */
+      if (w32_use_visible_system_caret)
+       {
+         if (w->phys_cursor_type != NO_CURSOR)
+           x_erase_phys_cursor (w);
+
+         new_cursor_type = w->phys_cursor_type = NO_CURSOR;
+         w->phys_cursor_width = -1;
+       }
+      else
+       {
+         w->phys_cursor_type = new_cursor_type;
+         w->phys_cursor_width = new_cursor_width;
+       }
+
       w->phys_cursor_on_p = 1;
 
+      /* If this is the active cursor, we need to track it with the
+        system caret, so third party software like screen magnifiers
+        and speech synthesizers can follow the cursor.  */
+      if (active_cursor)
+       {
+         HWND hwnd = FRAME_W32_WINDOW (f);
+
+         w32_system_caret_x
+           = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+         w32_system_caret_y
+           = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
+              + glyph_row->ascent - w->phys_cursor_ascent);
+
+         /* If the size of the active cursor changed, destroy the old
+            system caret.  */
+         if (w32_system_caret_hwnd
+             && (w32_system_caret_height != w->phys_cursor_height))
+           PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
+
+         w32_system_caret_height = w->phys_cursor_height;
+
+         /* Move the system caret.  */
+         PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
+       }
+
       switch (new_cursor_type)
        {
        case HOLLOW_BOX_CURSOR:
@@ -9593,7 +9885,11 @@ x_display_and_set_cursor (w, on, hpos, vpos, x, y)
          break;
 
        case BAR_CURSOR:
-         x_draw_bar_cursor (w, glyph_row, new_cursor_width);
+         x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR);
+         break;
+
+       case HBAR_CURSOR:
+         x_draw_bar_cursor (w, glyph_row, new_cursor_width, HBAR_CURSOR);
          break;
 
        case NO_CURSOR:
@@ -9695,7 +9991,7 @@ x_bitmap_icon (f, icon)
   if (NILP (icon))
     hicon = LoadIcon (hinst, EMACS_CLASS);
   else if (STRINGP (icon))
-    hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0,
+    hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
                       LR_DEFAULTSIZE | LR_LOADFROMFILE);
   else if (SYMBOLP (icon))
     {
@@ -9825,7 +10121,7 @@ x_new_fontset (f, fontsetname)
        to do.  */
     return fontset_name (fontset);
 
-  result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
+  result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
 
   if (!STRINGP (result))
     /* Can't load ASCII font.  */
@@ -9837,6 +10133,90 @@ x_new_fontset (f, fontsetname)
   return build_string (fontsetname);
 }
 
+/* Compute actual fringe widths */
+
+void
+x_compute_fringe_widths (f, redraw)
+     struct frame *f;
+     int redraw;
+{
+  int o_left = f->output_data.w32->left_fringe_width;
+  int o_right = f->output_data.w32->right_fringe_width;
+  int o_cols = f->output_data.w32->fringe_cols;
+
+  Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
+  Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
+  int left_fringe_width, right_fringe_width;
+
+  if (!NILP (left_fringe))
+    left_fringe = Fcdr (left_fringe);
+  if (!NILP (right_fringe))
+    right_fringe = Fcdr (right_fringe);
+
+  left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
+                      XINT (left_fringe));
+  right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
+                       XINT (right_fringe));
+
+  if (left_fringe_width || right_fringe_width)
+    {
+      int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
+      int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
+      int conf_wid = left_wid + right_wid;
+      int font_wid = FONT_WIDTH (f->output_data.w32->font);
+      int cols = (left_wid + right_wid + font_wid-1) / font_wid;
+      int real_wid = cols * font_wid;
+      if (left_wid && right_wid)
+       {
+         if (left_fringe_width < 0)
+           {
+             /* Left fringe width is fixed, adjust right fringe if necessary */
+             f->output_data.w32->left_fringe_width = left_wid;
+             f->output_data.w32->right_fringe_width = real_wid - left_wid;
+           }
+         else if (right_fringe_width < 0)
+           {
+             /* Right fringe width is fixed, adjust left fringe if necessary */
+             f->output_data.w32->left_fringe_width = real_wid - right_wid;
+             f->output_data.w32->right_fringe_width = right_wid;
+           }
+         else
+           {
+             /* Adjust both fringes with an equal amount.
+                Note that we are doing integer arithmetic here, so don't
+                lose a pixel if the total width is an odd number.  */
+             int fill = real_wid - conf_wid;
+             f->output_data.w32->left_fringe_width = left_wid + fill/2;
+             f->output_data.w32->right_fringe_width = right_wid + fill - fill/2;
+           }
+       }
+      else if (left_fringe_width)
+       {
+         f->output_data.w32->left_fringe_width = real_wid;
+         f->output_data.w32->right_fringe_width = 0;
+       }
+      else
+       {
+         f->output_data.w32->left_fringe_width = 0;
+         f->output_data.w32->right_fringe_width = real_wid;
+       }
+      f->output_data.w32->fringe_cols = cols;
+      f->output_data.w32->fringes_extra = real_wid;
+    }
+  else
+    {
+      f->output_data.w32->left_fringe_width = 0;
+      f->output_data.w32->right_fringe_width = 0;
+      f->output_data.w32->fringe_cols = 0;
+      f->output_data.w32->fringes_extra = 0;
+    }
+
+  if (redraw && FRAME_VISIBLE_P (f))
+    if (o_left != f->output_data.w32->left_fringe_width ||
+       o_right != f->output_data.w32->right_fringe_width ||
+       o_cols != f->output_data.w32->fringe_cols)
+      redraw_frame (f);
+}
 \f
 /***********************************************************************
        TODO: W32 Input Methods
@@ -9950,6 +10330,115 @@ x_set_offset (f, xoff, yoff, change_gravity)
   UNBLOCK_INPUT;
 }
 
+
+/* Check if we need to resize the frame due to a fullscreen request.
+   If so needed, resize the frame. */
+static void
+x_check_fullscreen (f)
+     struct frame *f;
+{
+  if (f->output_data.w32->want_fullscreen & FULLSCREEN_BOTH)
+    {
+      int width, height, ign;
+                      
+      x_real_positions (f, &f->output_data.w32->left_pos,
+                        &f->output_data.w32->top_pos);
+
+      x_fullscreen_adjust (f, &width, &height, &ign, &ign);
+                  
+      /* We do not need to move the window, it shall be taken care of
+         when setting WM manager hints.
+         If the frame is visible already, the position is checked by
+         x_check_fullscreen_move. */
+      if (f->width != width || f->height != height)
+        {
+          change_frame_size (f, height, width, 0, 1, 0);
+          SET_FRAME_GARBAGED (f);
+          cancel_mouse_face (f);
+
+          /* Wait for the change of frame size to occur */
+          f->output_data.w32->want_fullscreen |= FULLSCREEN_WAIT;
+        }
+    }
+}
+
+/* If frame parameters are set after the frame is mapped, we need to move
+   the window.  This is done in xfns.c.
+   Some window managers moves the window to the right position, some
+   moves the outer window manager window to the specified position.
+   Here we check that we are in the right spot.  If not, make a second
+   move, assuming we are dealing with the second kind of window manager. */
+static void
+x_check_fullscreen_move (f)
+     struct frame *f;
+{
+  if (f->output_data.w32->want_fullscreen & FULLSCREEN_MOVE_WAIT)
+  {
+    int expect_top = f->output_data.w32->top_pos;
+    int expect_left = f->output_data.w32->left_pos;
+
+    if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT)
+      expect_top = 0;
+    if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH)
+      expect_left = 0;
+    
+    if (expect_top != f->output_data.w32->top_pos
+        || expect_left != f->output_data.w32->left_pos)
+      x_set_offset (f, expect_left, expect_top, 1);
+
+    /* Just do this once */
+    f->output_data.w32->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
+  }
+}
+
+
+/* Calculate fullscreen size.  Return in *TOP_POS and *LEFT_POS the
+   wanted positions of the WM window (not emacs window).
+   Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
+   window (FRAME_X_WINDOW).
+ */
+void
+x_fullscreen_adjust (f, width, height, top_pos, left_pos)
+     struct frame *f;
+     int *width;
+     int *height;
+     int *top_pos;
+     int *left_pos;
+{
+  int newwidth = f->width, newheight = f->height;
+
+  *top_pos = f->output_data.w32->top_pos;
+  *left_pos = f->output_data.w32->left_pos;
+  
+  if (f->output_data.w32->want_fullscreen & FULLSCREEN_HEIGHT)
+    {
+      int ph;
+      
+      ph = FRAME_X_DISPLAY_INFO (f)->height;
+      newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+      ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
+        - f->output_data.w32->y_pixels_diff;
+      newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+      *top_pos = 0;
+    }
+
+  if (f->output_data.w32->want_fullscreen & FULLSCREEN_WIDTH)
+    {
+      int pw;
+      
+      pw = FRAME_X_DISPLAY_INFO (f)->width;
+      newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+      pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
+        - f->output_data.w32->x_pixels_diff;
+      newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+      *left_pos = 0;
+    }
+
+  *width = newwidth;
+  *height = newheight;
+}
+
+
 /* Call this to change the size of frame F's x-window.
    If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
    for this size change and subsequent size changes.
@@ -9970,8 +10459,9 @@ x_set_window_size (f, change_gravity, cols, rows)
     = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
        ? 0
        : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
-  f->output_data.w32->flags_areas_extra
-    = FRAME_FLAGS_AREA_WIDTH (f);
+
+  x_compute_fringe_widths (f, 0);
+
   pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
   pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
   
@@ -10221,7 +10711,7 @@ x_make_frame_visible (f)
 
       f->output_data.w32->asked_for_visible = 1;
 
-//      my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
+/*      my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);  */
       my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
     }
 
@@ -10557,11 +11047,11 @@ w32_initialize_display_info (display_name)
   dpyinfo->name_list_element = XCAR (w32_display_name_list);
   
   dpyinfo->w32_id_name
-    = (char *) xmalloc (XSTRING (Vinvocation_name)->size
-                       + XSTRING (Vsystem_name)->size
+    = (char *) xmalloc (SCHARS (Vinvocation_name)
+                       + SCHARS (Vsystem_name)
                        + 2);
   sprintf (dpyinfo->w32_id_name, "%s@%s",
-          XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
+          SDATA (Vinvocation_name), SDATA (Vsystem_name));
 
   /* Default Console mode values - overridden when running in GUI mode
      with values obtained from system metrics.  */
@@ -10580,6 +11070,7 @@ w32_initialize_display_info (display_name)
   dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
   dpyinfo->mouse_face_window = Qnil;
   dpyinfo->mouse_face_overlay = Qnil;
+  dpyinfo->mouse_face_hidden = 0;
   /* TODO: dpyinfo->gray */
 
 }
@@ -10787,6 +11278,11 @@ w32_initialize ()
                                   off the bottom */
   baud_rate = 19200;
 
+  w32_system_caret_hwnd = NULL;
+  w32_system_caret_height = 0;
+  w32_system_caret_x = 0;
+  w32_system_caret_y = 0;
+
   last_tool_bar_item = -1;
   any_help_event_p = 0;
 
@@ -10868,43 +11364,43 @@ syms_of_w32term ()
 
   DEFVAR_INT ("w32-num-mouse-buttons",
              &Vw32_num_mouse_buttons,
-             "Number of physical mouse buttons.");
+             doc: /* Number of physical mouse buttons.  */);
   Vw32_num_mouse_buttons = Qnil;
 
   DEFVAR_LISP ("w32-swap-mouse-buttons",
              &Vw32_swap_mouse_buttons,
-             "Swap the mapping of middle and right mouse buttons.\n\
-When nil, middle button is mouse-2 and right button is mouse-3.");
+              doc: /* Swap the mapping of middle and right mouse buttons.
+When nil, middle button is mouse-2 and right button is mouse-3.  */);
   Vw32_swap_mouse_buttons = Qnil;
 
   DEFVAR_LISP ("w32-grab-focus-on-raise",
               &Vw32_grab_focus_on_raise,
-              "Raised frame grabs input focus.\n\
-When t, `raise-frame' grabs input focus as well.  This fits well\n\
-with the normal Windows click-to-focus policy, but might not be\n\
-desirable when using a point-to-focus policy.");
+              doc: /* Raised frame grabs input focus.
+When t, `raise-frame' grabs input focus as well.  This fits well
+with the normal Windows click-to-focus policy, but might not be
+desirable when using a point-to-focus policy.  */);
   Vw32_grab_focus_on_raise = Qt;
 
   DEFVAR_LISP ("w32-capslock-is-shiftlock",
               &Vw32_capslock_is_shiftlock,
-              "Apply CapsLock state to non character input keys.\n\
-When nil, CapsLock only affects normal character input keys.");
+              doc: /* Apply CapsLock state to non character input keys.
+When nil, CapsLock only affects normal character input keys.  */);
   Vw32_capslock_is_shiftlock = Qnil;
 
   DEFVAR_LISP ("w32-recognize-altgr",
               &Vw32_recognize_altgr,
-              "Recognize right-alt and left-ctrl as AltGr.\n\
-When nil, the right-alt and left-ctrl key combination is\n\
-interpreted normally."); 
+              doc: /* Recognize right-alt and left-ctrl as AltGr.
+When nil, the right-alt and left-ctrl key combination is
+interpreted normally.  */); 
   Vw32_recognize_altgr = Qt;
 
   DEFVAR_BOOL ("w32-enable-unicode-output",
                &w32_enable_unicode_output,
-               "Enable the use of Unicode for text output if non-nil.\n\
-Unicode output may prevent some third party applications for displaying\n\
-Far-East Languages on Windows 95/98 from working properly.\n\
-NT uses Unicode internally anyway, so this flag will probably have no\n\
-affect on NT machines.");
+               doc: /* Enable the use of Unicode for text output if non-nil.
+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.  */);
   w32_enable_unicode_output = 1;
 
   help_echo = Qnil;
@@ -10917,24 +11413,45 @@ affect on NT machines.");
   staticpro (&previous_help_echo);
   help_echo_pos = -1;
 
+  DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
+    doc: /* *Non-nil means autoselect window with mouse pointer.  */);
+  mouse_autoselect_window = 0;
+
+  DEFVAR_BOOL ("w32-use-visible-system-caret",
+              &w32_use_visible_system_caret,
+              doc: /* Flag to make the system caret visible.
+When this is non-nil, Emacs will indicate the position of point by
+using the system caret instead of drawing its own cursor.  Some screen
+reader software does not track the system cursor properly when it is
+invisible, and gets confused by Emacs drawing its own cursor, so this
+variable is initialized to t when Emacs detects that screen reader 
+software is running as it starts up.
+
+When this variable is set, other variables affecting the appearance of
+the cursor have no effect.  */);
+
+  /* Initialize w32_use_visible_system_caret based on whether a screen
+     reader is in use.  */
+  if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
+                            &w32_use_visible_system_caret, 0))
+    w32_use_visible_system_caret = 0;
+
   DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
-    "*Non-nil means draw block cursor as wide as the glyph under it.\n\
-For example, if a block cursor is over a tab, it will be drawn as\n\
-wide as that tab on the display.");
+              doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
+For example, if a block cursor is over a tab, it will be drawn as
+wide as that tab on the display.  */);
   x_stretch_cursor_p = 0;
 
-#if 0 /* TODO: Setting underline position from font properties.  */
   DEFVAR_BOOL ("x-use-underline-position-properties",
               &x_use_underline_position_properties,
-     "*Non-nil means make use of UNDERLINE_POSITION font properties.\n\
-Nil means ignore them.  If you encounter fonts with bogus\n\
-UNDERLINE_POSITION font properties, for example 7x13 on XFree prior\n\
-to 4.1, set this to nil.");
+              doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
+nil means ignore them.  If you encounter fonts with bogus
+UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
+to 4.1, set this to nil.  */);
   x_use_underline_position_properties = 1;
-#endif
 
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
-    "If not nil, Emacs uses toolkit scroll bars.");
+              doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
   Vx_toolkit_scroll_bars = Qt;
 
   staticpro (&last_mouse_motion_frame);