*** empty log message ***
[bpt/emacs.git] / src / xdisp.c
index f800737..73ab892 100644 (file)
@@ -1,5 +1,5 @@
 /* Display generation from window structure and buffer text.
-   Copyright (C) 1985,86,87,88,93,94,95,97,98,99, 2000, 2001, 2002, 2003
+   Copyright (C) 1985,86,87,88,93,94,95,97,98,99,2000,01,02,03
    Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -176,6 +176,7 @@ Boston, MA 02111-1307, USA.  */
 #include "termchar.h"
 #include "dispextern.h"
 #include "buffer.h"
+#include "character.h"
 #include "charset.h"
 #include "indent.h"
 #include "commands.h"
@@ -198,6 +199,12 @@ Boston, MA 02111-1307, USA.  */
 #endif
 #ifdef MAC_OS
 #include "macterm.h"
+
+Cursor No_Cursor;
+#endif
+
+#ifndef FRAME_X_OUTPUT
+#define FRAME_X_OUTPUT(f) ((f)->output_data.x)
 #endif
 
 #define INFINITY 10000000
@@ -418,8 +425,8 @@ static EMACS_INT scroll_conservatively;
 
 /* Recenter the window whenever point gets within this many lines of
    the top or bottom of the window.  This value is translated into a
-   pixel value by multiplying it with CANON_Y_UNIT, which means that
-   there is really a fixed pixel height scroll margin.  */
+   pixel value by multiplying it with FRAME_LINE_HEIGHT, which means
+   that there is really a fixed pixel height scroll margin.  */
 
 EMACS_INT scroll_margin;
 
@@ -668,11 +675,13 @@ static enum prop_handled handle_display_prop P_ ((struct it *));
 static enum prop_handled handle_composition_prop P_ ((struct it *));
 static enum prop_handled handle_overlay_change P_ ((struct it *));
 static enum prop_handled handle_fontified_prop P_ ((struct it *));
+static enum prop_handled handle_auto_composed_prop P_ ((struct it *));
 
 /* Properties handled by iterators.  */
 
 static struct props it_props[] =
 {
+  {&Qauto_composed,    AUTO_COMPOSED_PROP_IDX, handle_auto_composed_prop},
   {&Qfontified,                FONTIFIED_PROP_IDX,     handle_fontified_prop},
   /* Handle `face' before `display' because some sub-properties of
      `display' need to know the face.  */
@@ -906,15 +915,13 @@ INLINE int
 window_text_bottom_y (w)
      struct window *w;
 {
-  struct frame *f = XFRAME (w->frame);
-  int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
+  int height = WINDOW_TOTAL_HEIGHT (w);
 
   if (WINDOW_WANTS_MODELINE_P (w))
     height -= CURRENT_MODE_LINE_HEIGHT (w);
   return height;
 }
 
-
 /* Return the pixel width of display area AREA of window W.  AREA < 0
    means return the total width of W, not including fringes to
    the left and right of the window.  */
@@ -924,29 +931,36 @@ window_box_width (w, area)
      struct window *w;
      int area;
 {
-  struct frame *f = XFRAME (w->frame);
-  int width = XFASTINT (w->width);
+  int cols = XFASTINT (w->total_cols);
+  int pixels = 0;
 
   if (!w->pseudo_window_p)
     {
-      width -= FRAME_SCROLL_BAR_WIDTH (f) + FRAME_FRINGE_COLS (f);
+      cols -= WINDOW_SCROLL_BAR_COLS (w);
 
       if (area == TEXT_AREA)
        {
-         if (INTEGERP (w->left_margin_width))
-           width -= XFASTINT (w->left_margin_width);
-         if (INTEGERP (w->right_margin_width))
-           width -= XFASTINT (w->right_margin_width);
+         if (INTEGERP (w->left_margin_cols))
+           cols -= XFASTINT (w->left_margin_cols);
+         if (INTEGERP (w->right_margin_cols))
+           cols -= XFASTINT (w->right_margin_cols);
+         pixels = -WINDOW_TOTAL_FRINGE_WIDTH (w);
        }
       else if (area == LEFT_MARGIN_AREA)
-       width = (INTEGERP (w->left_margin_width)
-                ? XFASTINT (w->left_margin_width) : 0);
+       {
+         cols = (INTEGERP (w->left_margin_cols)
+                  ? XFASTINT (w->left_margin_cols) : 0);
+         pixels = 0;
+       }
       else if (area == RIGHT_MARGIN_AREA)
-       width = (INTEGERP (w->right_margin_width)
-                ? XFASTINT (w->right_margin_width) : 0);
+       {
+         cols = (INTEGERP (w->right_margin_cols)
+                  ? XFASTINT (w->right_margin_cols) : 0);
+         pixels = 0;
+       }
     }
 
-  return width * CANON_X_UNIT (f);
+  return cols * WINDOW_FRAME_COLUMN_WIDTH (w) + pixels;
 }
 
 
@@ -958,7 +972,7 @@ window_box_height (w)
      struct window *w;
 {
   struct frame *f = XFRAME (w->frame);
-  int height = XFASTINT (w->height) * CANON_Y_UNIT (f);
+  int height = WINDOW_TOTAL_HEIGHT (w);
 
   xassert (height >= 0);
 
@@ -997,6 +1011,51 @@ window_box_height (w)
   return max (0, height);
 }
 
+/* Return the window-relative coordinate of the left edge of display
+   area AREA of window W.  AREA < 0 means return the left edge of the
+   whole window, to the right of the left fringe of W.  */
+
+INLINE int
+window_box_left_offset (w, area)
+     struct window *w;
+     int area;
+{
+  int x;
+
+  if (w->pseudo_window_p)
+    return 0;
+
+  x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
+
+  if (area == TEXT_AREA)
+    x += (WINDOW_LEFT_FRINGE_WIDTH (w)
+         + window_box_width (w, LEFT_MARGIN_AREA));
+  else if (area == RIGHT_MARGIN_AREA)
+    x += (WINDOW_LEFT_FRINGE_WIDTH (w)
+         + window_box_width (w, LEFT_MARGIN_AREA)
+         + window_box_width (w, TEXT_AREA)
+         + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+            ? 0
+            : WINDOW_RIGHT_FRINGE_WIDTH (w)));
+  else if (area == LEFT_MARGIN_AREA
+          && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
+    x += WINDOW_LEFT_FRINGE_WIDTH (w);
+
+  return x;
+}
+
+
+/* Return the window-relative coordinate of the right edge of display
+   area AREA of window W.  AREA < 0 means return the left edge of the
+   whole window, to the left of the right fringe of W.  */
+
+INLINE int
+window_box_right_offset (w, area)
+     struct window *w;
+     int area;
+{
+  return window_box_left_offset (w, area) + window_box_width (w, area);
+}
 
 /* Return the frame-relative coordinate of the left edge of display
    area AREA of window W.  AREA < 0 means return the left edge of the
@@ -1008,19 +1067,13 @@ window_box_left (w, area)
      int area;
 {
   struct frame *f = XFRAME (w->frame);
-  int x = FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
+  int x;
 
-  if (!w->pseudo_window_p)
-    {
-      x += (WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f)
-           + FRAME_LEFT_FRINGE_WIDTH (f));
+  if (w->pseudo_window_p)
+    return FRAME_INTERNAL_BORDER_WIDTH (f);
 
-      if (area == TEXT_AREA)
-       x += window_box_width (w, LEFT_MARGIN_AREA);
-      else if (area == RIGHT_MARGIN_AREA)
-       x += (window_box_width (w, LEFT_MARGIN_AREA)
-             + window_box_width (w, TEXT_AREA));
-    }
+  x = (WINDOW_LEFT_EDGE_X (w)
+       + window_box_left_offset (w, area));
 
   return x;
 }
@@ -1038,7 +1091,6 @@ window_box_right (w, area)
   return window_box_left (w, area) + window_box_width (w, area);
 }
 
-
 /* Get the bounding box of the display area AREA of window W, without
    mode lines, in frame-relative coordinates.  AREA < 0 means the
    whole window, not including the left and right fringes of
@@ -1052,15 +1104,18 @@ window_box (w, area, box_x, box_y, box_width, box_height)
      int area;
      int *box_x, *box_y, *box_width, *box_height;
 {
-  struct frame *f = XFRAME (w->frame);
-
-  *box_width = window_box_width (w, area);
-  *box_height = window_box_height (w);
-  *box_x = window_box_left (w, area);
-  *box_y = (FRAME_INTERNAL_BORDER_WIDTH_SAFE (f)
-           + XFASTINT (w->top) * CANON_Y_UNIT (f));
-  if (WINDOW_WANTS_HEADER_LINE_P (w))
-    *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
+  if (box_width)
+    *box_width = window_box_width (w, area);
+  if (box_height)
+    *box_height = window_box_height (w);
+  if (box_x)
+    *box_x = window_box_left (w, area);
+  if (box_y)
+    {
+      *box_y = WINDOW_TOP_EDGE_Y (w);
+      if (WINDOW_WANTS_HEADER_LINE_P (w))
+       *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
+    }
 }
 
 
@@ -1178,7 +1233,7 @@ pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
     {
       int top_y = it.current_y;
       int bottom_y = line_bottom_y (&it);
-      int window_top_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+      int window_top_y = WINDOW_HEADER_LINE_HEIGHT (w);
 
       if (top_y < window_top_y)
        visible_p = bottom_y > window_top_y;
@@ -1398,6 +1453,113 @@ estimate_mode_line_height (f, face_id)
   return 1;
 }
 
+/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
+   co-ordinates in (*X, *Y).  Set *BOUNDS to the rectangle that the
+   glyph at X, Y occupies, if BOUNDS != 0.  If NOCLIP is non-zero, do
+   not force the value into range.  */
+
+void
+pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
+     FRAME_PTR f;
+     register int pix_x, pix_y;
+     int *x, *y;
+     NativeRectangle *bounds;
+     int noclip;
+{
+
+#ifdef HAVE_WINDOW_SYSTEM
+  if (FRAME_WINDOW_P (f))
+    {
+      /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to round down
+        even for negative values.  */
+      if (pix_x < 0)
+       pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
+      if (pix_y < 0)
+       pix_y -= FRAME_LINE_HEIGHT (f) - 1;
+
+      pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
+      pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
+
+      if (bounds)
+       STORE_NATIVE_RECT (*bounds,
+                          FRAME_COL_TO_PIXEL_X (f, pix_x),
+                          FRAME_LINE_TO_PIXEL_Y (f, pix_y),
+                          FRAME_COLUMN_WIDTH (f) - 1,
+                          FRAME_LINE_HEIGHT (f) - 1);
+
+      if (!noclip)
+       {
+         if (pix_x < 0)
+           pix_x = 0;
+         else if (pix_x > FRAME_TOTAL_COLS (f))
+           pix_x = FRAME_TOTAL_COLS (f);
+
+         if (pix_y < 0)
+           pix_y = 0;
+         else if (pix_y > FRAME_LINES (f))
+           pix_y = FRAME_LINES (f);
+       }
+    }
+#endif
+
+  *x = pix_x;
+  *y = pix_y;
+}
+
+
+/* Given HPOS/VPOS in the current matrix of W, return corresponding
+   frame-relative pixel positions in *FRAME_X and *FRAME_Y.  If we
+   can't tell the positions because W's display is not up to date,
+   return 0.  */
+
+int
+glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
+     struct window *w;
+     int hpos, vpos;
+     int *frame_x, *frame_y;
+{
+#ifdef HAVE_WINDOW_SYSTEM
+  if (FRAME_WINDOW_P (XFRAME (WINDOW_FRAME (w))))
+    {
+      int success_p;
+
+      xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
+      xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
+
+      if (display_completed)
+       {
+         struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
+         struct glyph *glyph = row->glyphs[TEXT_AREA];
+         struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
+
+         hpos = row->x;
+         vpos = row->y;
+         while (glyph < end)
+           {
+             hpos += glyph->pixel_width;
+             ++glyph;
+           }
+
+         success_p = 1;
+       }
+      else
+       {
+         hpos = vpos = 0;
+         success_p = 0;
+       }
+
+      *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, hpos);
+      *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, vpos);
+      return success_p;
+    }
+#endif
+
+  *frame_x = hpos;
+  *frame_y = vpos;
+  return 1;
+}
+
+
 #ifdef HAVE_WINDOW_SYSTEM
 
 /* Find the glyph under window-relative coordinates X/Y in window W.
@@ -1417,7 +1579,7 @@ x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
 {
   struct glyph *glyph, *end;
   struct glyph_row *row = NULL;
-  int x0, i, left_area_width;
+  int x0, i;
 
   /* Find row containing Y.  Give up if some row is not enabled.  */
   for (i = 0; i < w->current_matrix->nrows; ++i)
@@ -1444,21 +1606,20 @@ x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
     }
   else
     {
-      left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
-      if (x < left_area_width)
+      if (x < window_box_left_offset (w, TEXT_AREA))
        {
          *area = LEFT_MARGIN_AREA;
-         x0 = 0;
+         x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
        }
-      else if (x < left_area_width + window_box_width (w, TEXT_AREA))
+      else if (x < window_box_right_offset (w, TEXT_AREA))
        {
          *area = TEXT_AREA;
-         x0 = row->x + left_area_width;
+         x0 = window_box_left_offset (w, TEXT_AREA);
        }
       else
        {
          *area = RIGHT_MARGIN_AREA;
-         x0 = left_area_width + window_box_width (w, TEXT_AREA);
+         x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
        }
     }
 
