]> code.delx.au - gnu-emacs/blobdiff - src/w32term.c
*** empty log message ***
[gnu-emacs] / src / w32term.c
index 6654b1a4087f2348289f67502857db7558cf8eae..2b5c9da39b607c178611220354b425b5e705662d 100644 (file)
@@ -1,6 +1,6 @@
 /* Implementation of GUI terminal on the Microsoft W32 API.
-   Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
-   Free Software Foundation, Inc.
+   Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+                 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -16,8 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include <config.h>
 #include <signal.h>
@@ -62,7 +62,8 @@ Boston, MA 02111-1307, USA.  */
 \f
 /* Fringe bitmaps.  */
 
-static HBITMAP fringe_bmp[MAX_FRINGE_BITMAPS];
+static int max_fringe_bmp = 0;
+static HBITMAP *fringe_bmp = 0;
 
 /* Non-nil means Emacs uses toolkit scroll bars.  */
 
@@ -86,6 +87,10 @@ static int any_help_event_p;
 /* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */
 static Lisp_Object last_window;
 
+/* Non-zero means make use of UNDERLINE_POSITION font properties.
+   (Not yet supported, see TODO in x_draw_glyph_string.)  */
+int x_use_underline_position_properties;
+
 extern unsigned int msh_mousewheel;
 
 extern void free_frame_menubar ();
@@ -133,6 +138,9 @@ int w32_use_visible_system_caret;
    for Far East languages.  */
 int w32_enable_unicode_output;
 
+/* Flag to enable Cleartype hack for font metrics.  */
+static int cleartype_active;
+
 DWORD dwWindowsThreadId = 0;
 HANDLE hWindowsThread = NULL;
 DWORD dwMainThreadId = 0;
@@ -175,9 +183,10 @@ int last_scroll_bar_drag_pos;
 /* Where the mouse was last time we reported a mouse event.  */
 
 static RECT last_mouse_glyph;
+static FRAME_PTR last_mouse_glyph_frame;
 static Lisp_Object last_mouse_press_frame;
 
-Lisp_Object Vw32_num_mouse_buttons;
+int w32_num_mouse_buttons;
 
 Lisp_Object Vw32_swap_mouse_buttons;
 
@@ -254,12 +263,21 @@ static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
 static void x_new_focus_frame P_ ((struct w32_display_info *,
                                   struct frame *));
+static void x_focus_changed P_ ((int, int, struct w32_display_info *,
+                                 struct frame *, struct input_event *));
+static void w32_detect_focus_change P_ ((struct w32_display_info *,
+                                       W32Msg *, struct input_event *));
 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,
                                   enum text_cursor_kinds));
-static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, HDC));
+static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, int, HDC));
+static BOOL my_show_window P_ ((struct frame *, HWND, int));
+static void my_set_window_pos P_ ((HWND, HWND, int, int, int, int, UINT));
+static void my_set_focus P_ ((struct frame *, HWND));
+static void my_set_foreground_window P_ ((HWND));
+static void my_destroy_window P_ ((struct frame *, HWND));
 
 static Lisp_Object Qvendor_specific_keysyms;
 
@@ -498,6 +516,7 @@ w32_draw_vertical_window_border (w, x, y0, y1)
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   RECT r;
   HDC hdc;
+  struct face *face;
 
   r.left = x;
   r.right = x + 1;
@@ -505,7 +524,12 @@ w32_draw_vertical_window_border (w, x, y0, y1)
   r.bottom = y1;
 
   hdc = get_frame_dc (f);
-  w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
+  face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
+  if (face)
+    w32_fill_rect (f, hdc, face->foreground, &r);
+  else
+    w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
+
   release_frame_dc (f, hdc);
 }
 
@@ -539,9 +563,8 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
                                output_cursor.vpos,
                                output_cursor.x, output_cursor.y);
 
-      x_draw_vertical_border (w);
-
-      draw_window_fringes (w);
+      if (draw_window_fringes (w, 1))
+       x_draw_vertical_border (w);
 
       UNBLOCK_INPUT;
     }
@@ -691,12 +714,12 @@ w32_draw_fringe_bitmap (w, row, p)
       int oldVH = row->visible_height;
       row->visible_height = p->h;
       row->y -= rowY - p->y;
-      w32_clip_to_row (w, row, hdc);
+      w32_clip_to_row (w, row, -1, hdc);
       row->y = oldY;
       row->visible_height = oldVH;
     }
   else