@@ -1501,12 +1662,12 @@ frame_to_window_pixel_xy (w, x, y)
       /* A pseudo-window is always full-width, and starts at the
         left edge of the frame, plus a frame border.  */
       struct frame *f = XFRAME (w->frame);
-      *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
+      *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
       *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
     }
   else
     {
-      *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
+      *x -= WINDOW_LEFT_EDGE_X (w);
       *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
     }
 }
@@ -1523,20 +1684,9 @@ get_glyph_string_clip_rect (s, nr)
 
   if (s->row->full_width_p)
     {
-      /* Draw full-width.  X coordinates are relative to S->w->left.  */
-      int canon_x = CANON_X_UNIT (s->f);
-
-      r.x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
-      r.width = XFASTINT (s->w->width) * canon_x;
-
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
-       {
-         int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
-         if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
-           r.x -= width;
-       }
-
-      r.x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
+      /* Draw full-width.  X coordinates are relative to S->w->left_col.  */
+      r.x = WINDOW_LEFT_EDGE_X (s->w);
+      r.width = WINDOW_TOTAL_WIDTH (s->w);
 
       /* Unless displaying a mode or menu bar line, which are always
         fully visible, clip to the visible part of the row.  */
@@ -1548,7 +1698,7 @@ get_glyph_string_clip_rect (s, nr)
   else
     {
       /* This is a text line that may be partially visible.  */
-      r.x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
+      r.x = window_box_left (s->w, s->area);
       r.width = window_box_width (s->w, s->area);
       r.height = s->row->visible_height;
     }
@@ -1558,7 +1708,7 @@ get_glyph_string_clip_rect (s, nr)
      intentionally draws over other lines.  */
   if (s->for_overlaps_p)
     {
-      r.y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
+      r.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
       r.height = window_text_bottom_y (s->w) - r.y;
     }
   else
@@ -1568,14 +1718,14 @@ get_glyph_string_clip_rect (s, nr)
         partially visible lines at the top of a window.  */
       if (!s->row->full_width_p
          && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
-       r.y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
+       r.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
       else
        r.y = max (0, s->row->y);
 
       /* If drawing a tool-bar window, draw it over the internal border
         at the top of the window.  */
       if (s->w == XWINDOW (s->f->tool_bar_window))
-       r.y -= s->f->output_data.x->internal_border_width;
+       r.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
     }
 
   r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
@@ -1599,7 +1749,7 @@ get_glyph_string_clip_rect (s, nr)
   CONVERT_FROM_XRECT (r, *nr);
 #else
   *nr = r;
-#endif;
+#endif
 }
 
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -1974,12 +2124,12 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
     {
       /* Mode lines, menu bar in terminal frames.  */
       it->first_visible_x = 0;
-      it->last_visible_x = XFASTINT (w->width) * CANON_X_UNIT (it->f);
+      it->last_visible_x = WINDOW_TOTAL_WIDTH (w);
     }
   else
     {
       it->first_visible_x
-       = XFASTINT (it->w->hscroll) * CANON_X_UNIT (it->f);
+       = XFASTINT (it->w->hscroll) * FRAME_COLUMN_WIDTH (it->f);
       it->last_visible_x = (it->first_visible_x
                            + window_box_width (w, TEXT_AREA));
 
@@ -1996,7 +2146,7 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
        }
 
       it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
-      it->current_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w) + w->vscroll;
+      it->current_y = WINDOW_HEADER_LINE_HEIGHT (w) + w->vscroll;
     }
 
   /* Leave room for a border glyph.  */
@@ -2808,7 +2958,7 @@ face_before_or_after_it_pos (it, before_p)
          struct face *face = FACE_FROM_ID (it->f, face_id);
 
          c = string_char_and_length (p, rest, &len);
-         face_id = FACE_FOR_CHAR (it->f, face, c);
+         face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), it->string);
        }
     }
   else
@@ -2847,7 +2997,7 @@ face_before_or_after_it_pos (it, before_p)
        {
          int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
          struct face *face = FACE_FROM_ID (it->f, face_id);
-         face_id = FACE_FOR_CHAR (it->f, face, c);
+         face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
        }
     }
 
@@ -3453,7 +3603,9 @@ single_display_prop_intangible_p (prop)
        return 0;
     }
 
-  return CONSP (prop) && EQ (XCAR (prop), Qimage);
+  return (CONSP (prop)
+         && (EQ (XCAR (prop), Qimage)
+             || EQ (XCAR (prop), Qspace)));
 }
 
 
@@ -3616,6 +3768,90 @@ string_buffer_position (w, string, around_charpos)
                        `composition' property
  ***********************************************************************/
 
+static enum prop_handled
+handle_auto_composed_prop (it)
+     struct it *it;
+{
+  enum prop_handled handled = HANDLED_NORMALLY;
+
+  if (FUNCTIONP (Vauto_composition_function))
+    {
+      Lisp_Object val;
+      EMACS_INT pos, this_pos;
+
+      if (STRINGP (it->string))
+       pos = IT_STRING_CHARPOS (*it);
+      else
+       pos = IT_CHARPOS (*it);
+      this_pos = pos;
+
+      val =Fget_char_property (make_number (pos), Qauto_composed, it->string);
+      if (! NILP (val))
+       {
+         Lisp_Object limit = Qnil, next;
+         
+         /* As Fnext_single_char_property_change is very slow, we
+            limit the search to the current line.  */
+         if (STRINGP (it->string))
+           limit = make_number (SCHARS (it->string));
+         else
+           limit = make_number (find_next_newline_no_quit (pos, 1));
+
+         next = (Fnext_single_property_change
+                    (make_number (pos), Qauto_composed, it->string, limit));
+         if (XINT (next) < XINT (limit))
+           {
+             /* The current point is auto-composed, but there exist
+                characters not yet composed beyond the auto-composed
+                region.  There's a possiblity that the last
+                characters in the region may be newly composed.  */
+             int charpos = XINT (next) - 1, bytepos, c;
+
+             if (STRINGP (it->string))
+               {
+                 bytepos = string_char_to_byte (it->string, charpos);
+                 c = SDATA (it->string)[bytepos];
+               }
+             else
+               {
+                 bytepos = CHAR_TO_BYTE (charpos);
+                 c = FETCH_BYTE (bytepos);
+               }
+             if (c != '\n')
+               /* If the last character is not newline, it may be
+                  composed with the following characters.  */
+               val = Qnil, pos = charpos + 1;
+           }
+       }
+      if (NILP (val))
+       {
+         int count = SPECPDL_INDEX ();
+         Lisp_Object args[3];
+
+         args[0] = Vauto_composition_function;
+         specbind (Qauto_composition_function, Qnil);
+         args[1] = make_number (pos);
+         args[2] = it->string;
+         safe_call (3, args);
+         unbind_to (count, Qnil);
+
+         if (this_pos == pos)
+           {
+             val = Fget_char_property (args[1], Qauto_composed, it->string);
+             /* Return HANDLED_RECOMPUTE_PROPS only if function composed
+                something.  This avoids an endless loop if they failed to
+                fontify the text for which reason ever.  */
+             if (! NILP (val))
+               handled = HANDLED_RECOMPUTE_PROPS;
+           }
+         else
+           handled = HANDLED_RECOMPUTE_PROPS;
+       }
+    }
+
+  return handled;
+}
+
 /* Set up iterator IT from `composition' property at its current
    position.  Called from handle_stop.  */
 
@@ -3624,7 +3860,7 @@ handle_composition_prop (it)
      struct it *it;
 {
   Lisp_Object prop, string;
-  int pos, pos_byte, end;
+  EMACS_INT pos, pos_byte, start, end;
   enum prop_handled handled = HANDLED_NORMALLY;
 
   if (STRINGP (it->string))
@@ -3643,11 +3879,20 @@ handle_composition_prop (it)
   /* If there's a valid composition and point is not inside of the
      composition (in the case that the composition is from the current
      buffer), draw a glyph composed from the composition components.  */
-  if (find_composition (pos, -1, &pos, &end, &prop, string)
-      && COMPOSITION_VALID_P (pos, end, prop)
-      && (STRINGP (it->string) || (PT <= pos || PT >= end)))
+  if (find_composition (pos, -1, &start, &end, &prop, string)
+      && COMPOSITION_VALID_P (start, end, prop)
+      && (STRINGP (it->string) || (PT <= start || PT >= end)))
     {
-      int id = get_composition_id (pos, pos_byte, end - pos, prop, string);
+      int id;
+
+      if (start != pos)
+       {
+         if (STRINGP (it->string))
+           pos_byte = string_char_to_byte (it->string, start);
+         else
+           pos_byte = CHAR_TO_BYTE (start);
+       }
+      id = get_composition_id (start, pos_byte, end - start, prop, string);
 
       if (id >= 0)
        {
@@ -3837,7 +4082,8 @@ load_overlay_strings (it, charpos)
      int charpos;
 {
   extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
-  Lisp_Object ov, overlay, window, str, invisible;
+  Lisp_Object overlay, window, str, invisible;
+  struct Lisp_Overlay *ov;
   int start, end;
   int size = 20;
   int n = 0, i, j, invis_p;
@@ -3877,9 +4123,9 @@ load_overlay_strings (it, charpos)
   while (0)
 
   /* Process overlay before the overlay center.  */
-  for (ov = current_buffer->overlays_before; CONSP (ov); ov = XCDR (ov))
+  for (ov = current_buffer->overlays_before; ov; ov = ov->next)
     {
-      overlay = XCAR (ov);
+      XSETMISC (overlay, ov);
       xassert (OVERLAYP (overlay));
       start = OVERLAY_POSITION (OVERLAY_START (overlay));
       end = OVERLAY_POSITION (OVERLAY_END (overlay));
@@ -3917,9 +4163,9 @@ load_overlay_strings (it, charpos)
     }
 
   /* Process overlays after the overlay center.  */
-  for (ov = current_buffer->overlays_after; CONSP (ov); ov = XCDR (ov))
+  for (ov = current_buffer->overlays_after; ov; ov = ov->next)
     {
-      overlay = XCAR (ov);
+      XSETMISC (overlay, ov);
       xassert (OVERLAYP (overlay));
       start = OVERLAY_POSITION (OVERLAY_START (overlay));
       end = OVERLAY_POSITION (OVERLAY_END (overlay));
@@ -4387,6 +4633,13 @@ reseat_1 (it, pos, set_stop_p)
   IT_STRING_BYTEPOS (*it) = -1;
   it->string = Qnil;
   it->method = next_element_from_buffer;
+  /* RMS: I added this to fix a bug in move_it_vertically_backward
+     where it->area continued to relate to the starting point
+     for the backward motion.  Bug report from
+     Nick Roberts <nick@nick.uklinux.net> on 19 May 2003.
+     However, I am not sure whether reseat still does the right thing
+     in general after this change.  */
+  it->area = TEXT_AREA;
   it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
   it->sp = 0;
   it->face_before_selective_p = 0;
@@ -4568,12 +4821,9 @@ get_next_display_element (it)
          else if ((it->c < ' '
                    && (it->area != TEXT_AREA
                        || (it->c != '\n' && it->c != '\t')))
-                  || (it->multibyte_p
-                      ? ((it->c >= 127
-                          && it->len == 1)
-                         || !CHAR_PRINTABLE_P (it->c))
-                      : (it->c >= 127
-                         && it->c == unibyte_char_to_multibyte (it->c))))
+                  || (it->c != '\n' && it->c != '\t'
+                      && (it->multibyte_p ? !CHAR_PRINTABLE_P (it->c)
+                          : it->c == 127)))
            {
              /* IT->c is a control character which must be displayed
                 either as '\003' or as `^C' where the '\\' and '^'
@@ -4619,24 +4869,28 @@ get_next_display_element (it)
                  else
                    escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
 
-                 if (SINGLE_BYTE_CHAR_P (it->c))
-                   str[0] = it->c, len = 1;
+                 if (CHAR_BYTE8_P (it->c))
+                   {
+                     str[0] = CHAR_TO_BYTE8 (it->c);
+                     len = 1;
+                   }
+                 else if (it->c < 256)
+                   {
+                     str[0] = it->c;
+                     len = 1;
+                   }
                  else
                    {
-                     len = CHAR_STRING_NO_SIGNAL (it->c, str);
-                     if (len < 0)
-                       {
-                         /* It's an invalid character, which
-                            shouldn't happen actually, but due to
-                            bugs it may happen.  Let's print the char
-                            as is, there's not much meaningful we can
-                            do with it.  */
-                         str[0] = it->c;
-                         str[1] = it->c >> 8;
-                         str[2] = it->c >> 16;
-                         str[3] = it->c >> 24;
-                         len = 4;
-                       }
+                     /* It's an invalid character, which
+                        shouldn't happen actually, but due to
+                        bugs it may happen.  Let's print the char
+                        as is, there's not much meaningful we can
+                        do with it.  */
+                     str[0] = it->c;
+                     str[1] = it->c >> 8;
+                     str[2] = it->c >> 16;
+                     str[3] = it->c >> 24;
+                     len = 4;
                    }
 
                  for (i = 0; i < len; i++)
@@ -4671,7 +4925,11 @@ get_next_display_element (it)
          && FRAME_WINDOW_P (it->f))
        {
          struct face *face = FACE_FROM_ID (it->f, it->face_id);
-         it->face_id = FACE_FOR_CHAR (it->f, face, it->c);
+         int pos = (it->s ? -1
+                    : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
+                    : IT_CHARPOS (*it));
+         
+         it->face_id = FACE_FOR_CHAR (it->f, face, it->c, pos, it->string);
        }
     }
 
@@ -5581,6 +5839,16 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
             the line.  */
          if (skip == MOVE_X_REACHED)
            {
+             /* Wait!  We can conclude that TO_Y is in the line if
+                the already scanned glyphs make the line tall enough
+                because further scanning doesn't make it shorter.  */
+             line_height = it->max_ascent + it->max_descent;
+             if (to_y >= it->current_y
+                 && to_y < it->current_y + line_height)
+               {
+                 reached = 6;
+                 break;
+               }
              it_backup = *it;
              TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it)));
              skip2 = move_it_in_display_line_to (it, to_charpos, -1,
@@ -5681,7 +5949,7 @@ move_it_vertically_backward (it, dy)
   xassert (dy >= 0);
 
   /* Estimate how many newlines we must move back.  */
-  nlines = max (1, dy / CANON_Y_UNIT (it->f));
+  nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f));
 
   /* Set the iterator's position that many lines back.  */
   while (nlines-- && IT_CHARPOS (*it) > BEGV)
@@ -5710,10 +5978,14 @@ move_it_vertically_backward (it, dy)
 
   move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
   xassert (IT_CHARPOS (*it) >= BEGV);
+  /* H is the actual vertical distance from the position in *IT
+     and the starting position.  */
   h = it2.current_y - it->current_y;
+  /* NLINES is the distance in number of lines.  */
   nlines = it2.vpos - it->vpos;
 
-  /* Correct IT's y and vpos position.  */
+  /* Correct IT's y and vpos position
+     so that they are relative to the starting point.  */
   it->vpos -= nlines;
   it->current_y -= h;
 
@@ -5725,10 +5997,10 @@ move_it_vertically_backward (it, dy)
        move_it_by_lines (it, nlines, 1);
       xassert (IT_CHARPOS (*it) <= start_pos);
     }
-  else if (nlines)
+  else
     {
-      /* The y-position we try to reach.  Note that h has been
-         subtracted in front of the if-statement.  */
+      /* The y-position we try to reach, relative to *IT.
+        Note that H has been subtracted in front of the if-statement.  */
       int target_y = it->current_y + h - dy;
       int y0 = it3.current_y;
       int y1 = line_bottom_y (&it3);
@@ -6047,7 +6319,7 @@ message_dolog (m, nbytes, nlflag, multibyte)
          for (i = 0; i < nbytes; i += char_bytes)
            {
              c = string_char_and_length (m + i, nbytes - i, &char_bytes);
-             work[0] = (SINGLE_BYTE_CHAR_P (c)
+             work[0] = (ASCII_CHAR_P (c)
                         ? c
                         : multibyte_char_to_unibyte (c, Qnil));
              insert_1_both (work, 1, 1, 1, 0, 0);
@@ -6143,9 +6415,9 @@ message_dolog (m, nbytes, nlflag, multibyte)
                          XMARKER (oldpoint)->bytepos);
 
       UNGCPRO;
-      unchain_marker (oldpoint);
-      unchain_marker (oldbegv);
-      unchain_marker (oldzv);
+      unchain_marker (XMARKER (oldpoint));
+      unchain_marker (XMARKER (oldbegv));
+      unchain_marker (XMARKER (oldzv));
 
       tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
       set_buffer_internal (oldbuf);
@@ -6988,9 +7260,9 @@ resize_mini_window (w, exact_p)
     {
       struct it it;
       struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
-      int total_height = XFASTINT (root->height) + XFASTINT (w->height);
+      int total_height = WINDOW_TOTAL_LINES (root) + WINDOW_TOTAL_LINES (w);
       int height, max_height;
-      int unit = CANON_Y_UNIT (f);
+      int unit = FRAME_LINE_HEIGHT (f);
       struct text_pos start;
       struct buffer *old_current_buffer = NULL;
 
@@ -7004,7 +7276,7 @@ resize_mini_window (w, exact_p)
 
       /* Compute the max. number of lines specified by the user.  */
       if (FLOATP (Vmax_mini_window_height))
-       max_height = XFLOATINT (Vmax_mini_window_height) * FRAME_HEIGHT (f);
+       max_height = XFLOATINT (Vmax_mini_window_height) * FRAME_LINES (f);
       else if (INTEGERP (Vmax_mini_window_height))
        max_height = XINT (Vmax_mini_window_height);
       else
@@ -7045,45 +7317,45 @@ resize_mini_window (w, exact_p)
        {
          /* Let it grow only, until we display an empty message, in which
             case the window shrinks again.  */
-         if (height > XFASTINT (w->height))
+         if (height > WINDOW_TOTAL_LINES (w))
            {
-             int old_height = XFASTINT (w->height);
+             int old_height = WINDOW_TOTAL_LINES (w);
              freeze_window_starts (f, 1);
-             grow_mini_window (w, height - XFASTINT (w->height));
-             window_height_changed_p = XFASTINT (w->height) != old_height;
+             grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
+             window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
            }
-         else if (height < XFASTINT (w->height)
+         else if (height < WINDOW_TOTAL_LINES (w)
                   && (exact_p || BEGV == ZV))
            {
-             int old_height = XFASTINT (w->height);
+             int old_height = WINDOW_TOTAL_LINES (w);
              freeze_window_starts (f, 0);
              shrink_mini_window (w);
-             window_height_changed_p = XFASTINT (w->height) != old_height;
+             window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
            }
        }
       else
        {
          /* Always resize to exact size needed.  */
-         if (height > XFASTINT (w->height))
+         if (height > WINDOW_TOTAL_LINES (w))
            {
-             int old_height = XFASTINT (w->height);
+             int old_height = WINDOW_TOTAL_LINES (w);
              freeze_window_starts (f, 1);
-             grow_mini_window (w, height - XFASTINT (w->height));
-             window_height_changed_p = XFASTINT (w->height) != old_height;
+             grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
+             window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
            }
-         else if (height < XFASTINT (w->height))
+         else if (height < WINDOW_TOTAL_LINES (w))
            {
-             int old_height = XFASTINT (w->height);
+             int old_height = WINDOW_TOTAL_LINES (w);
              freeze_window_starts (f, 0);
              shrink_mini_window (w);
 
              if (height)
                {
                  freeze_window_starts (f, 1);
-                 grow_mini_window (w, height - XFASTINT (w->height));
+                 grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
                }
 
-             window_height_changed_p = XFASTINT (w->height) != old_height;
+             window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
            }
        }
 
@@ -7317,7 +7589,7 @@ set_message_1 (a1, a2, nbytes, multibyte_p)
          for (i = 0; i < nbytes; i += n)
            {
              c = string_char_and_length (s + i, nbytes - i, &n);
-             work[0] = (SINGLE_BYTE_CHAR_P (c)
+             work[0] = (ASCII_CHAR_P (c)
                         ? c
                         : multibyte_char_to_unibyte (c, Qnil));
              insert_1_both (work, 1, 1, 1, 0, 0);
@@ -7887,6 +8159,8 @@ update_menu_bar (f, save_match_data)
                            Output Cursor
  ***********************************************************************/
 
+#ifdef HAVE_WINDOW_SYSTEM
+
 /* EXPORT:
    Nominal cursor position -- where to draw output.
    HPOS and VPOS are window relative glyph matrix coordinates.
@@ -7951,6 +8225,7 @@ x_cursor_to (vpos, hpos, y, x)
     }
 }
 
+#endif /* HAVE_WINDOW_SYSTEM */
 
 \f
 /***********************************************************************
@@ -7983,7 +8258,7 @@ update_tool_bar (f, save_match_data)
   int do_update = FRAME_EXTERNAL_TOOL_BAR(f);
 #else
   int do_update = WINDOWP (f->tool_bar_window)
-    && XFASTINT (XWINDOW (f->tool_bar_window)->height) > 0;
+    && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0;
 #endif
 
   if (do_update)
@@ -8003,6 +8278,7 @@ update_tool_bar (f, save_match_data)
         windows_or_buffers_changed anyway.  */
       if (windows_or_buffers_changed
          || !NILP (w->update_mode_line)
+         || update_mode_lines
          || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
               < BUF_MODIFF (XBUFFER (w->buffer)))
              != !NILP (w->last_had_star))
@@ -8012,6 +8288,8 @@ update_tool_bar (f, save_match_data)
        {
          struct buffer *prev = current_buffer;
          int count = SPECPDL_INDEX ();
+         Lisp_Object old_tool_bar;
+         struct gcpro gcpro1;
 
          /* Set current_buffer to the buffer of the selected
             window of the frame, so that we get the right local
@@ -8029,12 +8307,20 @@ update_tool_bar (f, save_match_data)
              specbind (Qoverriding_local_map, Qnil);
            }
 
+         old_tool_bar = f->tool_bar_items;
+         GCPRO1 (old_tool_bar);
+
          /* Build desired tool-bar items from keymaps.  */
+          BLOCK_INPUT;
          f->tool_bar_items
            = tool_bar_items (f->tool_bar_items, &f->n_tool_bar_items);
+          UNBLOCK_INPUT;
 
-         /* Redisplay the tool-bar in case we changed it.  */
-         w->update_mode_line = Qt;
+         /* Redisplay the tool-bar if we changed it.  */
+         if (! NILP (Fequal (old_tool_bar, f->tool_bar_items)))
+           w->update_mode_line = Qt;
+         
+         UNGCPRO;
 
          unbind_to (count, Qnil);
          set_buffer_internal_1 (prev);
@@ -8307,7 +8593,7 @@ tool_bar_lines_needed (f)
      F->desired_tool_bar_string in the tool-bar window of frame F.  */
   init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
   it.first_visible_x = 0;
-  it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
+  it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
   reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
 
   while (!ITERATOR_AT_END_P (&it))
@@ -8317,7 +8603,7 @@ tool_bar_lines_needed (f)
       display_tool_bar_line (&it);
     }
 
-  return (it.current_y + CANON_Y_UNIT (f) - 1) / CANON_Y_UNIT (f);
+  return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
 }
 
 
@@ -8339,7 +8625,7 @@ DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
 
   if (WINDOWP (f->tool_bar_window)
       || (w = XWINDOW (f->tool_bar_window),
-         XFASTINT (w->height) > 0))
+         WINDOW_TOTAL_LINES (w) > 0))
     {
       update_tool_bar (f, 1);
       if (f->n_tool_bar_items)
@@ -8377,13 +8663,13 @@ redisplay_tool_bar (f)
      can turn off tool-bars by specifying tool-bar-lines zero.  */
   if (!WINDOWP (f->tool_bar_window)
       || (w = XWINDOW (f->tool_bar_window),
-          XFASTINT (w->height) == 0))
+          WINDOW_TOTAL_LINES (w) == 0))
     return 0;
 
   /* Set up an iterator for the tool-bar window.  */
   init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
   it.first_visible_x = 0;
-  it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
+  it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
   row = it.glyph_row;
 
   /* Build a string that represents the contents of the tool-bar.  */
@@ -8410,10 +8696,10 @@ redisplay_tool_bar (f)
 
       /* If there are blank lines at the end, except for a partially
         visible blank line at the end that is smaller than
-        CANON_Y_UNIT, change the tool-bar's height.  */
+        FRAME_LINE_HEIGHT, change the tool-bar's height.  */
       row = it.glyph_row - 1;
       if (!row->displays_text_p
-         && row->height >= CANON_Y_UNIT (f))
+         && row->height >= FRAME_LINE_HEIGHT (f))
        change_height_p = 1;
 
       /* If row displays tool-bar items, but is partially visible,
@@ -8426,11 +8712,11 @@ redisplay_tool_bar (f)
         frame parameter.  */
       if (change_height_p
          && (nlines = tool_bar_lines_needed (f),
-             nlines != XFASTINT (w->height)))
+             nlines != WINDOW_TOTAL_LINES (w)))
        {
          extern Lisp_Object Qtool_bar_lines;
          Lisp_Object frame;
-         int old_height = XFASTINT (w->height);
+         int old_height = WINDOW_TOTAL_LINES (w);
 
          XSETFRAME (frame, f);
          clear_glyph_matrix (w->desired_matrix);
@@ -8438,7 +8724,7 @@ redisplay_tool_bar (f)
                                    Fcons (Fcons (Qtool_bar_lines,
                                                  make_number (nlines)),
                                           Qnil));
-         if (XFASTINT (w->height) != old_height)
+         if (WINDOW_TOTAL_LINES (w) != old_height)
            fonts_changed_p = 1;
        }
     }