-    w32_clip_to_row (w, row, hdc);
+    w32_clip_to_row (w, row, -1, hdc);
 
   if (p->bx >= 0 && !p->overlay_p)
     {
@@ -704,7 +727,7 @@ w32_draw_fringe_bitmap (w, row, p)
                     p->bx, p->by, p->nx, p->ny);
     }
 
-  if (p->which)
+  if (p->which && p->which < max_fringe_bmp)
     {
       HBITMAP pixmap = fringe_bmp[p->which];
       HDC compat_hdc;
@@ -767,6 +790,15 @@ w32_define_fringe_bitmap (which, bits, h, wd)
      unsigned short *bits;
      int h, wd;
 {
+  if (which >= max_fringe_bmp)
+    {
+      int i = max_fringe_bmp;
+      max_fringe_bmp = which + 20;
+      fringe_bmp = (HBITMAP *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (HBITMAP));
+      while (i < max_fringe_bmp)
+       fringe_bmp[i++] = 0;
+    }
+
   fringe_bmp[which] = CreateBitmap (wd, h, 1, 1, bits);
 }
 
@@ -774,6 +806,9 @@ static void
 w32_destroy_fringe_bitmap (which)
      int which;
 {
+  if (which >= max_fringe_bmp)
+    return;
+
   if (fringe_bmp[which])
     DeleteObject (fringe_bmp[which]);
   fringe_bmp[which] = 0;
@@ -807,8 +842,7 @@ w32_reset_terminal_modes (void)
 
 /* Function prototypes of this page.  */
 
-static XCharStruct *w32_per_char_metric P_ ((XFontStruct *,
-                                             wchar_t *, int));
+XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, int));
 static int w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
 
 
@@ -888,6 +922,16 @@ w32_native_per_char_metric (font, char2b, font_type, pcm)
          int real_width;
          GetCharWidth (hdc, *char2b, *char2b, &real_width);
 #endif
+         if (cleartype_active)
+           {
+             /* Cleartype antialiasing causes characters to overhang
+                by a pixel on each side compared with what GetCharABCWidths
+                reports.  */
+             char_widths.abcA -= 1;
+             char_widths.abcC -= 1;
+             char_widths.abcB += 2;
+           }
+
          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
@@ -945,7 +989,7 @@ w32_native_per_char_metric (font, char2b, font_type, pcm)
 }
 
 
-static XCharStruct *
+XCharStruct *
 w32_per_char_metric (font, char2b, font_type)
      XFontStruct *font;
      wchar_t *char2b;
@@ -1197,7 +1241,6 @@ w32_text_out (s, x, y,chars,nchars)
 }
 
 
-
 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 *,
@@ -1525,7 +1568,7 @@ x_draw_glyph_string_foreground (s)
   else
     x = s->x;
 
-  if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR))
+  if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR))
     SetBkMode (s->hdc, TRANSPARENT);
   else
     SetBkMode (s->hdc, OPAQUE);
@@ -1911,15 +1954,9 @@ x_draw_glyph_string_box (s)
   struct glyph *last_glyph;
   RECT clip_rect;
 
-  last_x = window_box_right (s->w, s->area);
-  if (s->row->full_width_p
-      && !s->w->pseudo_window_p)
-    {
-      last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
-      if (s->area != RIGHT_MARGIN_AREA
-         || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
-       last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
-    }
+  last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
+           ? WINDOW_RIGHT_EDGE_X (s->w)
+           : window_box_right (s->w, s->area));
 
   /* The glyph that may have a right box line.  */
   last_glyph = (s->cmp || s->img
@@ -2049,7 +2086,6 @@ x_draw_image_foreground (s)
 }
 
 
-
 /* Draw a relief around the image glyph string S.  */
 
 static void
@@ -2413,7 +2449,7 @@ x_draw_glyph_string (s)
   /* If S draws into the background of its successor, draw the
      background of the successor first so that S can draw into it.
      This makes S->next use XDrawString instead of XDrawImageString.  */