@@ -8570,6 +8856,7 @@ handle_tool_bar_click (f, x, y, down_p, modifiers)
     {
       Lisp_Object key, frame;
       struct input_event event;
+      EVENT_INIT (event);
 
       /* Show item in released state.  */
       show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
@@ -8651,7 +8938,7 @@ note_tool_bar_highlight (f, x, y)
   if (!NILP (enabled_p))
     {
       /* Compute the x-position of the glyph.  In front and past the
-        image is a space.  We include this is the highlighted area.  */
+        image is a space.  We include this in the highlighted area.  */
       row = MATRIX_ROW (w->current_matrix, vpos);
       for (i = x = 0; i < hpos; ++i)
        x += row->glyphs[TEXT_AREA][i].pixel_width;
@@ -8778,41 +9065,46 @@ draw_fringe_bitmap (w, row, which, left_p)
   p.bx = -1;
   if (left_p)
     {
-      if (p.wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
-       p.wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
-      p.x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
-            - p.wd
-            - (FRAME_X_LEFT_FRINGE_WIDTH (f) - p.wd) / 2);
-      if (p.wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > p.h)
+      int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
+      int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                                  ? LEFT_MARGIN_AREA
+                                  : TEXT_AREA));
+      if (p.wd > wd)
+       p.wd = wd;
+      p.x = x - p.wd - (wd - p.wd) / 2;
+
+      if (p.wd < wd || row->height > p.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);
-         p.bx = (window_box_left (w, -1)
-                 - FRAME_X_LEFT_FRINGE_WIDTH (f)
-                 + border);
-         p.nx = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
+         wd -= ((!WINDOW_LEFTMOST_P (w)
+                 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
+                ? 1 : 0);
+         p.bx = x - wd;
+         p.nx = wd;
        }
     }
   else
     {
-      if (p.wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
-       p.wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
-      p.x = (window_box_right (w, -1)
-            + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - p.wd) / 2);
+      int x = window_box_right (w,
+                               (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                                ? RIGHT_MARGIN_AREA
+                                : TEXT_AREA));
+      int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
+      if (p.wd > wd)
+       p.wd = wd;
+      p.x = x + (wd - p.wd) / 2;
       /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
         the fringe.  */
-      if (p.wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > p.h)
+      if (p.wd < wd || row->height > p.h)
        {
-         p.bx = window_box_right (w, -1);
-         p.nx = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+         p.bx = x;
+         p.nx = wd;
        }
     }
 
   if (p.bx >= 0)
     {
-      int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+      int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
 
       p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
       p.ny = row->visible_height;
@@ -8832,7 +9124,6 @@ draw_row_fringe_bitmaps (w, row)
      struct window *w;
      struct glyph_row *row;
 {
-  struct frame *f = XFRAME (w->frame);
   enum fringe_bitmap_type bitmap;
 
   xassert (interrupt_input_blocked);
@@ -8842,7 +9133,7 @@ draw_row_fringe_bitmaps (w, row)
   if (row->visible_height <= 0)
     return;
 
-  if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
+  if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
     {
       /* Decide which bitmap to draw in the left fringe.  */
       if (row->overlay_arrow_p)
@@ -8859,14 +9150,14 @@ draw_row_fringe_bitmaps (w, row)
       draw_fringe_bitmap (w, row, bitmap, 1);
     }
 
-  if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
+  if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
     {
       /* 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)
+      else if (row->indicate_empty_line_p && WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
        bitmap = ZV_LINE_BITMAP;
       else
        bitmap = NO_FRINGE_BITMAP;
@@ -8883,9 +9174,9 @@ compute_fringe_widths (f, redraw)
      struct frame *f;
      int redraw;
 {
-  int o_left = FRAME_X_LEFT_FRINGE_WIDTH (f);
-  int o_right = FRAME_X_RIGHT_FRINGE_WIDTH (f);
-  int o_cols = FRAME_X_FRINGE_COLS (f);
+  int o_left = FRAME_LEFT_FRINGE_WIDTH (f);
+  int o_right = FRAME_RIGHT_FRINGE_WIDTH (f);
+  int o_cols = FRAME_FRINGE_COLS (f);
 
   Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
   Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
@@ -8906,7 +9197,7 @@ compute_fringe_widths (f, redraw)
       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 (FRAME_FONT (f));
+      int font_wid = FRAME_COLUMN_WIDTH (f);
       int cols = (left_wid + right_wid + font_wid-1) / font_wid;
       int real_wid = cols * font_wid;
       if (left_wid && right_wid)
@@ -8914,14 +9205,14 @@ compute_fringe_widths (f, redraw)
          if (left_fringe_width < 0)
            {
              /* Left fringe width is fixed, adjust right fringe if necessary */
-             FRAME_X_LEFT_FRINGE_WIDTH (f) = left_wid;
-             FRAME_X_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
+             FRAME_LEFT_FRINGE_WIDTH (f) = left_wid;
+             FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
            }
          else if (right_fringe_width < 0)
            {
              /* Right fringe width is fixed, adjust left fringe if necessary */
-             FRAME_X_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
-             FRAME_X_RIGHT_FRINGE_WIDTH (f) = right_wid;
+             FRAME_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
+             FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid;
            }
          else
            {
@@ -8929,35 +9220,33 @@ compute_fringe_widths (f, redraw)
                 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;
-             FRAME_X_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
-             FRAME_X_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
+             FRAME_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
+             FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
            }
        }
       else if (left_fringe_width)
        {
-         FRAME_X_LEFT_FRINGE_WIDTH (f) = real_wid;
-         FRAME_X_RIGHT_FRINGE_WIDTH (f) = 0;
+         FRAME_LEFT_FRINGE_WIDTH (f) = real_wid;
+         FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
        }
       else
        {
-         FRAME_X_LEFT_FRINGE_WIDTH (f) = 0;
-         FRAME_X_RIGHT_FRINGE_WIDTH (f) = real_wid;
+         FRAME_LEFT_FRINGE_WIDTH (f) = 0;
+         FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
        }
-      FRAME_X_FRINGE_COLS (f) = cols;
-      FRAME_X_FRINGE_WIDTH (f) = real_wid;
+      FRAME_FRINGE_COLS (f) = cols;
     }
   else
     {
-      FRAME_X_LEFT_FRINGE_WIDTH (f) = 0;
-      FRAME_X_RIGHT_FRINGE_WIDTH (f) = 0;
-      FRAME_X_FRINGE_COLS (f) = 0;
-      FRAME_X_FRINGE_WIDTH (f) = 0;
+      FRAME_LEFT_FRINGE_WIDTH (f) = 0;
+      FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
+      FRAME_FRINGE_COLS (f) = 0;
     }
 
   if (redraw && FRAME_VISIBLE_P (f))
-    if (o_left != FRAME_X_LEFT_FRINGE_WIDTH (f) ||
-       o_right != FRAME_X_RIGHT_FRINGE_WIDTH (f) ||
-       o_cols != FRAME_X_FRINGE_COLS (f))
+    if (o_left != FRAME_LEFT_FRINGE_WIDTH (f) ||
+       o_right != FRAME_RIGHT_FRINGE_WIDTH (f) ||
+       o_cols != FRAME_FRINGE_COLS (f))
       redraw_frame (f);
 }
 
@@ -9015,8 +9304,8 @@ hscroll_window_tree (window)
        hscrolled_p |= hscroll_window_tree (w->vchild);
       else if (w->cursor.vpos >= 0)
        {
-         int h_margin, text_area_x, text_area_y;
-         int text_area_width, text_area_height;
+         int h_margin;
+         int text_area_width;
          struct glyph_row *current_cursor_row
            = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
          struct glyph_row *desired_cursor_row
@@ -9026,11 +9315,10 @@ hscroll_window_tree (window)
               ? desired_cursor_row
               : current_cursor_row);
 
-         window_box (w, TEXT_AREA, &text_area_x, &text_area_y,
-                     &text_area_width, &text_area_height);
+         text_area_width = window_box_width (w, TEXT_AREA);
 
          /* Scroll when cursor is inside this scroll margin.  */