-  if (s->next && s->right_overhang && !s->for_overlaps_p)
+  if (s->next && s->right_overhang && !s->for_overlaps)
     {
       xassert (s->next->img == NULL);
       x_set_glyph_string_gc (s->next);
@@ -2426,7 +2462,7 @@ x_draw_glyph_string (s)
 
   /* Draw relief (if any) in advance for char/composition so that the
      glyph string can be drawn over it.  */
-  if (!s->for_overlaps_p
+  if (!s->for_overlaps
       && s->face->box != FACE_NO_BOX
       && (s->first_glyph->type == CHAR_GLYPH
          || s->first_glyph->type == COMPOSITE_GLYPH))
@@ -2452,7 +2488,7 @@ x_draw_glyph_string (s)
       break;
 
     case CHAR_GLYPH:
-      if (s->for_overlaps_p)
+      if (s->for_overlaps)
        s->background_filled_p = 1;
       else
         x_draw_glyph_string_background (s, 0);
@@ -2460,7 +2496,7 @@ x_draw_glyph_string (s)
       break;
 
     case COMPOSITE_GLYPH:
-      if (s->for_overlaps_p || s->gidx > 0)
+      if (s->for_overlaps || s->gidx > 0)
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 1);
@@ -2471,7 +2507,7 @@ x_draw_glyph_string (s)
       abort ();
     }
 
-  if (!s->for_overlaps_p)
+  if (!s->for_overlaps)
     {
       /* Draw underline.  */
       if (s->face->underline_p
@@ -2481,7 +2517,9 @@ x_draw_glyph_string (s)
           unsigned long dy = s->height - h;
 
          /* TODO: Use font information for positioning and thickness
-            of underline.  See OUTLINETEXTMETRIC, and xterm.c.  */
+            of underline.  See OUTLINETEXTMETRIC, and xterm.c.
+            Note: If you make this work, don't forget to change the
+            doc string of x-use-underline-position-properties below.  */
           if (s->face->underline_defaulted_p)
             {
               w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
@@ -2506,7 +2544,7 @@ x_draw_glyph_string (s)
         }
           else
             {
-              w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
+              w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
                              s->y + dy, s->width, h);
             }
         }
@@ -2753,9 +2791,13 @@ x_scroll_run (w, run)
     /* If the dirty region is not what we expected, redraw the entire frame.  */
     if (!EqualRgn (combined, expect_dirty))
       SET_FRAME_GARBAGED (f);
+
+    DeleteObject (dirty);
+    DeleteObject (combined);
   }
 
   UNBLOCK_INPUT;
+  DeleteObject (expect_dirty);
 }
 
 
@@ -2800,23 +2842,90 @@ x_new_focus_frame (dpyinfo, frame)
       if (old_focus && old_focus->auto_lower)
        x_lower_frame (old_focus);
 
+      if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
+       pending_autoraise_frame = dpyinfo->w32_focus_frame;
+      else
+       pending_autoraise_frame = 0;
+    }
 
+  x_frame_rehighlight (dpyinfo);
+}
 
 
+/* Handle FocusIn and FocusOut state changes for FRAME.
+   If FRAME has focus and there exists more than one frame, puts
+   a FOCUS_IN_EVENT into *BUFP.  */
 
+static void
+x_focus_changed (type, state, dpyinfo, frame, bufp)
+     int type;
+     int state;
+     struct w32_display_info *dpyinfo;
+     struct frame *frame;
+     struct input_event *bufp;
+{
+  if (type == WM_SETFOCUS)
+    {
+      if (dpyinfo->w32_focus_event_frame != frame)
+        {
+          x_new_focus_frame (dpyinfo, frame);
+          dpyinfo->w32_focus_event_frame = frame;
+
+          /* Don't stop displaying the initial startup message
+             for a switch-frame event we don't need.  */
+          if (GC_NILP (Vterminal_frame)
+              && GC_CONSP (Vframe_list)
+              && !GC_NILP (XCDR (Vframe_list)))
+            {
+              bufp->kind = FOCUS_IN_EVENT;
+              XSETFRAME (bufp->frame_or_window, frame);
+            }
+        }
 
+      frame->output_data.x->focus_state |= state;
 
+      /* TODO: IME focus?  */
+    }
+  else if (type == WM_KILLFOCUS)
+    {
+      frame->output_data.x->focus_state &= ~state;
 
+      if (dpyinfo->w32_focus_event_frame == frame)
+        {
+          dpyinfo->w32_focus_event_frame = 0;
+          x_new_focus_frame (dpyinfo, 0);
+        }
 
-      if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
-       pending_autoraise_frame = dpyinfo->w32_focus_frame;
-      else
-       pending_autoraise_frame = 0;
+      /* TODO: IME focus?  */
     }
+}
 