-         h_margin = hscroll_margin * CANON_X_UNIT (XFRAME (w->frame));
+         h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
 
          if ((XFASTINT (w->hscroll)
               && w->cursor.x <= h_margin)
@@ -9067,7 +9355,7 @@ hscroll_window_tree (window)
              /* Position cursor in window.  */
              if (!hscroll_relative_p && hscroll_step_abs == 0)
                hscroll = max (0, it.current_x - text_area_width / 2)
-                         / CANON_X_UNIT (it.f);
+                         / FRAME_COLUMN_WIDTH (it.f);
              else if (w->cursor.x >= text_area_width - h_margin)
                {
                  if (hscroll_relative_p)
@@ -9075,10 +9363,10 @@ hscroll_window_tree (window)
                               - h_margin;
                  else
                    wanted_x = text_area_width
-                              - hscroll_step_abs * CANON_X_UNIT (it.f)
+                              - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
                               - h_margin;
                  hscroll
-                   = max (0, it.current_x - wanted_x) / CANON_X_UNIT (it.f);
+                   = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
                }
              else
                {
@@ -9086,10 +9374,10 @@ hscroll_window_tree (window)
                    wanted_x = text_area_width * hscroll_step_rel
                               + h_margin;
                  else
-                   wanted_x = hscroll_step_abs * CANON_X_UNIT (it.f)
+                   wanted_x = hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
                               + h_margin;
                  hscroll
-                   = max (0, it.current_x - wanted_x) / CANON_X_UNIT (it.f);
+                   = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
                }
              hscroll = max (hscroll, XFASTINT (w->min_hscroll));
 
@@ -9284,7 +9572,7 @@ check_point_in_composition (prev_buf, prev_pt, buf, pt)
      struct buffer *prev_buf, *buf;
      int prev_pt, pt;
 {
-  int start, end;
+  EMACS_INT start, end;
   Lisp_Object prop;
   Lisp_Object buffer;
 
@@ -9738,7 +10026,7 @@ redisplay_internal (preserve_echo_area)
               /* Make sure the cursor was last displayed
                  in this window.  Otherwise we have to reposition it.  */
               && 0 <= w->cursor.vpos
-              && XINT (w->height) > w->cursor.vpos)
+              && WINDOW_TOTAL_LINES (w) > w->cursor.vpos)
        {
          if (!must_finish)
            {
@@ -9874,8 +10162,10 @@ redisplay_internal (preserve_echo_area)
                  /* Update the display.  */
                  set_window_update_flags (XWINDOW (f->root_window), 1);
                  pause |= update_frame (f, 0, 0);
+#if 0  /* Exiting the loop can leave the wrong value for buffer_shared.  */
                  if (pause)
                    break;
+#endif
 
                  if (n == size)
                    {
@@ -10140,7 +10430,7 @@ mark_window_display_accurate_1 (w, accurate_p)
       w->window_end_valid = w->buffer;
 #if 0 /* This is incorrect with variable-height lines.  */
       xassert (XINT (w->window_end_vpos)
-              < (XINT (w->height)
+              < (WINDOW_TOTAL_LINES (w)
                  - (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0)));
 #endif
       w->update_mode_line = Qnil;
@@ -10197,35 +10487,24 @@ disp_char_vector (dp, c)
      struct Lisp_Char_Table *dp;
      int c;
 {
-  int code[4], i;
   Lisp_Object val;
 
-  if (SINGLE_BYTE_CHAR_P (c))
-    return (dp->contents[c]);
-
-  SPLIT_CHAR (c, code[0], code[1], code[2]);
-  if (code[1] < 32)
-    code[1] = -1;
-  else if (code[2] < 32)
-    code[2] = -1;
-
-  /* Here, the possible range of code[0] (== charset ID) is
-     128..max_charset.  Since the top level char table contains data
-     for multibyte characters after 256th element, we must increment
-     code[0] by 128 to get a correct index.  */
-  code[0] += 128;
-  code[3] = -1;                /* anchor */
-
-  for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
+  if (ASCII_CHAR_P (c))
     {
-      val = dp->contents[code[i]];
-      if (!SUB_CHAR_TABLE_P (val))
-       return (NILP (val) ? dp->defalt : val);
+      val = dp->ascii;
+      if (SUB_CHAR_TABLE_P (val))
+       val = XSUB_CHAR_TABLE (val)->contents[c];
     }
+  else
+    {
+      Lisp_Object table;
 
-  /* Here, val is a sub char table.  We return the default value of
-     it.  */
-  return (dp->defalt);
+      XSETCHAR_TABLE (table, dp);
+      val = char_table_ref (table, c);
+    }
+  if (NILP (val))
+    val = dp->defalt;
+  return val;
 }
 
 
@@ -10603,8 +10882,8 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
      within this distance from the top or bottom of the window.  */
   if (scroll_margin > 0)
     {
-      this_scroll_margin = min (scroll_margin, XINT (w->height) / 4);
-      this_scroll_margin *= CANON_Y_UNIT (f);
+      this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+      this_scroll_margin *= FRAME_LINE_HEIGHT (f);
     }
   else
     this_scroll_margin = 0;
@@ -10622,7 +10901,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
     scroll_max = 10;
   else
     scroll_max = 0;
-  scroll_max *= CANON_Y_UNIT (f);
+  scroll_max *= FRAME_LINE_HEIGHT (f);
 
   /* Decide whether we have to scroll down.  Start at the window end
      and move this_scroll_margin up to find the position of the scroll
@@ -10673,15 +10952,14 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
        /* Set AMOUNT_TO_SCROLL to at least one line,
           and at most scroll_conservatively lines.  */
        amount_to_scroll
-         = min (max (dy, CANON_Y_UNIT (f)),
-                CANON_Y_UNIT (f) * scroll_conservatively);
+         = min (max (dy, FRAME_LINE_HEIGHT (f)),
+                FRAME_LINE_HEIGHT (f) * scroll_conservatively);
       else if (scroll_step || temp_scroll_step)
        amount_to_scroll = scroll_max;
       else
        {
          aggressive = current_buffer->scroll_up_aggressively;
-         height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
-                   - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
+         height = WINDOW_BOX_TEXT_HEIGHT (w);
          if (NUMBERP (aggressive))
            amount_to_scroll = XFLOATINT (aggressive) * height;
        }
@@ -10733,14 +11011,13 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 
          if (scroll_conservatively)
            amount_to_scroll =
-             max (dy, CANON_Y_UNIT (f) * max (scroll_step, temp_scroll_step));
+             max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
          else if (scroll_step || temp_scroll_step)
            amount_to_scroll = scroll_max;
          else
            {
              aggressive = current_buffer->scroll_down_aggressively;
-             height = (WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (w)
-                       - WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
+             height = WINDOW_BOX_TEXT_HEIGHT (w);
              if (NUMBERP (aggressive))
                amount_to_scroll = XFLOATINT (aggressive) * height;
            }
@@ -10830,7 +11107,7 @@ compute_window_start_on_continuation_line (w)
       /* If the line start is "too far" away from the window start,
          say it takes too much time to compute a new window start.  */
       if (CHARPOS (start_pos) - IT_CHARPOS (it)
-         < XFASTINT (w->height) * XFASTINT (w->width))
+         < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w))
        {
          int min_distance, distance;
 
@@ -10948,8 +11225,8 @@ try_cursor_movement (window, startp, scroll_step)
       /* Scroll if point within this distance from the top or bottom
         of the window.  This is a pixel value.  */
       this_scroll_margin = max (0, scroll_margin);
-      this_scroll_margin = min (this_scroll_margin, XFASTINT (w->height) / 4);
-      this_scroll_margin *= CANON_Y_UNIT (f);
+      this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+      this_scroll_margin *= FRAME_LINE_HEIGHT (f);
 
       /* Start with the row the cursor was displayed during the last
         not paused redisplay.  Give up if that row is not valid.  */
@@ -11087,6 +11364,41 @@ try_cursor_movement (window, startp, scroll_step)
   return rc;
 }
 
+void
+set_vertical_scroll_bar (w)
+     struct window *w;
+{
+  int start, end, whole;
+
+  /* Calculate the start and end positions for the current window.
+     At some point, it would be nice to choose between scrollbars
+     which reflect the whole buffer size, with special markers
+     indicating narrowing, and scrollbars which reflect only the
+     visible region.
+     
+     Note that mini-buffers sometimes aren't displaying any text.  */
+  if (!MINI_WINDOW_P (w)
+      || (w == XWINDOW (minibuf_window)
+         && NILP (echo_area_buffer[0])))
+    {
+      struct buffer *buf = XBUFFER (w->buffer);
+      whole = BUF_ZV (buf) - BUF_BEGV (buf);
+      start = marker_position (w->start) - BUF_BEGV (buf);
+      /* I don't think this is guaranteed to be right.  For the
+        moment, we'll pretend it is.  */
+      end = BUF_Z (buf) - XFASTINT (w->window_end_pos) - BUF_BEGV (buf);
+      
+      if (end < start)
+       end = start;
+      if (whole < (end - start))
+       whole = end - start;
+    }
+  else
+    start = end = whole = 0;
+
+  /* Indicate what this scroll bar ought to be displaying now.  */
+  set_vertical_scroll_bar_hook (w, end - start, whole, start);
+}
 
 /* Redisplay leaf window WINDOW.  JUST_THIS_ONE_P non-zero means only
    selected_window is redisplayed.
@@ -11153,6 +11465,8 @@ redisplay_window (window, just_this_one_p)
        }
       else if ((w != XWINDOW (minibuf_window)
                || minibuf_level == 0)
+              /* When buffer is nonempty, redisplay window normally. */
+              && BUF_Z (XBUFFER (w->buffer)) == BUF_BEG (XBUFFER (w->buffer))
               /* Quail displays non-mini buffers in minibuffer window.
                  In that case, redisplay the window normally.  */
               && !NILP (Fmemq (w->buffer, Vminibuffer_list)))
@@ -11772,37 +12086,10 @@ redisplay_window (window, just_this_one_p)
   ;
  finish_scroll_bars:
 
-  if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+  if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
     {
-      int start, end, whole;
-
-      /* Calculate the start and end positions for the current window.
-        At some point, it would be nice to choose between scrollbars
-        which reflect the whole buffer size, with special markers
-        indicating narrowing, and scrollbars which reflect only the
-        visible region.
-
-        Note that mini-buffers sometimes aren't displaying any text.  */
-      if (!MINI_WINDOW_P (w)
-         || (w == XWINDOW (minibuf_window)
-             && NILP (echo_area_buffer[0])))
-       {
-         whole = ZV - BEGV;
-         start = marker_position (w->start) - BEGV;
-         /* I don't think this is guaranteed to be right.  For the
-            moment, we'll pretend it is.  */
-         end = (Z - XFASTINT (w->window_end_pos)) - BEGV;
-
-         if (end < start)
-           end = start;
-         if (whole < (end - start))
-           whole = end - start;
-       }
-      else
-       start = end = whole = 0;
-
-      /* Indicate what this scroll bar ought to be displaying now.  */
-      set_vertical_scroll_bar_hook (w, end - start, whole, start);
+      /* Set the thumb's position and size.  */
+      set_vertical_scroll_bar (w);
 
       /* Note that we actually used the scroll bar attached to this
         window, so it shouldn't be deleted at the end of redisplay.  */
@@ -11873,8 +12160,9 @@ try_window (window, pos)
     }
   else
     {
-      w->window_end_bytepos = 0;
-      w->window_end_pos = w->window_end_vpos = make_number (0);
+      w->window_end_bytepos = Z_BYTE - ZV_BYTE;
+      w->window_end_pos = make_number (Z - ZV);
+      w->window_end_vpos = make_number (0);
     }
 
   /* But that is not valid info until redisplay finishes.  */
@@ -12033,7 +12321,7 @@ try_window_reusing_current_matrix (w)
            (start_row + i)->enabled_p = 0;
 
          /* Re-compute Y positions.  */
-         min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+         min_y = WINDOW_HEADER_LINE_HEIGHT (w);
          max_y = it.last_visible_y;
          for (row = start_row + nrows_scrolled;
               row < bottom_row;
@@ -12087,8 +12375,9 @@ try_window_reusing_current_matrix (w)
       else
        {
          /* This window must be completely empty.  */
-         w->window_end_bytepos = 0;
-         w->window_end_pos = w->window_end_vpos = make_number (0);
+         w->window_end_bytepos = Z_BYTE - ZV_BYTE;
+         w->window_end_pos = make_number (Z - ZV);
+         w->window_end_vpos = make_number (0);
        }
       w->window_end_valid = Qnil;
 
@@ -12147,7 +12436,7 @@ try_window_reusing_current_matrix (w)
       it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
                 - nrows_scrolled);
       it.current_y = (first_row_to_display->y - first_reusable_row->y
-                     + WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w));
+                     + WINDOW_HEADER_LINE_HEIGHT (w));
 
       /* Display lines beginning with first_row_to_display in the
          desired matrix.  Set last_text_row to the last row displayed
@@ -12178,7 +12467,7 @@ try_window_reusing_current_matrix (w)
 
       /* Scroll the display.  */
       run.current_y = first_reusable_row->y;
-      run.desired_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+      run.desired_y = WINDOW_HEADER_LINE_HEIGHT (w);
       run.height = it.last_visible_y - run.current_y;
       dy = run.current_y - run.desired_y;
 
@@ -12195,7 +12484,7 @@ try_window_reusing_current_matrix (w)
 
       /* Adjust Y positions of reused rows.  */
       bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