-  x_frame_rehighlight (dpyinfo);
+
+/* The focus may have changed.  Figure out if it is a real focus change,
+   by checking both FocusIn/Out and Enter/LeaveNotify events.
+
+   Returns FOCUS_IN_EVENT event in *BUFP. */
+
+static void
+w32_detect_focus_change (dpyinfo, event, bufp)
+     struct w32_display_info *dpyinfo;
+     W32Msg *event;
+     struct input_event *bufp;
+{
+  struct frame *frame;
+
+  frame = x_any_window_to_frame (dpyinfo, event->msg.hwnd);
+  if (! frame)
+    return;
+
+  /* On w32, this is only called from focus events, so no switch needed.  */
+  x_focus_changed (event->msg.message,
+                  (event->msg.message == WM_KILLFOCUS ?
+                   FOCUS_IMPLICIT : FOCUS_EXPLICIT),
+                  dpyinfo, frame, bufp);
 }
 
+
 /* Handle an event saying the mouse has moved out of an Emacs frame.  */
 
 void
@@ -3022,8 +3131,10 @@ construct_mouse_wheel (result, msg, f)
   result->modifiers = (msg->dwModifiers
                        | ((delta < 0 ) ? down_modifier : up_modifier));
 
-  p.x = LOWORD (msg->msg.lParam);
-  p.y = HIWORD (msg->msg.lParam);
+  /* With multiple monitors, we can legitimately get negative
+     coordinates, so cast to short to interpret them correctly.  */
+  p.x = (short) LOWORD (msg->msg.lParam);
+  p.y = (short) HIWORD (msg->msg.lParam);
   ScreenToClient (msg->msg.hwnd, &p);
   XSETINT (result->x, p.x);
   XSETINT (result->y, p.y);
@@ -3079,8 +3190,8 @@ construct_drag_n_drop (result, msg, f)
   DragFinish (hdrop);
 
   XSETFRAME (frame, f);
-  result->frame_or_window = Fcons (frame, files);
-  result->arg = Qnil;
+  result->frame_or_window = frame;
+  result->arg = files;
   return Qnil;
 }
 
@@ -3096,9 +3207,7 @@ construct_drag_n_drop (result, msg, f)
 static MSG last_mouse_motion_event;
 static Lisp_Object last_mouse_motion_frame;
 
-static void remember_mouse_glyph P_ ((struct frame *, int, int));
-
-static void
+static int
 note_mouse_movement (frame, msg)
      FRAME_PTR frame;
      MSG *msg;
@@ -3115,13 +3224,16 @@ note_mouse_movement (frame, msg)
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
       note_mouse_highlight (frame, -1, -1);
+      last_mouse_glyph_frame = 0;
+      return 1;
     }
 
   /* Has the mouse moved off the glyph it was on at the last sighting?  */
-  else if (mouse_x < last_mouse_glyph.left
-          || mouse_x > last_mouse_glyph.right
-          || mouse_y < last_mouse_glyph.top
-          || mouse_y > last_mouse_glyph.bottom)
+  if (frame != last_mouse_glyph_frame
+      || mouse_x < last_mouse_glyph.left
+      || mouse_x >= last_mouse_glyph.right
+      || mouse_y < last_mouse_glyph.top
+      || mouse_y >= last_mouse_glyph.bottom)
     {
       frame->mouse_moved = 1;
       last_mouse_scroll_bar = Qnil;
@@ -3130,8 +3242,12 @@ note_mouse_movement (frame, msg)
         gets called when mouse tracking is enabled but we also need
         to keep track of the mouse for help_echo and highlighting at
         other times.  */
-      remember_mouse_glyph (frame, mouse_x, mouse_y);
+      remember_mouse_glyph (frame, mouse_x, mouse_y, &last_mouse_glyph);
+      last_mouse_glyph_frame = frame;
+      return 1;
     }
+
+  return 0;
 }
 
 \f
@@ -3142,8 +3258,6 @@ note_mouse_movement (frame, msg)
 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 int glyph_rect P_ ((struct frame *f, int, int, RECT *));
-
 
 static void
 redo_mouse_highlight ()
@@ -3162,108 +3276,6 @@ w32_define_cursor (window, cursor)
 {
   PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
 }