-      min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+      min_y = WINDOW_HEADER_LINE_HEIGHT (w);
       max_y = it.last_visible_y;
       for (row = first_reusable_row; row < first_row_to_display; ++row)
        {
@@ -12447,7 +12736,7 @@ sync_frame_with_window_matrix_rows (w)
      marginal areas (see build_frame_matrix).  */
   window_row = w->current_matrix->rows;
   window_row_end = window_row + w->current_matrix->nrows;
-  frame_row = f->current_matrix->rows + XFASTINT (w->top);
+  frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
   while (window_row < window_row_end)
     {
       struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
@@ -12703,7 +12992,10 @@ try_window_id (w)
         the window end again, since its offset from Z hasn't changed.  */
       r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
       if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + delta
-         && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + delta_bytes)
+         && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + delta_bytes
+         /* PT must not be in a partially visible line.  */
+         && !(PT >= MATRIX_ROW_START_CHARPOS (row) + delta
+              && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
        {
          /* Adjust positions in the glyph matrix.  */
          if (delta || delta_bytes)
@@ -12748,7 +13040,10 @@ try_window_id (w)
         as is, without changing glyph positions since no text has
         been added/removed in front of the window end.  */
       r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
-      if (TEXT_POS_EQUAL_P (start, r0->start.pos))
+      if (TEXT_POS_EQUAL_P (start, r0->start.pos)
+         /* PT must not be in a partially visible line.  */
+         && !(PT >= MATRIX_ROW_START_CHARPOS (row)
+              && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
        {
          /* We have to compute the window end anew since text
             can have been added/removed after it.  */
@@ -12988,9 +13283,8 @@ try_window_id (w)
     int this_scroll_margin, cursor_height;
 
     this_scroll_margin = max (0, scroll_margin);
-    this_scroll_margin = min (this_scroll_margin,
-                             XFASTINT (w->height) / 4);
-    this_scroll_margin *= CANON_Y_UNIT (it.f);
+    this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
+    this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
     cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
 
     if ((w->cursor.y < this_scroll_margin
@@ -13025,8 +13319,8 @@ try_window_id (w)
             lines to scroll by; dvpos < 0 means scroll up.  */
          int first_unchanged_at_end_vpos
            = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
-         int from = XFASTINT (w->top) + first_unchanged_at_end_vpos;
-         int end = (XFASTINT (w->top)
+         int from = WINDOW_TOP_EDGE_LINE (w) + first_unchanged_at_end_vpos;
+         int end = (WINDOW_TOP_EDGE_LINE (w)
                     + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0)
                     + window_internal_height (w));
 
@@ -13716,7 +14010,7 @@ compute_line_metrics (it)
       if (row->height == 0)
        {
          if (it->max_ascent + it->max_descent == 0)
-           it->max_descent = it->max_phys_descent = CANON_Y_UNIT (it->f);
+           it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
          row->ascent = it->max_ascent;
          row->height = it->max_ascent + it->max_descent;
          row->phys_ascent = it->max_phys_ascent;
@@ -13747,8 +14041,8 @@ compute_line_metrics (it)
       /* Compute how much of the line is visible.  */
       row->visible_height = row->height;
 
-      min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (it->w);
-      max_y = WINDOW_DISPLAY_HEIGHT_NO_MODE_LINE (it->w);
+      min_y = WINDOW_HEADER_LINE_HEIGHT (it->w);
+      max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
 
       if (row->y < min_y)
        row->visible_height -= min_y - row->y;
@@ -13832,7 +14126,7 @@ append_space (it, default_face_p)
          else if (it->face_before_selective_p)
            it->face_id = it->saved_face_id;
          face = FACE_FROM_ID (it->f, it->face_id);
-         it->face_id = FACE_FOR_CHAR (it->f, face, 0);
+         it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
 
          PRODUCE_GLYPHS (it);
 
@@ -13889,9 +14183,9 @@ extend_face_to_end_of_line (it)
          ASCII face.  This will be automatically undone the next time
          get_next_display_element returns a multibyte character.  Note
          that the character will always be single byte in unibyte text.  */
-  if (!SINGLE_BYTE_CHAR_P (it->c))
+  if (!ASCII_CHAR_P (it->c))
     {
-      it->face_id = FACE_FOR_CHAR (f, face, 0);
+      it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
     }
 
   if (FRAME_WINDOW_P (f))
@@ -13997,7 +14291,7 @@ highlight_trailing_whitespace (f, row)
                  && glyph->u.ch == ' '))
          && trailing_whitespace_p (glyph->charpos))
        {
-         int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
+         int face_id = lookup_named_face (f, Qtrailing_whitespace);
 
          while (glyph >= start
                 && BUFFERP (glyph->object)
@@ -14504,7 +14798,7 @@ display_menu_bar (w)
   xassert (!FRAME_WINDOW_P (f));
   init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
   it.first_visible_x = 0;
-  it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
+  it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
 #else /* not USE_X_TOOLKIT */
   if (FRAME_WINDOW_P (f))
     {
@@ -14516,7 +14810,7 @@ display_menu_bar (w)
       init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
                     MENU_FACE_ID);
       it.first_visible_x = 0;
-      it.last_visible_x = FRAME_WINDOW_WIDTH (f) * CANON_X_UNIT (f);
+      it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
     }
   else
     {
@@ -14525,7 +14819,7 @@ display_menu_bar (w)
       init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
                     MENU_FACE_ID);
       it.first_visible_x = 0;
-      it.last_visible_x = FRAME_WIDTH (f);
+      it.last_visible_x = FRAME_COLS (f);
     }
 #endif /* not USE_X_TOOLKIT */
 
@@ -14782,8 +15076,8 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
   int literal = 0;
 
  tail_recurse:
-  if (depth > 10)
-    goto invalid;
+  if (depth > 100)
+    elt = build_string ("*too-deep*");
 
   depth++;
 
@@ -15138,14 +15432,8 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
 
     default:
     invalid:
-      if (frame_title_ptr)
-       n += store_frame_title ("*invalid*", 0, precision - n);
-      else if (!NILP (mode_line_string_list))
-       n += store_mode_line_string ("*invalid*", Qnil, 0, 0, precision - n, Qnil);
-      else
-       n += display_string ("*invalid*", Qnil, Qnil, 0, 0, it, 0,
-                            precision - n, 0, 0);
-      return n;
+      elt = build_string ("*invalid*");
+      goto tail_recurse;
     }
 
   /* Pad to FIELD_WIDTH.  */
@@ -15414,7 +15702,7 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
   /* The EOL conversion we are using.  */
   Lisp_Object eoltype;
 
-  val = Fget (coding_system, Qcoding_system);
+  val = CODING_SYSTEM_SPEC (coding_system);
   eoltype = Qnil;
 
   if (!VECTORP (val))          /* Not yet decided.  */
@@ -15427,12 +15715,14 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
     }
   else
     {
+      Lisp_Object attrs;
       Lisp_Object eolvalue;
 
-      eolvalue = Fget (coding_system, Qeol_type);
+      attrs = AREF (val, 0);
+      eolvalue = AREF (val, 2);
 
       if (multibyte)
-       *buf++ = XFASTINT (AREF (val, 1));
+       *buf++ = XFASTINT (CODING_ATTR_MNEMONIC (attrs));
 
       if (eol_flag)
        {
@@ -15442,10 +15732,10 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
            eoltype = eol_mnemonic_undecided;
          else if (VECTORP (eolvalue)) /* Not yet decided.  */
            eoltype = eol_mnemonic_undecided;
-         else                  /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
-           eoltype = (XFASTINT (eolvalue) == 0
+         else                  /* eolvalue is Qunix, Qdos, or Qmac.  */
+           eoltype = (EQ (eolvalue, Qunix)
                       ? eol_mnemonic_unix
-                      : (XFASTINT (eolvalue) == 1
+                      : (EQ (eolvalue, Qdos) == 1
                          ? eol_mnemonic_dos : eol_mnemonic_mac));
        }
     }
@@ -15458,8 +15748,7 @@ decode_mode_spec_coding (coding_system, buf, eol_flag)
          eol_str = SDATA (eoltype);
          eol_str_len = SBYTES (eoltype);
        }
-      else if (INTEGERP (eoltype)
-              && CHAR_VALID_P (XINT (eoltype), 0))
+      else if (CHARACTERP (eoltype))
        {
          unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
          eol_str_len = CHAR_STRING (XINT (eoltype), tmp);
@@ -15603,7 +15892,7 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
        int startpos_byte = marker_byte_position (w->start);
        int line, linepos, linepos_byte, topline;
        int nlines, junk;
-       int height = XFASTINT (w->height);
+       int height = WINDOW_TOTAL_LINES (w);
 
        /* If we decided that this buffer isn't suitable for line numbers,
           don't forget that too fast.  */
@@ -15810,8 +16099,10 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
          {
            /* No need to mention EOL here--the terminal never needs
               to do EOL conversion.  */
-           p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
-           p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
+           p = decode_mode_spec_coding (CODING_ID_NAME (keyboard_coding.id),
+                                        p, 0);
+           p = decode_mode_spec_coding (CODING_ID_NAME (terminal_coding.id),
+                                        p, 0);
          }
        p = decode_mode_spec_coding (b->buffer_file_coding_system,
                                     p, eol_flag);
@@ -16082,7 +16373,7 @@ display_string (string, lisp_string, face_string, face_string_pos,
                }
              break;
            }
-         else if (x + glyph->pixel_width > it->first_visible_x)
+         else if (x + glyph->pixel_width >= it->first_visible_x)
            {
              /* Glyph is at least partially visible.  */
              ++it->hpos;
@@ -16385,24 +16676,25 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
     }
   else
     {
-      int c1, c2, charset;
+      struct font_info *font_info
+       = FONT_INFO_FROM_ID (f, face->font_info_id);
+      if (font_info)
+       {
+         struct charset *charset = CHARSET_FROM_ID (font_info->charset);
+         unsigned code = ENCODE_CHAR (charset, glyph->u.ch);
 
-      /* Split characters into bytes.  If c2 is -1 afterwards, C is
-        really a one-byte character so that byte1 is zero.  */
-      SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
-      if (c2 > 0)
-       STORE_XCHAR2B (char2b, c1, c2);
-      else
-       STORE_XCHAR2B (char2b, 0, c1);
+         if (CHARSET_DIMENSION (charset) == 1)
+           STORE_XCHAR2B (char2b, 0, code);
+         else
+           STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
 
-      /* Maybe encode the character in *CHAR2B.  */
-      if (charset != CHARSET_ASCII)
-       {
-         struct font_info *font_info
-           = FONT_INFO_FROM_ID (f, face->font_info_id);
-         if (font_info)
-           glyph->font_type
-             = rif->encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
+         /* Maybe encode the character in *CHAR2B.  */
+         if (CHARSET_ID (charset) != charset_ascii)
+           {
+             glyph->font_type
+               = rif->encode_char (glyph->u.ch, char2b, font_info, charset,
+                                   two_byte_p);
+           }
        }
     }
 
@@ -16640,6 +16932,13 @@ x_get_glyph_overhangs (glyph, f, left, right)
            *left = -pcm->lbearing;
        }
     }
+  else if (glyph->type == COMPOSITE_GLYPH)
+    {
+      struct composition *cmp = composition_table[glyph->u.cmp_id];
+
+      *right = cmp->rbearing - cmp->pixel_width;
+      *left = - cmp->lbearing;
+    }
 }
 
 
@@ -16774,7 +17073,7 @@ get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
       /* Unibyte case.  We don't have to encode, but we have to make
         sure to use a face suitable for unibyte.  */
       STORE_XCHAR2B (char2b, 0, c);
-      face_id = FACE_FOR_CHAR (f, face, c);
+      face_id = FACE_FOR_CHAR (f, face, c, -1, Qnil);
       face = FACE_FROM_ID (f, face_id);
     }
   else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
@@ -16782,26 +17081,19 @@ get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
       /* Case of ASCII in a face known to fit ASCII.  */
       STORE_XCHAR2B (char2b, 0, c);
     }
-  else
+  else if (face->font != NULL)
     {
-      int c1, c2, charset;
+      struct font_info *font_info
+       = FONT_INFO_FROM_ID (f, face->font_info_id);
+      struct charset *charset = CHARSET_FROM_ID (font_info->charset);
+      unsigned code = ENCODE_CHAR (charset, c);
 
-      /* Split characters into bytes.  If c2 is -1 afterwards, C is
-        really a one-byte character so that byte1 is zero.  */
-      SPLIT_CHAR (c, charset, c1, c2);
-      if (c2 > 0)
-       STORE_XCHAR2B (char2b, c1, c2);
+      if (CHARSET_DIMENSION (charset) == 1)
+       STORE_XCHAR2B (char2b, 0, code);
       else
-       STORE_XCHAR2B (char2b, 0, c1);
-
-      /* Maybe encode the character in *CHAR2B.  */
-      if (face->font != NULL)
-       {
-         struct font_info *font_info
-           = FONT_INFO_FROM_ID (f, face->font_info_id);
-         if (font_info)
-           rif->encode_char (c, char2b, font_info, 0);
-       }
+       STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
+       /* Maybe encode the character in *CHAR2B.  */
+      rif->encode_char (c, char2b, font_info, charset, NULL);
     }
 
   /* Make sure X resources of the face are allocated.  */
@@ -16960,10 +17252,9 @@ compute_overhangs_and_x (s, x, backward_p)
 #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X)           \
      do                                                                           \
        {                                                                  \
-        int c, face_id;                                                   \
+        int face_id;                                                      \
         XChar2b *char2b;                                                  \
                                                                           \
-        c = (row)->glyphs[area][START].u.ch;                              \
         face_id = (row)->glyphs[area][START].face_id;                     \
                                                                           \
         s = (struct glyph_string *) alloca (sizeof *s);                   \
@@ -17004,7 +17295,7 @@ compute_overhangs_and_x (s, x, backward_p)
     for (n = 0; n < glyph_len; n++)                                      \
       {                                                                          \
        int c = COMPOSITION_GLYPH (cmp, n);                               \
-       int this_face_id = FACE_FOR_CHAR (f, base_face, c);               \
+       int this_face_id = FACE_FOR_CHAR (f, base_face, c, -1, Qnil);     \
        faces[n] = FACE_FROM_ID (f, this_face_id);                        \
        get_char_face_and_encoding (f, c, this_face_id,                   \
                                    char2b + n, 1, 1);                    \
@@ -17104,7 +17395,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
      int x;
      struct glyph_row *row;
      enum glyph_row_area area;
-     int start, end;
+     EMACS_INT start, end;
      enum draw_glyphs_face hl;
      int overlaps_p;
 {
@@ -17129,30 +17420,15 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
     {
       /* X is relative to the left edge of W, without scroll bars
         or fringes.  */
-      int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
-
-      x += window_left_x;
-      area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
-      last_x = window_left_x + area_width;
-
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
-       {
-         int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
-         if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
-           last_x += width;
-         else
-           x -= width;
-       }
-
-      x += FRAME_INTERNAL_BORDER_WIDTH (f);
-      /* ++KFS: W32 and MAC versions had -= in next line (bug??)  */
-      last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
+      x += WINDOW_LEFT_EDGE_X (w);
+      last_x = WINDOW_LEFT_EDGE_X (w) + WINDOW_TOTAL_WIDTH (w);
     }
   else
     {
-      x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
+      int area_left = window_box_left (w, area);
+      x += area_left;
       area_width = window_box_width (w, area);
-      last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
+      last_x = area_left + area_width;
     }
 
   /* Build a doubly-linked list of glyph_string structures between
@@ -17257,38 +17533,20 @@ draw_glyphs (w, x, row, area, start, end, hl, 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);
-
-      /* ++KFS: W32 and MAC versions had following test here:
-        if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
-      */
+      int text_left = window_box_left (w, TEXT_AREA);
+      x0 -= text_left;
+      x1 -= text_left;
 
-      if (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,
+      notice_overwritten_cursor (w, TEXT_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);
-  if (!row->full_width_p)
-    {
-      /* ++KFS: W32 and MAC versions only had this test here:
-        if (area > LEFT_MARGIN_AREA)
-      */
-
-      if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
-       x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
-      if (area > TEXT_AREA)
-       x_reached -= window_box_width (w, TEXT_AREA);
-    }
+  if (row->full_width_p)
+    x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
+  else
+    x_reached -= window_box_left (w, area);
 
   RELEASE_HDC (hdc, f);
 
@@ -17556,7 +17814,7 @@ produce_stretch_glyph (it)
   if (prop = Fplist_get (plist, QCwidth),
       NUMVAL (prop) > 0)
     /* Absolute width `:width WIDTH' specified and valid.  */
-    width = NUMVAL (prop) * CANON_X_UNIT (it->f);
+    width = NUMVAL (prop) * FRAME_COLUMN_WIDTH (it->f);
   else if (prop = Fplist_get (plist, QCrelative_width),
           NUMVAL (prop) > 0)
     {
@@ -17583,15 +17841,15 @@ produce_stretch_glyph (it)
     }
   else if (prop = Fplist_get (plist, QCalign_to),
           NUMVAL (prop) > 0)
-    width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
+    width = NUMVAL (prop) * FRAME_COLUMN_WIDTH (it->f) - it->current_x;
   else
     /* Nothing specified -> width defaults to canonical char width.  */
-    width = CANON_X_UNIT (it->f);
+    width = FRAME_COLUMN_WIDTH (it->f);
 
   /* Compute height.  */
   if (prop = Fplist_get (plist, QCheight),
       NUMVAL (prop) > 0)
-    height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
+    height = NUMVAL (prop) * FRAME_LINE_HEIGHT (it->f);
   else if (prop = Fplist_get (plist, QCrelative_height),
           NUMVAL (prop) > 0)
     height = FONT_HEIGHT (font) * NUMVAL (prop);
@@ -17676,23 +17934,17 @@ x_produce_glyphs (it)
       /* Maybe translate single-byte characters to multibyte, or the
         other way.  */
       it->char_to_display = it->c;
-      if (!ASCII_BYTE_P (it->c))
+      if (!ASCII_BYTE_P (it->c)
+         && ! it->multibyte_p)
        {
-         if (unibyte_display_via_language_environment
-             && SINGLE_BYTE_CHAR_P (it->c)
-             && (it->c >= 0240
-                 || !NILP (Vnonascii_translation_table)))
+         if (SINGLE_BYTE_CHAR_P (it->c)
+             && unibyte_display_via_language_environment)
+           it->char_to_display = unibyte_char_to_multibyte (it->c);
+         if (! SINGLE_BYTE_CHAR_P (it->c))
            {
-             it->char_to_display = unibyte_char_to_multibyte (it->c);
              it->multibyte_p = 1;
-             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
-             face = FACE_FROM_ID (it->f, it->face_id);
-           }
-         else if (!SINGLE_BYTE_CHAR_P (it->c)
-                  && !it->multibyte_p)
-           {
-             it->multibyte_p = 1;
-             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display,
+                                          -1, Qnil);
              face = FACE_FROM_ID (it->f, it->face_id);
            }
        }
@@ -17818,14 +18070,14 @@ x_produce_glyphs (it)
        }
       else if (it->char_to_display == '\t')
        {
-         int tab_width = it->tab_width * CANON_X_UNIT (it->f);
+         int tab_width = it->tab_width * FRAME_COLUMN_WIDTH (it->f);
          int x = it->current_x + it->continuation_lines_width;
          int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
 
          /* If the distance from the current position to the next tab
             stop is less than a canonical character width, use the
             tab stop after that.  */
-         if (next_tab_x - x < CANON_X_UNIT (it->f))
+         if (next_tab_x - x < FRAME_COLUMN_WIDTH (it->f))
            next_tab_x += tab_width;
 
          it->pixel_width = next_tab_x - x;
@@ -17848,20 +18100,18 @@ x_produce_glyphs (it)
 
          /* If we found a font, this font should give us the right
             metrics.  If we didn't find a font, use the frame's
-            default font and calculate the width of the character
-            from the charset width; this is what old redisplay code
-            did.  */
+            default font and calculate the width of the character by
+            multiplying the width of font by the width of the
+            character.  */
 
          pcm = rif->per_char_metric (font, &char2b,
                                      FONT_TYPE_FOR_MULTIBYTE (font, it->c));
 
          if (font_not_found_p || !pcm)
            {
-             int charset = CHAR_CHARSET (it->char_to_display);
-
              it->glyph_not_available_p = 1;
-             it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
-                                * CHARSET_WIDTH (charset));
+             it->pixel_width = (FRAME_COLUMN_WIDTH (it->f)
+                                * CHAR_WIDTH (it->char_to_display));
              it->phys_ascent = FONT_BASE (font) + boff;
              it->phys_descent = FONT_DESCENT (font) - boff;
            }
@@ -17920,20 +18170,20 @@ x_produce_glyphs (it)
       struct font_info *font_info;
       int boff;                        /* baseline offset */
       struct composition *cmp = composition_table[it->cmp_id];
+      int pos;
 
       /* Maybe translate single-byte characters to multibyte.  */
       it->char_to_display = it->c;
       if (unibyte_display_via_language_environment
-         && SINGLE_BYTE_CHAR_P (it->c)
-         && (it->c >= 0240
-             || (it->c >= 0200
-                 && !NILP (Vnonascii_translation_table))))
+         && it->c >= 0200)
        {
          it->char_to_display = unibyte_char_to_multibyte (it->c);
        }
 
       /* Get face and font to use.  Encode IT->char_to_display.  */
-      it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+      pos = STRINGP (it->string) ? IT_STRING_CHARPOS (*it) : IT_CHARPOS (*it);
+      it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display,
+                                  pos, it->string);
       face = FACE_FROM_ID (it->f, it->face_id);
       get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
                                  &char2b, it->multibyte_p, 0);