-
-/* Try to determine frame pixel position and size of the glyph under
-   frame pixel coordinates X/Y on frame F .  Return the position and
-   size in *RECT.  Value is non-zero if we could compute these
-   values.  */
-
-static int
-glyph_rect (f, x, y, rect)
-     struct frame *f;
-     int x, y;
-     RECT *rect;
-{
-  Lisp_Object window;
-
-  window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
-
-  if (!NILP (window))
-    {
-      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;
-
-      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;
-
-           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.  */
-               /* Shouldn't this be a pixel value?
-                  WINDOW_LEFT_EDGE_X (w) seems to be the right value.
-                  ++KFS */
-               rect->left = WINDOW_LEFT_EDGE_COL (w);
-               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->right = rect->left + g->pixel_width;
-                 return 1;
-               }
-
-           /* x is to the right of the last glyph in the row.  */
-           rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
-           /* Shouldn't this be a pixel value?
-              WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
-              ++KFS */
-           rect->right = WINDOW_RIGHT_EDGE_COL (w);
-           return 1;
-         }
-    }
-
-  /* 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)
-     struct frame * f1;
-     int gx, gy;
-{
-  if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
-    {
-      int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
-      int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
-
-      /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
-        round down even for negative values.  */
-      if (gx < 0)
-       gx -= width - 1;
-      if (gy < 0)
-       gy -= height - 1;
-#if 0
-      /* This was the original code from XTmouse_position, but it seems
-        to give the position of the glyph diagonally next to the one
-        the mouse is over.  */
-      gx = (gx + width - 1) / width * width;
-      gy = (gy + height - 1) / height * height;
-#else
-      gx = gx / width * width;
-      gy = gy / height * height;
-#endif
-
-      last_mouse_glyph.left = gx;
-      last_mouse_glyph.top = gy;
-      last_mouse_glyph.right  = gx + width;
-      last_mouse_glyph.bottom = gy + height;
-    }
-}
-
 /* Return the current position of the mouse.
    *fp should be a frame which indicates which display to ask about.
 
@@ -3355,19 +3367,9 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time)
               on it, i.e. into the same rectangles that matrices on
               the frame are divided into.  */
 
-#if OLD_REDISPLAY_CODE
-           int ignore1, ignore2;
-
            ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
-
-           pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
-                                  &last_mouse_glyph,
-                                  FRAME_W32_DISPLAY_INFO (f1)->grabbed
-                                  || insist);
-#else
-           ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
-           remember_mouse_glyph (f1, pt.x, pt.y);
-#endif
+           remember_mouse_glyph (f1, pt.x, pt.y, &last_mouse_glyph);
+           last_mouse_glyph_frame = f1;
 
            *bar_window = Qnil;
            *part = 0;
@@ -3529,7 +3531,7 @@ my_create_scrollbar (f, bar)
 
 /*#define ATTACH_THREADS*/
 
-BOOL
+static BOOL
 my_show_window (FRAME_PTR f, HWND hwnd, int how)
 {
 #ifndef ATTACH_THREADS
@@ -3540,7 +3542,7 @@ my_show_window (FRAME_PTR f, HWND hwnd, int how)
 #endif
 }
 
-void
+static void
 my_set_window_pos (HWND hwnd, HWND hwndAfter,
                   int x, int y, int cx, int cy, UINT flags)
 {
@@ -3558,7 +3560,7 @@ my_set_window_pos (HWND hwnd, HWND hwndAfter,
 #endif
 }
 
-void
+static void
 my_set_focus (f, hwnd)
      struct frame * f;
      HWND hwnd;
@@ -3567,14 +3569,15 @@ my_set_focus (f, hwnd)
               (WPARAM) hwnd, 0);
 }
 
-void
+static void
 my_set_foreground_window (hwnd)
      HWND hwnd;
 {
   SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
 }
 
-void
+
+static void
 my_destroy_window (f, hwnd)
      struct frame * f;
      HWND hwnd;
@@ -4177,8 +4180,7 @@ w32_read_socket (sd, expected, hold_quit)
   /* So people can tell when we have read the available input.  */
   input_signal_count++;
 
-  /* TODO: tool-bars, ghostscript integration, mouse
-     cursors. */
+  /* TODO: ghostscript integration. */
   while (get_next_msg (&msg, FALSE))
     {
       struct input_event inev;
@@ -4260,7 +4262,8 @@ w32_read_socket (sd, expected, hold_quit)
 
          if (f && !f->iconified)
            {
-             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+                 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
                {
                  clear_mouse_face (dpyinfo);
                  dpyinfo->mouse_face_hidden = 1;
@@ -4283,7 +4286,8 @@ w32_read_socket (sd, expected, hold_quit)
 
          if (f && !f->iconified)
            {
-             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+                 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
                {
                  clear_mouse_face (dpyinfo);
                  dpyinfo->mouse_face_hidden = 1;
@@ -4312,6 +4316,7 @@ w32_read_socket (sd, expected, hold_quit)
          }
 
           previous_help_echo_string = help_echo_string;
+         help_echo_string = Qnil;
 
          if (dpyinfo->grabbed && last_mouse_frame
              && FRAME_LIVE_P (last_mouse_frame))
@@ -4350,7 +4355,8 @@ w32_read_socket (sd, expected, hold_quit)
 
                  last_window=window;
                }
-             note_mouse_movement (f, &msg.msg);
+             if (!note_mouse_movement (f, &msg.msg))
+               help_echo_string = previous_help_echo_string;
            }
          else
             {
@@ -4361,10 +4367,16 @@ w32_read_socket (sd, expected, hold_quit)
 
           /* If the contents of the global variable help_echo_string
              has changed, generate a HELP_EVENT.  */
+#if 0 /* The below is an invalid comparison when USE_LISP_UNION_TYPE.
+        But it was originally changed to this to fix a bug, so I have
+        not removed it completely in case the bug is still there.  */
           if (help_echo_string != previous_help_echo_string ||
              (!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved))
+#else /* This is what xterm.c does.  */
+           if (!NILP (help_echo_string)
+               || !NILP (previous_help_echo_string))
            do_help = 1;
-
+#endif
           break;
 
        case WM_LBUTTONDOWN:
@@ -4565,7 +4577,7 @@ w32_read_socket (sd, expected, hold_quit)
                  f->async_visible = 1;
                  f->async_iconified = 0;
 
-                 /* wait_reading_process_input will notice this and update
+                 /* wait_reading_process_output will notice this and update
                     the frame's display structures.  */
                  SET_FRAME_GARBAGED (f);
 
@@ -4656,28 +4668,13 @@ w32_read_socket (sd, expected, hold_quit)
          break;
 
        case WM_SETFOCUS:
-         /* TODO: Port this change:
-            2002-06-28  Jan D.  <jan.h.d@swipnet.se>
-            * xterm.h (struct x_output): Add focus_state.
-            * xterm.c (x_focus_changed): New function.
-            (x_detect_focus_change): New function.
-            (XTread_socket): Call x_detect_focus_change for FocusIn/FocusOut
-            EnterNotify and LeaveNotify to track X focus changes.
-         */
-         f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
-
-          dpyinfo->w32_focus_event_frame = f;
-
-          if (f)
-            x_new_focus_frame (dpyinfo, f);
-
+         w32_detect_focus_change (dpyinfo, &msg, &inev);
 
          dpyinfo->grabbed = 0;
          check_visibility = 1;
          break;
 
        case WM_KILLFOCUS:
-          /* TODO: some of this belongs in MOUSE_LEAVE */
          f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
 
           if (f)
@@ -4785,7 +4782,7 @@ w32_read_socket (sd, expected, hold_quit)
 
          if (do_help > 0)
            {
-             if (help_echo_string == Qnil)
+             if (NILP (help_echo_string))
                {
                  help_echo_object = help_echo_window = Qnil;
                  help_echo_pos = -1;
@@ -4889,7 +4886,6 @@ w32_read_socket (sd, expected, hold_quit)
 }
 
 
-
 \f
 /***********************************************************************
                             Text Cursor
@@ -4903,18 +4899,19 @@ w32_read_socket (sd, expected, hold_quit)
    mode lines must be clipped to the whole window.  */
 
 static void
-w32_clip_to_row (w, row, hdc)
+w32_clip_to_row (w, row, area, hdc)
      struct window *w;
      struct glyph_row *row;
+     int area;
      HDC hdc;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   RECT clip_rect;
-  int window_y, window_width;
+  int window_x, window_y, window_width;
 
-  window_box (w, -1, 0, &window_y, &window_width, 0);
+  window_box (w, area, &window_x, &window_y, &window_width, 0);
 
-  clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
+  clip_rect.left = window_x;
   clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
   clip_rect.top = max (clip_rect.top, window_y);
   clip_rect.right = clip_rect.left + window_width;
@@ -4934,37 +4931,25 @@ x_draw_hollow_cursor (w, row)
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   HDC hdc;
   RECT rect;
-  int wd;
+  int h;
   struct glyph *cursor_glyph;
   HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
 
-  /* Compute frame-relative coordinates from window-relative
-     coordinates.  */
-  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;
-
   /* Get the glyph the cursor is on.  If we can't tell because
      the current matrix is invalid or such, give up.  */
   cursor_glyph = get_phys_cursor_glyph (w);
   if (cursor_glyph == NULL)
     return;
 
-  /* Compute the width of the rectangle to draw.  If on a stretch
-     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;
-  if (cursor_glyph->type == STRETCH_GLYPH
-      && !x_stretch_cursor_p)
-    wd = min (FRAME_COLUMN_WIDTH (f), wd);
-  w->phys_cursor_width = wd;
+  /* Compute frame-relative coordinates for phys cursor.  */
+  rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+  rect.top = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
+  rect.bottom = rect.top + h;
+  rect.right = rect.left + w->phys_cursor_width;
 
-  rect.right = rect.left + wd;
   hdc = get_frame_dc (f);
   /* Set clipping, draw the rectangle, and reset clipping again.  */
-  w32_clip_to_row (w, row, hdc);
+  w32_clip_to_row (w, row, TEXT_AREA, hdc);
   FrameRect (hdc, &rect, hb);
   DeleteObject (hb);
   w32_set_clip_rectangle (hdc, NULL);
@@ -5030,7 +5015,7 @@ x_draw_bar_cursor (w, row, width, kind)
 
 
       hdc = get_frame_dc (f);
-      w32_clip_to_row (w, row, hdc);
+      w32_clip_to_row (w, row, TEXT_AREA, hdc);
 
       if (kind == BAR_CURSOR)
        {
@@ -5180,16 +5165,25 @@ x_bitmap_icon (f, icon)
      struct frame *f;
      Lisp_Object icon;
 {
-  HANDLE hicon;
+  HANDLE main_icon;
+  HANDLE small_icon = NULL;
 
   if (FRAME_W32_WINDOW (f) == 0)
     return 1;
 
   if (NILP (icon))
-    hicon = LoadIcon (hinst, EMACS_CLASS);
+    main_icon = LoadIcon (hinst, EMACS_CLASS);
   else if (STRINGP (icon))
-    hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
-                      LR_DEFAULTSIZE | LR_LOADFROMFILE);
+    {
+      /* Load the main icon from the named file.  */
+      main_icon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
+                            LR_DEFAULTSIZE | LR_LOADFROMFILE);
+      /* Try to load a small icon to go with it.  */
+      small_icon = LoadImage (NULL, (LPCSTR) SDATA (icon), IMAGE_ICON,
+                             GetSystemMetrics (SM_CXSMICON),
+                             GetSystemMetrics (SM_CYSMICON),
+                             LR_LOADFROMFILE);
+    }
   else if (SYMBOLP (icon))
     {
       LPCTSTR name;
@@ -5209,16 +5203,21 @@ x_bitmap_icon (f, icon)
       else
        return 1;
 
-      hicon = LoadIcon (NULL, name);
+      main_icon = LoadIcon (NULL, name);
     }
   else
     return 1;
 
-  if (hicon == NULL)
+  if (main_icon == NULL)
     return 1;
 
   PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
-               (LPARAM) hicon);
+               (LPARAM) main_icon);
+
+  /* If there is a small icon that goes with it, set that too.  */
+  if (small_icon)
+    PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_SMALL,
+                (LPARAM) small_icon);
 
   return 0;
 }