@@ -17966,8 +18216,8 @@ x_produce_glyphs (it)
         now.  Theoretically, we have to check all fonts for the
         glyphs, but that requires much time and memory space.  So,
         here we check only the font of the first glyph.  This leads
-        to incorrect display very rarely, and C-l (recenter) can
-        correct the display anyway.  */
+        to incorrect display, but it's very rare, and C-l (recenter)
+        can correct the display anyway.  */
       if (cmp->font != (void *) font)
        {
          /* Ascent and descent of the font of the first character of
@@ -17976,8 +18226,10 @@ x_produce_glyphs (it)
             them respectively.  */
          int font_ascent = FONT_BASE (font) + boff;
          int font_descent = FONT_DESCENT (font) - boff;
+         int font_height = FONT_HEIGHT (font);
          /* Bounding box of the overall glyphs.  */
          int leftmost, rightmost, lowest, highest;
+         int lbearing, rbearing;
          int i, width, ascent, descent;
 
          cmp->font = (void *) font;
@@ -17990,12 +18242,20 @@ x_produce_glyphs (it)
              width = pcm->width;
              ascent = pcm->ascent;
              descent = pcm->descent;
+             lbearing = pcm->lbearing;
+             if (lbearing > 0)
+               lbearing = 0;
+             rbearing = pcm->rbearing;
+             if (rbearing < width)
+               rbearing = width;
            }
          else
            {
              width = FONT_WIDTH (font);
              ascent = FONT_BASE (font);
              descent = FONT_DESCENT (font);
+             lbearing = 0;
+             rbearing = width;
            }
 
          rightmost = width;
@@ -18015,13 +18275,15 @@ x_produce_glyphs (it)
             the left.  */
          cmp->offsets[0] = 0;
          cmp->offsets[1] = boff;
+         cmp->lbearing = lbearing;
+         cmp->rbearing = rbearing;
 
          /* Set cmp->offsets for the remaining glyphs.  */
          for (i = 1; i < cmp->glyph_len; i++)
            {
              int left, right, btm, top;
              int ch = COMPOSITION_GLYPH (cmp, i);
-             int face_id = FACE_FOR_CHAR (it->f, face, ch);
+             int face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
 
              face = FACE_FROM_ID (it->f, face_id);
              get_char_face_and_encoding (it->f, ch, face->id,
@@ -18049,12 +18311,20 @@ x_produce_glyphs (it)
                  width = pcm->width;
                  ascent = pcm->ascent;
                  descent = pcm->descent;
+                 lbearing = pcm->lbearing;
+                 if (lbearing > 0)
+                   lbearing = 0;
+                 rbearing = pcm->rbearing;
+                 if (rbearing < width)
+                   rbearing = width;
                }
              else
                {
                  width = FONT_WIDTH (font);
                  ascent = 1;
                  descent = 0;
+                 lbearing = 0;
+                 rbearing = width;
                }
 
              if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
@@ -18095,15 +18365,21 @@ x_produce_glyphs (it)
                        6---7---8 -- descent
                  */
                  int rule = COMPOSITION_RULE (cmp, i);
-                 int gref, nref, grefx, grefy, nrefx, nrefy;
+                 int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
 
-                 COMPOSITION_DECODE_RULE (rule, gref, nref);
+                 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
                  grefx = gref % 3, nrefx = nref % 3;
                  grefy = gref / 3, nrefy = nref / 3;
+                 if (xoff)
+                   xoff = font_height * (xoff - 128) / 256;
+                 if (yoff)
+                   yoff = font_height * (yoff - 128) / 256;
 
                  left = (leftmost
                          + grefx * (rightmost - leftmost) / 2
-                         - nrefx * width / 2);
+                         - nrefx * width / 2
+                         + xoff);
+                 
                  btm = ((grefy == 0 ? highest
                          : grefy == 1 ? 0
                          : grefy == 2 ? lowest
@@ -18111,23 +18387,32 @@ x_produce_glyphs (it)
                         - (nrefy == 0 ? ascent + descent
                            : nrefy == 1 ? descent - boff
                            : nrefy == 2 ? 0
-                           : (ascent + descent) / 2));
+                           : (ascent + descent) / 2)
+                        + yoff);
                }
 
              cmp->offsets[i * 2] = left;
              cmp->offsets[i * 2 + 1] = btm + descent;
 
              /* Update the bounding box of the overall glyphs. */
-             right = left + width;
+             if (width > 0)
+               {
+                 right = left + width;
+                 if (left < leftmost)
+                   leftmost = left;
+                 if (right > rightmost)
+                   rightmost = right;
+               }
              top = btm + descent + ascent;
-             if (left < leftmost)
-               leftmost = left;
-             if (right > rightmost)
-               rightmost = right;
              if (top > highest)
                highest = top;
              if (btm < lowest)
                lowest = btm;
+
+             if (cmp->lbearing > left + lbearing)
+               cmp->lbearing = left + lbearing;
+             if (cmp->rbearing < left + rbearing)
+               cmp->rbearing = left + rbearing;
            }
 
          /* If there are glyphs whose x-offsets are negative,
@@ -18138,6 +18423,8 @@ x_produce_glyphs (it)
              for (i = 0; i < cmp->glyph_len; i++)
                cmp->offsets[i * 2] -= leftmost;
              rightmost -= leftmost;
+             cmp->lbearing -= leftmost;
+             cmp->rbearing -= leftmost;
            }
 
          cmp->pixel_width = rightmost;
@@ -18149,6 +18436,11 @@ x_produce_glyphs (it)
            cmp->descent = font_descent;
        }
 
+      if (it->glyph_row
+         && (cmp->lbearing < 0
+             || cmp->rbearing > cmp->pixel_width))
+       it->glyph_row->contains_overlapping_glyphs_p = 1;
+
       it->pixel_width = cmp->pixel_width;
       it->ascent = it->phys_ascent = cmp->ascent;
       it->descent = it->phys_descent = cmp->descent;
@@ -18225,9 +18517,6 @@ x_write_glyphs (start, len)
                   hpos, hpos + len,
                   DRAW_NORMAL_TEXT, 0);
 
-#ifndef HAVE_CARBON  
-  /* ++KFS: Why not on MAC ? */
-
   /* Invalidate old phys cursor if the glyph at its hpos is redrawn.  */
   if (updated_area == TEXT_AREA
       && updated_window->phys_cursor_on_p
@@ -18235,7 +18524,6 @@ x_write_glyphs (start, len)
       && updated_window->phys_cursor.hpos >= hpos
       && updated_window->phys_cursor.hpos < hpos + len)
     updated_window->phys_cursor_on_p = 0;
-#endif
 
   UNBLOCK_INPUT;
 
@@ -18258,7 +18546,8 @@ 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;
+  int frame_x, frame_y;
+  EMACS_INT hpos;
 
   xassert (updated_window && updated_row);
   BLOCK_INPUT;
@@ -18283,8 +18572,8 @@ x_insert_glyphs (start, len)
   frame_x = window_box_left (w, updated_area) + output_cursor.x;
   frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
 
-  rif->shift_glyphs_for_insert (f, frame_x, frame_y, line_height,
-                               shifted_region_width, shift_by_width);
+  rif->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
+                               line_height, shift_by_width);
 
   /* Write the glyphs.  */
   hpos = start - row->glyphs[updated_area];
@@ -18320,12 +18609,7 @@ x_clear_end_of_line (to_x)
   f = XFRAME (w->frame);
 
   if (updated_row->full_width_p)
-    {
-      max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
-      if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
-         && !w->pseudo_window_p)
-       max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
-    }
+    max_x = WINDOW_TOTAL_WIDTH (w);
   else
     max_x = window_box_width (w, updated_area);
   max_y = window_text_bottom_y (w);
@@ -18358,11 +18642,12 @@ x_clear_end_of_line (to_x)
     }
   else
     {
-      from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
-      to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
+      int area_left = window_box_left (w, updated_area);
+      from_x += area_left;
+      to_x += area_left;
     }
 
-  min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+  min_y = WINDOW_HEADER_LINE_HEIGHT (w);
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
 
@@ -18594,16 +18879,6 @@ notice_overwritten_cursor (w, area, x0, x1, y0, y1)
      enum glyph_row_area area;
      int x0, y0, x1, y1;
 {
-#ifdef HAVE_CARBON
-  /* ++KFS:  Why is there a special version of this for the mac ? */
-  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;
-#else
   if (area == TEXT_AREA && w->phys_cursor_on_p)
     {
       int cx0 = w->phys_cursor.x;
@@ -18634,7 +18909,6 @@ notice_overwritten_cursor (w, area, x0, x1, y0, y1)
            w->phys_cursor_on_p = 0;
        }
     }
-#endif
 }
 
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -18659,14 +18933,7 @@ x_fix_overlapping_area (w, row, area)
 
   BLOCK_INPUT;
 
-  if (area == LEFT_MARGIN_AREA)
-    x = 0;
-  else if (area == TEXT_AREA)
-    x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
-  else
-    x = (window_box_width (w, LEFT_MARGIN_AREA)
-        + window_box_width (w, TEXT_AREA));
-
+  x = 0;
   for (i = 0; i < row->used[area];)
     {
       if (row->glyphs[area][i].overlaps_vertically_p)
@@ -18718,16 +18985,12 @@ draw_phys_cursor_glyph (w, row, hl)
                        hl, 0);
       w->phys_cursor_on_p = on_p;
 