@@ -5235,6 +5234,8 @@ x_error_catcher (display, error)
 x_catch_errors (dpy)
 x_catch_errors_unwind (old_val)
 x_check_errors (dpy, format)
+x_fully_uncatch_errors ()
+x_catching_errors ()
 x_had_errors_p (dpy)
 x_clear_errors (dpy)
 x_uncatch_errors (dpy, count)
@@ -5270,7 +5271,8 @@ x_new_font (f, fontname)
   FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
   FRAME_FONTSET (f) = -1;
 
-  FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
+  FRAME_COLUMN_WIDTH (f) = fontp->average_width;
+  FRAME_SPACE_WIDTH (f) = fontp->space_width;
   FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
 
   compute_fringe_widths (f, 1);
@@ -5354,47 +5356,17 @@ void
 x_calc_absolute_position (f)
      struct frame *f;
 {
-  POINT pt;
   int flags = f->size_hint_flags;
 
-  pt.x = pt.y = 0;
-
-  /* Find the position of the outside upper-left corner of
-     the inner window, with respect to the outer window.
-     But do this only if we will need the results.  */
-  if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
-    {
-      BLOCK_INPUT;
-      MapWindowPoints (FRAME_W32_WINDOW (f),
-                      f->output_data.w32->parent_desc,
-                      &pt, 1);
-      UNBLOCK_INPUT;
-    }
-
-  {
-      RECT rt;
-      rt.left = rt.right = rt.top = rt.bottom = 0;
-
-      BLOCK_INPUT;
-      AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
-                      FRAME_EXTERNAL_MENU_BAR (f));
-      UNBLOCK_INPUT;
-
-      pt.x += (rt.right - rt.left);
-      pt.y += (rt.bottom - rt.top);
-  }
-
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
     f->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