-#ifndef HAVE_CARBON
-      /* ++KFS: MAC version did not adjust phys_cursor_width (bug?) */
       if (hl == DRAW_CURSOR)
        w->phys_cursor_width = x1 - w->phys_cursor.x;
-      else
-#endif
       /* When we erase the cursor, and ROW is overlapped by other
         rows, make sure that these overlapping parts of other rows
         are redrawn.  */
-      if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
+      else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
        {
          if (row > w->current_matrix->rows
              && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
@@ -18808,7 +19071,7 @@ erase_phys_cursor (w)
   if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
     {
       int x, y;
-      int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+      int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
 
       cursor_glyph = get_phys_cursor_glyph (w);
       if (cursor_glyph == NULL)
@@ -18850,7 +19113,6 @@ display_and_set_cursor (w, on, hpos, vpos, x, y)
   int active_cursor;
   struct glyph_matrix *current_glyphs;
   struct glyph_row *glyph_row;
-  struct glyph *glyph;
 
   /* This is pointless on invisible frames, and dangerous on garbaged
      windows and frames; in the latter case, the frame or window may
@@ -18868,7 +19130,6 @@ display_and_set_cursor (w, on, hpos, vpos, x, y)
 
   current_glyphs = w->current_matrix;
   glyph_row = MATRIX_ROW (current_glyphs, vpos);
-  glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
 
   /* If cursor row is not enabled, we don't really know where to
      display the cursor.  */
@@ -18913,8 +19174,9 @@ display_and_set_cursor (w, on, hpos, vpos, x, y)
       w->phys_cursor.vpos = vpos;
     }
 
-  rif->draw_window_cursor (w, glyph_row, on, x, y,
-                          new_cursor_type, new_cursor_width);
+  rif->draw_window_cursor (w, glyph_row, x, y,
+                          new_cursor_type, new_cursor_width,
+                          on, active_cursor);
 }
 
 
@@ -19130,7 +19392,7 @@ cursor_in_mouse_face_p (w)
    of last line in W.  In the row containing CHARPOS, stop before glyphs
    having STOP as object.  */
 
-#if 0 /* This is a version of fast_find_position that's more correct
+#if 1 /* This is a version of fast_find_position that's more correct
         in the presence of hscrolling, for example.  I didn't install
         it right away because the problem fixed is minor, it failed
         in 20.x as well, and I think it's too risky to install
@@ -19139,13 +19401,13 @@ cursor_in_mouse_face_p (w)
 static int
 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
      struct window *w;
-     int charpos;
+     EMACS_INT charpos;
      int *hpos, *vpos, *x, *y;
      Lisp_Object stop;
 {
   struct glyph_row *row, *first;
   struct glyph *glyph, *end;
-  int i, past_end = 0;
+  int past_end = 0;
 
   first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
   row = row_containing_pos (w, charpos, first, NULL, 0);
@@ -19197,12 +19459,12 @@ fast_find_position (w, charpos, hpos, vpos, x, y, stop)
   return past_end;
 }
 
-#else /* not 0 */
+#else /* not 1 */
 
 static int
 fast_find_position (w, pos, hpos, vpos, x, y, stop)
      struct window *w;
-     int pos;
+     EMACS_INT pos;
      int *hpos, *vpos, *x, *y;
      Lisp_Object stop;
 {
@@ -19295,7 +19557,7 @@ fast_find_position (w, pos, hpos, vpos, x, y, stop)
   return 0;
 }
 
-#endif /* not 0 */
+#endif /* not 1 */
 
 
 /* Find the position of the glyph for position POS in OBJECT in
@@ -19316,7 +19578,7 @@ fast_find_position (w, pos, hpos, vpos, x, y, stop)
 static int
 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
      struct window *w;
-     int pos;
+     EMACS_INT pos;
      Lisp_Object object;
      int *hpos, *vpos, *x, *y;
      int right_p;
@@ -19380,90 +19642,6 @@ fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
 }
 
 
-#ifdef HAVE_CARBON  
-
-/* ++KFS: Why does MAC have its own version here?  Looks like OLD CODE!! */
-
-/* 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 fringes and scroll bars must be subtracted
-   to get a position relative to the start of the mode line.  */
-
-static void
-note_mode_line_highlight (w, x, mode_line_p)
-     struct window *w;
-     int x, mode_line_p;
-{
-  struct frame *f = XFRAME (w->frame);
-  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-  Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
-  struct glyph_row *row;
-
-  if (mode_line_p)
-    row = MATRIX_MODE_LINE_ROW (w->current_matrix);
-  else
-    row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
-
-  if (row->enabled_p)
-    {
-      struct glyph *glyph, *end;
-      Lisp_Object help, map;
-      int x0;
-
-      /* Find the glyph under X.  */
-      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_FRINGE_WIDTH (f));
-
-      while (glyph < end
-            && x >= x0 + glyph->pixel_width)
-       {
-         x0 += glyph->pixel_width;
-         ++glyph;
-       }
-
-      if (glyph < end
-         && STRINGP (glyph->object)
-         && STRING_INTERVALS (glyph->object)
-         && glyph->charpos >= 0
-         && 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
-            setting the global variable help_echo_string to the help
-            string.  */
-         help = Fget_text_property (make_number (glyph->charpos),
-                                    Qhelp_echo, glyph->object);
-         if (!NILP (help))
-            {
-              help_echo_string = help;
-              XSETWINDOW (help_echo_window, w);
-              help_echo_object = glyph->object;
-              help_echo_pos = glyph->charpos;
-            }
-
-         /* Change the mouse pointer according to what is under X/Y.  */
-         map = Fget_text_property (make_number (glyph->charpos),
-                                   Qlocal_map, glyph->object);
-         if (KEYMAPP (map))
-           cursor = f->output_data.mac->nontext_cursor;
-         else
-           {
-             map = Fget_text_property (make_number (glyph->charpos),
-                                       Qkeymap, glyph->object);
-             if (KEYMAPP (map))
-               cursor = f->output_data.mac->nontext_cursor;
-           }
-       }
-    }
-
-  rif->define_frame_cursor (f, cursor);
-}
-
-#else
-
 /* Take proper action when mouse has moved to the mode or header line
    or marginal area AREA of window W, x-position X and y-position Y.
    X is relative to the start of the text display area of W, so the
@@ -19514,8 +19692,6 @@ note_mode_line_or_margin_highlight (w, x, y, area)
   rif->define_frame_cursor (f, cursor);
 }
 
-#endif /* !HAVE_CARBON */
-
 
 /* EXPORT:
    Take proper action when the mouse has moved to position X, Y on
@@ -19559,7 +19735,7 @@ note_mouse_highlight (f, x, y)
     }
 
   /* Which window is that in?  */
-  window = window_from_coordinates (f, x, y, &part, 1);
+  window = window_from_coordinates (f, x, y, &part, 0, 0, 1);
 
   /* If we were displaying active text in another window, clear that.  */
   if (! EQ (window, dpyinfo->mouse_face_window))
@@ -19585,16 +19761,6 @@ note_mouse_highlight (f, x, y)
       return;
     }
 
-#ifdef HAVE_CARBON
-  /* ++KFS: Why does MAC have its own version here?  Looks like OLD CODE!! */
-
-  /* Mouse is on the mode or header line?  */
-  if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
-    {
-      note_mode_line_highlight (w, x, part == ON_MODE_LINE);
-      return;
-    }
-#else
   /* Mouse is on the mode, header line or margin?  */
   if (part == ON_MODE_LINE || part == ON_HEADER_LINE
       || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
@@ -19602,7 +19768,6 @@ note_mouse_highlight (f, x, y)
       note_mode_line_or_margin_highlight (w, x, y, part);
       return;
     }
-#endif
 
   if (part == ON_VERTICAL_BORDER)
     cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
@@ -19970,7 +20135,11 @@ note_mouse_highlight (f, x, y)
 
  set_cursor:
 
+#ifndef HAVE_CARBON
   if (cursor != No_Cursor)
+#else
+  if (bcmp (&cursor, &No_Cursor, sizeof (Cursor)))
+#endif
     rif->define_frame_cursor (f, cursor);
 }
 
@@ -20050,13 +20219,9 @@ expose_area (w, row, r, area)
       /* Set START_X to the window-relative start position for drawing glyphs of
         AREA.  The first glyph of the text area can be partially visible.
         The first glyphs of other areas cannot.  */
-      if (area == LEFT_MARGIN_AREA)
-       start_x = 0;
-      else if (area == TEXT_AREA)
-       start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
-      else
-       start_x = (window_box_width (w, LEFT_MARGIN_AREA)
-                  + window_box_width (w, TEXT_AREA));
+      start_x = window_box_left_offset (w, area);
+      if (area == TEXT_AREA)
+       start_x += row->x;
       x = start_x;
 
       /* Find the first glyph that must be redrawn.  */
@@ -20163,7 +20328,9 @@ phys_cursor_in_rect_p (w, r)
   cursor_glyph = get_phys_cursor_glyph (w);
   if (cursor_glyph)
     {
-      cr.x = w->phys_cursor.x;
+      /* r is relative to W's box, but w->phys_cursor.x is relative 
+        to left edge of W's TEXT area.  Adjust it.  */
+      cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
       cr.y = w->phys_cursor.y;
       cr.width = cursor_glyph->pixel_width;
       cr.height = w->phys_cursor_height;
@@ -20184,23 +20351,34 @@ void
 x_draw_vertical_border (w)
      struct window *w;
 {
-  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  /* We could do better, if we knew what type of scroll-bar the adjacent
+     windows (on either side) have...  But we don't :-( 
+     However, I think this works ok.  ++KFS 2003-04-25 */
 
   /* Redraw borders between horizontally adjacent windows.  Don't
      do it for frames with vertical scroll bars because either the
      right scroll bar of a window, or the left scroll bar of its
      neighbor will suffice as a border.  */
   if (!WINDOW_RIGHTMOST_P (w)
-      && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+      && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
     {
       int x0, x1, y0, y1;
 
       window_box_edges (w, -1, &x0, &y0, &x1, &y1);
-      x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
       y1 -= 1;
 
       rif->draw_vertical_window_border (w, x1, y0, y1);
     }
+  else if (!WINDOW_LEFTMOST_P (w)
+          && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
+    {
+      int x0, x1, y0, y1;
+
+      window_box_edges (w, -1, &x0, &y0, &x1, &y1);
+      y1 -= 1;
+
+      rif->draw_vertical_window_border (w, x0, y0, y1);
+    }
 }
 
 
@@ -20235,10 +20413,10 @@ expose_window (w, fr)
     }
 
   /* Frame-relative pixel rectangle of W.  */
-  wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
-  wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
-  wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
-  wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
+  wr.x = WINDOW_LEFT_EDGE_X (w);
+  wr.y = WINDOW_TOP_EDGE_Y (w);
+  wr.width = WINDOW_TOTAL_WIDTH (w);
+  wr.height = WINDOW_TOTAL_HEIGHT (w);
 
   if (x_intersect_rectangles (fr, &wr, &r))
     {
@@ -20251,8 +20429,8 @@ expose_window (w, fr)
              r.x, r.y, r.width, r.height));
 
       /* Convert to window coordinates.  */
-      r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
-      r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
+      r.x -= WINDOW_LEFT_EDGE_X (w);
+      r.y -= WINDOW_TOP_EDGE_Y (w);
 
       /* Turn off the cursor.  */
       if (!w->pseudo_window_p
@@ -20413,8 +20591,8 @@ expose_frame (f, x, y, w, h)
   if (w == 0 || h == 0)
     {
       r.x = r.y = 0;
-      r.width = CANON_X_UNIT (f) * f->width;
-      r.height = CANON_Y_UNIT (f) * f->height;
+      r.width = FRAME_COLUMN_WIDTH (f) * FRAME_COLS (f);
+      r.height = FRAME_LINE_HEIGHT (f) * FRAME_LINES (f);
     }
   else
     {
@@ -20979,15 +21157,15 @@ init_xdisp ()
       struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
       int i;
 
-      XWINDOW (root_window)->top = make_number (FRAME_TOP_MARGIN (f));
+      XWINDOW (root_window)->top_line = make_number (FRAME_TOP_MARGIN (f));
       set_window_height (root_window,
-                        FRAME_HEIGHT (f) - 1 - FRAME_TOP_MARGIN (f),
+                        FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f),
                         0);
-      mini_w->top = make_number (FRAME_HEIGHT (f) - 1);
+      mini_w->top_line = make_number (FRAME_LINES (f) - 1);
       set_window_height (minibuf_window, 1, 0);
 
-      XWINDOW (root_window)->width = make_number (FRAME_WIDTH (f));
-      mini_w->width = make_number (FRAME_WIDTH (f));
+      XWINDOW (root_window)->total_cols = make_number (FRAME_COLS (f));
+      mini_w->total_cols = make_number (FRAME_COLS (f));
 
       scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
       scratch_glyph_row.glyphs[TEXT_AREA + 1]