-                  - 2 * f->border_width - pt.x
                   - FRAME_PIXEL_WIDTH (f)
                   + f->left_pos);
 
   if (flags & YNegative)
     f->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
-                 - 2 * f->border_width - pt.y
                  - FRAME_PIXEL_HEIGHT (f)
                  + f->top_pos);
   /* The left_pos and top_pos
@@ -6370,6 +6342,12 @@ w32_initialize ()
   w32_system_caret_x = 0;
   w32_system_caret_y = 0;
 
+  /* 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;
+
   last_tool_bar_item = -1;
   any_help_event_p = 0;
 
@@ -6414,6 +6392,8 @@ w32_initialize ()
   /* Dynamically link to optional system components. */
   {
     HANDLE user_lib = LoadLibrary ("user32.dll");
+    UINT smoothing_type;
+    BOOL smoothing_enabled;
 
 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
 
@@ -6434,6 +6414,28 @@ w32_initialize ()
        effectively form the border of the main scroll bar range.  */
     vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
       = GetSystemMetrics (SM_CYVSCROLL);
+
+    /* Constants that are not always defined by the system headers
+       since they only exist on certain versions of Windows.  */
+#ifndef SPI_GETFONTSMOOTHING
+#define SPI_GETFONTSMOOTHING 0x4A
+#endif
+#ifndef SPI_GETFONTSMOOTHINGTYPE
+#define SPI_GETFONTSMOOTHINGTYPE 0x0200A
+#endif
+#ifndef FE_FONTSMOOTHINGCLEARTYPE
+#define FE_FONTSMOOTHINGCLEARTYPE 0x2
+#endif
+
+    /* Determine if Cleartype is in use.  Used to enable a hack in
+       the char metric calculations which adds extra pixels to
+       compensate for the "sub-pixels" that are not counted by the
+       system APIs. */
+    cleartype_active =
+      SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &smoothing_enabled, 0)
+      && smoothing_enabled
+      && SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, 0, &smoothing_type, 0)
+      && smoothing_type == FE_FONTSMOOTHINGCLEARTYPE;
   }
 }
 
@@ -6450,9 +6452,9 @@ syms_of_w32term ()
   Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
 
   DEFVAR_INT ("w32-num-mouse-buttons",
-             &Vw32_num_mouse_buttons,
+             &w32_num_mouse_buttons,
              doc: /* Number of physical mouse buttons.  */);
-  Vw32_num_mouse_buttons = Qnil;
+  w32_num_mouse_buttons = 2;
 
   DEFVAR_LISP ("w32-swap-mouse-buttons",
              &Vw32_swap_mouse_buttons,
@@ -6503,11 +6505,19 @@ 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;
+  w32_use_visible_system_caret = 0;
+
+  /* We don't yet support this, but defining this here avoids whining
+     from cus-start.el and other places, like "M-x set-variable".  */
+  DEFVAR_BOOL ("x-use-underline-position-properties",
+              &x_use_underline_position_properties,
+     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.
+
+NOTE: Not supported on MS-Windows yet.  */);
+  x_use_underline_position_properties = 0;
 
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
               doc: /* If not nil, Emacs uses toolkit scroll bars.  */);