Mention `tla replay' in README.multi-tty (Gaute Strokkenes).
[bpt/emacs.git] / src / xdisp.c
index 4b49472..3c144f4 100644 (file)
@@ -301,6 +301,7 @@ extern Lisp_Object Qface, Qinvisible, Qwidth;
 Lisp_Object Vdisplay_pixels_per_inch;
 Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
 Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
+Lisp_Object Qcenter;
 Lisp_Object Qmargin, Qpointer;
 extern Lisp_Object Qheight;
 extern Lisp_Object QCwidth, QCheight, QCascent;
@@ -311,13 +312,10 @@ extern Lisp_Object Qscroll_bar;
 Lisp_Object Vshow_trailing_whitespace;
 
 #ifdef HAVE_WINDOW_SYSTEM
-/* Non-nil means that newline may flow into the right fringe.  */
-
-Lisp_Object Voverflow_newline_into_fringe;
-#endif /* HAVE_WINDOW_SYSTEM */
+extern Lisp_Object Voverflow_newline_into_fringe;
 
 /* Test if overflow newline into fringe.  Called with iterator IT
-   at or past right window margin, and with IT->current_x set.  */ 
+   at or past right window margin, and with IT->current_x set.  */
 
 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it)    \
   (!NILP (Voverflow_newline_into_fringe)       \
@@ -325,6 +323,8 @@ Lisp_Object Voverflow_newline_into_fringe;
    && WINDOW_RIGHT_FRINGE_WIDTH (it->w) > 0    \
    && it->current_x == it->last_visible_x)
 
+#endif /* HAVE_WINDOW_SYSTEM */
+
 /* Non-nil means show the text cursor in void text areas
    i.e. in blank areas after eol and eob.  This used to be
    the default in 21.3.  */
@@ -404,6 +404,13 @@ int multiple_frames;
 
 Lisp_Object Vglobal_mode_string;
 
+
+/* List of variables (symbols) which hold markers for overlay arrows.
+   The symbols on this list are examined during redisplay to determine
+   where to display overlay arrows.  */
+
+Lisp_Object Voverlay_arrow_variable_list;
+
 /* Marker for where to display an arrow on top of the buffer text.  */
 
 Lisp_Object Voverlay_arrow_position;
@@ -412,11 +419,17 @@ Lisp_Object Voverlay_arrow_position;
 
 Lisp_Object Voverlay_arrow_string;
 
-/* Values of those variables at last redisplay.  However, if
-   Voverlay_arrow_position is a marker, last_arrow_position is its
+/* Values of those variables at last redisplay are stored as
+   properties on `overlay-arrow-position' symbol.  However, if
+   Voverlay_arrow_position is a marker, last-arrow-position is its
    numerical position.  */
 
-static Lisp_Object last_arrow_position, last_arrow_string;
+Lisp_Object Qlast_arrow_position, Qlast_arrow_string;
+
+/* Alternative overlay-arrow-string and overlay-arrow-bitmap
+   properties on a symbol in overlay-arrow-variable-list.  */
+
+Lisp_Object Qoverlay_arrow_string, Qoverlay_arrow_bitmap;
 
 /* Like mode-line-format, but for the title bar on a visible frame.  */
 
@@ -829,10 +842,11 @@ static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
 static int compute_window_start_on_continuation_line P_ ((struct window *));
 static Lisp_Object safe_eval_handler P_ ((Lisp_Object));
 static void insert_left_trunc_glyphs P_ ((struct it *));
-static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
+static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *,
+                                                         Lisp_Object));
 static void extend_face_to_end_of_line P_ ((struct it *));
 static int append_space P_ ((struct it *, int));
-static int make_cursor_line_fully_visible P_ ((struct window *));
+static int make_cursor_line_fully_visible P_ ((struct window *, int));
 static int try_scrolling P_ ((Lisp_Object, int, EMACS_INT, EMACS_INT, int, int));
 static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
 static int trailing_whitespace_p P_ ((int));
@@ -1775,8 +1789,9 @@ get_glyph_string_clip_rect (s, nr)
       height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
       if (height < r.height)
        {
-         r.y = s->ybase + glyph->descent - height;
-         r.height = height;
+         int max_y = r.y + r.height;
+         r.y = min (max_y, s->ybase + glyph->descent - height);
+         r.height = min (max_y - r.y, height);
        }
     }
 
@@ -1901,10 +1916,14 @@ check_it (it)
       xassert (STRINGP (it->string));
       xassert (IT_STRING_CHARPOS (*it) >= 0);
     }
-  else if (it->method == next_element_from_buffer)
+  else
     {
-      /* Check that character and byte positions agree.  */
-      xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
+      xassert (IT_STRING_CHARPOS (*it) < 0);
+      if (it->method == next_element_from_buffer)
+       {
+         /* Check that character and byte positions agree.  */
+         xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
+       }
     }
 
   if (it->dpvec)
@@ -2017,6 +2036,8 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id)
   it->current.overlay_string_index = -1;
   it->current.dpvec_index = -1;
   it->base_face_id = base_face_id;
+  it->string = Qnil;
+  IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
 
   /* The window in which we iterate over current_buffer:  */
   XSETWINDOW (it->window, w);
@@ -3275,6 +3296,8 @@ handle_display_prop (it)
       && !EQ (XCAR (prop), Qraise)
       /* Marginal area specifications.  */
       && !(CONSP (XCAR (prop)) && EQ (XCAR (XCAR (prop)), Qmargin))
+      && !EQ (XCAR (prop), Qleft_fringe)
+      && !EQ (XCAR (prop), Qright_fringe)
       && !NILP (XCAR (prop)))
     {
       for (; CONSP (prop); prop = XCDR (prop))
@@ -3499,6 +3522,64 @@ handle_single_display_prop (it, prop, object, position,
         text properties change there.  */
       it->stop_charpos = position->charpos;
 
+      if (CONSP (prop)
+         && (EQ (XCAR (prop), Qleft_fringe)
+             || EQ (XCAR (prop), Qright_fringe))
+         && CONSP (XCDR (prop)))
+       {
+         unsigned face_id = DEFAULT_FACE_ID;
+
+         /* Save current settings of IT so that we can restore them
+            when we are finished with the glyph property value.  */
+
+         /* `(left-fringe BITMAP FACE)'.  */
+         if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+           return 0;
+
+#ifdef HAVE_WINDOW_SYSTEM
+         value = XCAR (XCDR (prop));
+         if (!NUMBERP (value)
+             || !valid_fringe_bitmap_id_p (XINT (value)))
+           return 0;
+
+         if (CONSP (XCDR (XCDR (prop))))
+           {
+             Lisp_Object face_name = XCAR (XCDR (XCDR (prop)));
+
+             face_id = lookup_named_face (it->f, face_name, 'A');
+             if (face_id < 0)
+               return 0;
+           }
+
+         push_it (it);
+
+         it->area = TEXT_AREA;
+         it->what = IT_IMAGE;
+         it->image_id = -1; /* no image */
+         it->position = start_pos;
+         it->object = NILP (object) ? it->w->buffer : object;
+         it->method = next_element_from_image;
+         it->face_id = face_id;
+
+         /* Say that we haven't consumed the characters with
+            `display' property yet.  The call to pop_it in
+            set_iterator_to_next will clean this up.  */
+         *position = start_pos;
+
+         if (EQ (XCAR (prop), Qleft_fringe))
+           {
+             it->left_user_fringe_bitmap = XINT (value);
+             it->left_user_fringe_face_id = face_id;
+           }
+         else
+           {
+             it->right_user_fringe_bitmap = XINT (value);
+             it->right_user_fringe_face_id = face_id;
+           }
+#endif /* HAVE_WINDOW_SYSTEM */
+         return 1;
+       }
+
       location = Qunbound;
       if (CONSP (prop) && CONSP (XCAR (prop)))
        {
@@ -3524,16 +3605,11 @@ handle_single_display_prop (it, prop, object, position,
          value = prop;
        }
 
+      valid_p = (STRINGP (value)
 #ifdef HAVE_WINDOW_SYSTEM
-      if (FRAME_TERMCAP_P (it->f))
-       valid_p = STRINGP (value);
-      else
-       valid_p = (STRINGP (value)
-                  || (CONSP (value) && EQ (XCAR (value), Qspace))
-                  || valid_image_p (value));
-#else /* not HAVE_WINDOW_SYSTEM */
-      valid_p = STRINGP (value);
+                || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
 #endif /* not HAVE_WINDOW_SYSTEM */
+                || (CONSP (value) && EQ (XCAR (value), Qspace)));
 
       if ((EQ (location, Qleft_margin)
           || EQ (location, Qright_margin)
@@ -5515,15 +5591,18 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
   saved_glyph_row = it->glyph_row;
   it->glyph_row = NULL;
 
+#define BUFFER_POS_REACHED_P()                     \
+  ((op & MOVE_TO_POS) != 0                         \
+   && BUFFERP (it->object)                         \
+   && IT_CHARPOS (*it) >= to_charpos)
+
   while (1)
     {
       int x, i, ascent = 0, descent = 0;
 
       /* Stop when ZV or TO_CHARPOS reached.  */
       if (!get_next_display_element (it)
-         || ((op & MOVE_TO_POS) != 0
-             && BUFFERP (it->object)
-             && IT_CHARPOS (*it) >= to_charpos))
+         || BUFFER_POS_REACHED_P ())
        {
          result = MOVE_POS_MATCH_OR_ZV;
          break;
@@ -5610,7 +5689,12 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
 #ifdef HAVE_WINDOW_SYSTEM
                          if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
                            {
-                             get_next_display_element (it);
+                             if (!get_next_display_element (it)
+                                 || BUFFER_POS_REACHED_P ())
+                               {
+                                 result = MOVE_POS_MATCH_OR_ZV;
+                                 break;
+                               }
                              if (ITERATOR_AT_END_OF_LINE_P (it))
                                {
                                  result = MOVE_NEWLINE_OR_CR;
@@ -5678,7 +5762,12 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
 #ifdef HAVE_WINDOW_SYSTEM
          if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
            {
-             get_next_display_element (it);
+             if (!get_next_display_element (it)
+                 || BUFFER_POS_REACHED_P ())
+               {
+                 result = MOVE_POS_MATCH_OR_ZV;
+                 break;
+               }
              if (ITERATOR_AT_END_OF_LINE_P (it))
                {
                  result = MOVE_NEWLINE_OR_CR;
@@ -5691,6 +5780,8 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
        }
     }
 
+#undef BUFFER_POS_REACHED_P
+
   /* Restore the iterator settings altered at the beginning of this
      function.  */
   it->glyph_row = saved_glyph_row;
@@ -7614,7 +7705,10 @@ clear_garbaged_frames ()
          if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
            {
              if (f->resized_p)
-               Fredraw_frame (frame);
+               {
+                 Fredraw_frame (frame);
+                 f->force_flush_display_p = 1;
+               }
              clear_current_matrices (f);
              changed_count++;
              f->garbaged = 0;
@@ -8270,7 +8364,7 @@ update_tool_bar (f, save_match_data)
          /* 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);
@@ -8928,536 +9022,6 @@ note_tool_bar_highlight (f, x, y)
 
 
 \f
-/***********************************************************************
-                              Fringes
- ***********************************************************************/
-
-#ifdef HAVE_WINDOW_SYSTEM
-
-/* Notice that all bitmaps bits are "mirrored".  */
-
-/* An arrow like this: `<-'.  */
-/*
-  ...xx...
-  ....xx..
-  .....xx.
-  ..xxxxxx
-  ..xxxxxx
-  .....xx.
-  ....xx..
-  ...xx...
-*/
-static unsigned char left_bits[] = {
-   0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
-
-
-/* Right truncation arrow bitmap `->'.  */
-/*
-  ...xx...
-  ..xx....
-  .xx.....
-  xxxxxx..
-  xxxxxx..
-  .xx.....
-  ..xx....
-  ...xx...
-*/
-static unsigned char right_bits[] = {
-   0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
-
-
-/* Up arrow bitmap.  */
-/*
-  ...xx...
-  ..xxxx..
-  .xxxxxx.
-  xxxxxxxx
-  ...xx...
-  ...xx...
-  ...xx...
-  ...xx...
-*/
-static unsigned char up_arrow_bits[] = {
-   0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
-
-
-/* Down arrow bitmap.  */
-/*
-  ...xx...
-  ...xx...
-  ...xx...
-  ...xx...
-  xxxxxxxx
-  .xxxxxx.
-  ..xxxx..
-  ...xx...
-*/
-static unsigned char down_arrow_bits[] = {
-   0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
-
-/* Marker for continued lines.  */
-/*
-  ..xxxx..
-  .xxxxx..
-  xx......
-  xxx..x..
-  xxxxxx..
-  .xxxxx..
-  ..xxxx..
-  .xxxxx..
-*/
-static unsigned char continued_bits[] = {
-   0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
-
-/* Marker for continuation lines.  */
-/*
-  ..xxxx..
-  ..xxxxx.
-  ......xx
-  ..x..xxx
-  ..xxxxxx
-  ..xxxxx.
-  ..xxxx..
-  ..xxxxx.
-*/
-static unsigned char continuation_bits[] = {
-   0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
-
-/* Overlay arrow bitmap.  A triangular arrow.  */
-/*
-  ......xx
-  ....xxxx
-  ...xxxxx
-  ..xxxxxx
-  ..xxxxxx
-  ...xxxxx
-  ....xxxx
-  ......xx
-*/
-static unsigned char ov_bits[] = {
-   0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
-
-
-/* First line bitmap.  An left-up angle.  */
-/*
-  ..xxxxxx
-  ..xxxxxx
-  ......xx
-  ......xx
-  ......xx
-  ......xx
-  ......xx
-  ........
-*/
-static unsigned char first_line_bits[] = {
-   0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00};
-
-
-/* Last line bitmap.  An left-down angle.  */
-/*
-  ........
-  xx......
-  xx......
-  xx......
-  xx......
-  xx......
-  xxxxxx..
-  xxxxxx..
-*/
-static unsigned char last_line_bits[] = {
-   0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
-
-/* Filled box cursor bitmap.  A filled box; max 13 pixels high.  */
-/*
-  .xxxxxxx
-  .xxxxxxx
-  .xxxxxxx
-  .xxxxxxx
-  .xxxxxxx
-  .xxxxxxx
-  .xxxxxxx
-  .xxxxxxx
-  .xxxxxxx
-  .xxxxxxx
-  .xxxxxxx
-  .xxxxxxx
-  .xxxxxxx
-*/
-static unsigned char filled_box_cursor_bits[] = {
-   0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f};
-
-/* Hollow box cursor bitmap.  A hollow box; max 13 pixels high.  */
-/*
-  .xxxxxxx
-  .x.....x
-  .x.....x
-  .x.....x
-  .x.....x
-  .x.....x
-  .x.....x
-  .x.....x
-  .x.....x
-  .x.....x
-  .x.....x
-  .x.....x
-  .xxxxxxx
-*/
-static unsigned char hollow_box_cursor_bits[] = {
-   0x7f, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x7f};
-
-/* Bar cursor bitmap.  A vertical bar; max 13 pixels high.  */
-/*
-  ......xx
-  ......xx
-  ......xx
-  ......xx
-  ......xx
-  ......xx
-  ......xx
-  ......xx
-  ......xx
-  ......xx
-  ......xx
-  ......xx
-  ......xx
-*/
-static unsigned char bar_cursor_bits[] = {
-   0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
-
-/* HBar cursor bitmap.  A horisontal bar; 2 pixels high.  */
-/*
-  .xxxxxxx
-  .xxxxxxx
-*/
-static unsigned char hbar_cursor_bits[] = {
-  0x7f, 0x7f};
-
-
-/* Bitmap drawn to indicate lines not displaying text if
-   `indicate-empty-lines' is non-nil.  */
-static unsigned char zv_bits[] = {
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
-
-/* Hollow square bitmap.  */
-/*
-  .xxxxxx.
-  .x....x.
-  .x....x.
-  .x....x.
-  .x....x.
-  .xxxxxx.
-*/
-static unsigned char hollow_square_bits[] = {
-   0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
-
-
-struct fringe_bitmap fringe_bitmaps[MAX_FRINGE_BITMAPS] =
-{
-  { 0, 0, 0, NULL /* NO_FRINGE_BITMAP */ },
-  { 8, sizeof (left_bits), 0, left_bits },
-  { 8, sizeof (right_bits), 0, right_bits },
-  { 8, sizeof (up_arrow_bits), -1, up_arrow_bits },
-  { 8, sizeof (down_arrow_bits), -2, down_arrow_bits },
-  { 8, sizeof (continued_bits), 0, continued_bits },
-  { 8, sizeof (continuation_bits), 0, continuation_bits },
-  { 8, sizeof (ov_bits), 0, ov_bits },
-  { 8, sizeof (first_line_bits), -1, first_line_bits },
-  { 8, sizeof (last_line_bits), -2, last_line_bits },
-  { 8, sizeof (filled_box_cursor_bits), 0, filled_box_cursor_bits },
-  { 8, sizeof (hollow_box_cursor_bits), 0, hollow_box_cursor_bits },
-  { 8, sizeof (bar_cursor_bits), 0, bar_cursor_bits },
-  { 8, sizeof (hbar_cursor_bits), -2, hbar_cursor_bits },
-  { 8, sizeof (zv_bits), 3, zv_bits },
-  { 8, sizeof (hollow_square_bits), 0, hollow_square_bits },
-};
-
-
-/* Draw the bitmap WHICH in one of the left or right fringes of
-   window W.  ROW is the glyph row for which to display the bitmap; it
-   determines the vertical position at which the bitmap has to be
-   drawn.
-   LEFT_P is 1 for left fringe, 0 for right fringe.
-*/
-
-void
-draw_fringe_bitmap (w, row, left_p)
-     struct window *w;
-     struct glyph_row *row;
-     int left_p;
-{
-  struct frame *f = XFRAME (WINDOW_FRAME (w));
-  struct draw_fringe_bitmap_params p;
-  enum fringe_bitmap_type which;
-  int period;
-
-  if (left_p)
-    which = row->left_fringe_bitmap;
-  else if (!row->cursor_in_fringe_p)
-    which = row->right_fringe_bitmap;
-  else
-    switch (w->phys_cursor_type)
-      {
-      case HOLLOW_BOX_CURSOR:
-       if (row->visible_height >= sizeof(hollow_box_cursor_bits))
-         which = HOLLOW_BOX_CURSOR_BITMAP;
-       else
-         which = HOLLOW_SQUARE_BITMAP;
-       break;
-      case FILLED_BOX_CURSOR:
-       which = FILLED_BOX_CURSOR_BITMAP;
-       break;
-      case BAR_CURSOR:
-       which = BAR_CURSOR_BITMAP;
-       break;
-      case HBAR_CURSOR:
-       which = HBAR_CURSOR_BITMAP;
-       break;
-      case NO_CURSOR:
-      default:
-       w->phys_cursor_on_p = 0;
-       row->cursor_in_fringe_p = 0;
-       which = row->right_fringe_bitmap;
-       break;
-      }
-
-  period = fringe_bitmaps[which].period;
-
-  /* Convert row to frame coordinates.  */
-  p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
-
-  p.which = which;
-  p.wd = fringe_bitmaps[which].width;
-
-  p.h = fringe_bitmaps[which].height;
-  p.dh = (period > 0 ? (p.y % period) : 0);
-  p.h -= p.dh;
-  /* Clip bitmap if too high.  */
-  if (p.h > row->height)
-    p.h = row->height;
-
-  p.face = FACE_FROM_ID (f, FRINGE_FACE_ID);
-  PREPARE_FACE_FOR_DISPLAY (f, p.face);
-
-  /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
-     the fringe.  */
-  p.bx = -1;
-  if (left_p)
-    {
-      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.  */
-         wd -= ((!WINDOW_LEFTMOST_P (w)
-                 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
-                ? 1 : 0);
-         p.bx = x - wd;
-         p.nx = wd;
-       }
-    }
-  else
-    {
-      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 < wd || row->height > p.h)
-       {
-         p.bx = x;
-         p.nx = wd;
-       }
-    }
-
-  if (p.bx >= 0)
-    {
-      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;
-    }
-
-  /* Adjust y to the offset in the row to start drawing the bitmap.  */
-  if (period == 0)
-    p.y += (row->height - p.h) / 2;
-  else if (period == -2)
-    {
-      p.h = fringe_bitmaps[which].height;
-      p.y += (row->visible_height - p.h);
-    }
-
-  FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p);
-}
-
-/* Draw fringe bitmaps for glyph row ROW on window W.  Call this
-   function with input blocked.  */
-
-void
-draw_row_fringe_bitmaps (w, row)
-     struct window *w;
-     struct glyph_row *row;
-{
-  xassert (interrupt_input_blocked);
-
-  /* If row is completely invisible, because of vscrolling, we
-     don't have to draw anything.  */
-  if (row->visible_height <= 0)
-    return;
-
-  if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
-    draw_fringe_bitmap (w, row, 1);
-
-  if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
-    draw_fringe_bitmap (w, row, 0);
-}
-
-/* Draw the fringes of window W.  Only fringes for rows marked for
-   update in redraw_fringe_bitmaps_p are drawn.  */
-
-void
-draw_window_fringes (w)
-     struct window *w;
-{
-  struct glyph_row *row;
-  int yb = window_text_bottom_y (w);
-  int nrows = w->current_matrix->nrows;
-  int y = 0, rn;
-
-  if (w->pseudo_window_p)
-    return;
-
-  for (y = 0, rn = 0, row = w->current_matrix->rows;
-       y < yb && rn < nrows;
-       y += row->height, ++row, ++rn)
-    {
-      if (!row->redraw_fringe_bitmaps_p)
-       continue;
-      draw_row_fringe_bitmaps (w, row);
-      row->redraw_fringe_bitmaps_p = 0;
-    }
-}
-
-
-/* Compute actual fringe widths for frame F.  
-
-   If REDRAW is 1, redraw F if the fringe settings was actually
-   modified and F is visible.
-
-   Since the combined left and right fringe must occupy an integral
-   number of columns, we may need to add some pixels to each fringe.
-   Typically, we add an equal amount (+/- 1 pixel) to each fringe,
-   but a negative width value is taken literally (after negating it).
-
-   We never make the fringes narrower than specified.  It is planned
-   to make fringe bitmaps customizable and expandable, and at that
-   time, the user will typically specify the minimum number of pixels
-   needed for his bitmaps, so we shouldn't select anything less than
-   what is specified.
-*/
-
-void
-compute_fringe_widths (f, redraw)
-     struct frame *f;
-     int redraw;
-{
-  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);
-  int left_fringe_width, right_fringe_width;
-
-  if (!NILP (left_fringe))
-    left_fringe = Fcdr (left_fringe);
-  if (!NILP (right_fringe))
-    right_fringe = Fcdr (right_fringe);
-
-  left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
-                      XINT (left_fringe));
-  right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
-                       XINT (right_fringe));
-
-  if (left_fringe_width || right_fringe_width)
-    {
-      int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
-      int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
-      int conf_wid = left_wid + right_wid;
-      int font_wid = 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)
-       {
-         if (left_fringe_width < 0)
-           {
-             /* Left fringe width is fixed, adjust right fringe if necessary */
-             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_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
-             FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid;
-           }
-         else
-           {
-             /* Adjust both fringes with an equal amount.
-                Note that we are doing integer arithmetic here, so don't
-                lose a pixel if the total width is an odd number.  */
-             int fill = real_wid - conf_wid;
-             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_LEFT_FRINGE_WIDTH (f) = real_wid;
-         FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
-       }
-      else
-       {
-         FRAME_LEFT_FRINGE_WIDTH (f) = 0;
-         FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
-       }
-      FRAME_FRINGE_COLS (f) = cols;
-    }
-  else
-    {
-      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_LEFT_FRINGE_WIDTH (f) ||
-       o_right != FRAME_RIGHT_FRINGE_WIDTH (f) ||
-       o_cols != FRAME_FRINGE_COLS (f))
-      redraw_frame (f);
-}
-
-#endif /* HAVE_WINDOW_SYSTEM */
-
-
-\f
 /************************************************************************
                         Horizontal scrolling
  ************************************************************************/
@@ -9558,7 +9122,10 @@ 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)
+               hscroll = max (0, (it.current_x
+                                  - (ITERATOR_AT_END_OF_LINE_P (&it)
+                                     ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
+                                     : (text_area_width / 2))))
                          / FRAME_COLUMN_WIDTH (it.f);
              else if (w->cursor.x >= text_area_width - h_margin)
                {
@@ -9767,76 +9334,223 @@ redisplay ()
 }
 
 
-/* Return 1 if point moved out of or into a composition.  Otherwise
-   return 0.  PREV_BUF and PREV_PT are the last point buffer and
-   position.  BUF and PT are the current point buffer and position.  */
+static Lisp_Object
+overlay_arrow_string_or_property (var, pbitmap)
+     Lisp_Object var;
+     int *pbitmap;
+{
+  Lisp_Object pstr = Fget (var, Qoverlay_arrow_string);
+  Lisp_Object bitmap;
 
-int
-check_point_in_composition (prev_buf, prev_pt, buf, pt)
-     struct buffer *prev_buf, *buf;
-     int prev_pt, pt;
+  if (pbitmap)
+    {
+      *pbitmap = 0;
+      if (bitmap  = Fget (var, Qoverlay_arrow_bitmap), INTEGERP (bitmap))
+       *pbitmap = XINT (bitmap);
+    }
+
+  if (!NILP (pstr))
+    return pstr;
+  return Voverlay_arrow_string;
+}
+
+/* Return 1 if there are any overlay-arrows in current_buffer.  */
+static int
+overlay_arrow_in_current_buffer_p ()
 {
-  int start, end;
-  Lisp_Object prop;
-  Lisp_Object buffer;
+  Lisp_Object vlist;
 
-  XSETBUFFER (buffer, buf);
-  /* Check a composition at the last point if point moved within the
-     same buffer.  */
-  if (prev_buf == buf)
+  for (vlist = Voverlay_arrow_variable_list;
+       CONSP (vlist);
+       vlist = XCDR (vlist))
     {
-      if (prev_pt == pt)
-       /* Point didn't move.  */
-       return 0;
+      Lisp_Object var = XCAR (vlist);
+      Lisp_Object val;
 
-      if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
-         && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
-         && COMPOSITION_VALID_P (start, end, prop)
-         && start < prev_pt && end > prev_pt)
-       /* The last point was within the composition.  Return 1 iff
-            point moved out of the composition.  */
-       return (pt <= start || pt >= end);
+      if (!SYMBOLP (var))
+       continue;
+      val = find_symbol_value (var);
+      if (MARKERP (val)
+         && current_buffer == XMARKER (val)->buffer)
+       return 1;
     }
-
-  /* Check a composition at the current point.  */
-  return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
-         && find_composition (pt, -1, &start, &end, &prop, buffer)
-         && COMPOSITION_VALID_P (start, end, prop)
-         && start < pt && end > pt);
+  return 0;
 }
 
 
-/* Reconsider the setting of B->clip_changed which is displayed
-   in window W.  */
+/* Return 1 if any overlay_arrows have moved or overlay-arrow-string
+   has changed.  */
 
-static INLINE void
-reconsider_clip_changes (w, b)
-     struct window *w;
-     struct buffer *b;
+static int
+overlay_arrows_changed_p ()
 {
-  if (b->clip_changed
-          && !NILP (w->window_end_valid)
-          && w->current_matrix->buffer == b
-          && w->current_matrix->zv == BUF_ZV (b)
-          && w->current_matrix->begv == BUF_BEGV (b))
-    b->clip_changed = 0;
+  Lisp_Object vlist;
 
-  /* If display wasn't paused, and W is not a tool bar window, see if
-     point has been moved into or out of a composition.  In that case,
-     we set b->clip_changed to 1 to force updating the screen.  If
-     b->clip_changed has already been set to 1, we can skip this
-     check.  */
-  if (!b->clip_changed
-      && BUFFERP (w->buffer) && !NILP (w->window_end_valid))
+  for (vlist = Voverlay_arrow_variable_list;
+       CONSP (vlist);
+       vlist = XCDR (vlist))
     {
-      int pt;
-
-      if (w == XWINDOW (selected_window))
-       pt = BUF_PT (current_buffer);
-      else
-       pt = marker_position (w->pointm);
+      Lisp_Object var = XCAR (vlist);
+      Lisp_Object val, pstr;
 
-      if ((w->current_matrix->buffer != XBUFFER (w->buffer)
+      if (!SYMBOLP (var))
+       continue;
+      val = find_symbol_value (var);
+      if (!MARKERP (val))
+       continue;
+      if (! EQ (COERCE_MARKER (val),
+               Fget (var, Qlast_arrow_position))
+         || ! (pstr = overlay_arrow_string_or_property (var, 0),
+               EQ (pstr, Fget (var, Qlast_arrow_string))))
+       return 1;
+    }
+  return 0;
+}
+
+/* Mark overlay arrows to be updated on next redisplay.  */
+
+static void
+update_overlay_arrows (up_to_date)
+     int up_to_date;
+{
+  Lisp_Object vlist;
+
+  for (vlist = Voverlay_arrow_variable_list;
+       CONSP (vlist);
+       vlist = XCDR (vlist))
+    {
+      Lisp_Object var = XCAR (vlist);
+
+      if (!SYMBOLP (var))
+       continue;
+
+      if (up_to_date > 0)
+       {
+         Lisp_Object val = find_symbol_value (var);
+         Fput (var, Qlast_arrow_position,
+               COERCE_MARKER (val));
+         Fput (var, Qlast_arrow_string,
+               overlay_arrow_string_or_property (var, 0));
+       }
+      else if (up_to_date < 0
+              || !NILP (Fget (var, Qlast_arrow_position)))
+       {
+         Fput (var, Qlast_arrow_position, Qt);
+         Fput (var, Qlast_arrow_string, Qt);
+       }
+    }
+}
+
+
+/* Return overlay arrow string at row, or nil.  */
+
+static Lisp_Object
+overlay_arrow_at_row (f, row, pbitmap)
+     struct frame *f;
+     struct glyph_row *row;
+     int *pbitmap;
+{
+  Lisp_Object vlist;
+
+  for (vlist = Voverlay_arrow_variable_list;
+       CONSP (vlist);
+       vlist = XCDR (vlist))
+    {
+      Lisp_Object var = XCAR (vlist);
+      Lisp_Object val;
+
+      if (!SYMBOLP (var))
+       continue;
+
+      val = find_symbol_value (var);
+
+      if (MARKERP (val)
+         && current_buffer == XMARKER (val)->buffer
+         && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
+       {
+         val = overlay_arrow_string_or_property (var, pbitmap);
+         if (FRAME_WINDOW_P (f))
+           return Qt;
+         else if (STRINGP (val))
+           return val;
+         break;
+       }
+    }
+
+  *pbitmap = 0;
+  return Qnil;
+}
+
+/* Return 1 if point moved out of or into a composition.  Otherwise
+   return 0.  PREV_BUF and PREV_PT are the last point buffer and
+   position.  BUF and PT are the current point buffer and position.  */
+
+int
+check_point_in_composition (prev_buf, prev_pt, buf, pt)
+     struct buffer *prev_buf, *buf;
+     int prev_pt, pt;
+{
+  int start, end;
+  Lisp_Object prop;
+  Lisp_Object buffer;
+
+  XSETBUFFER (buffer, buf);
+  /* Check a composition at the last point if point moved within the
+     same buffer.  */
+  if (prev_buf == buf)
+    {
+      if (prev_pt == pt)
+       /* Point didn't move.  */
+       return 0;
+
+      if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
+         && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
+         && COMPOSITION_VALID_P (start, end, prop)
+         && start < prev_pt && end > prev_pt)
+       /* The last point was within the composition.  Return 1 iff
+            point moved out of the composition.  */
+       return (pt <= start || pt >= end);
+    }
+
+  /* Check a composition at the current point.  */
+  return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
+         && find_composition (pt, -1, &start, &end, &prop, buffer)
+         && COMPOSITION_VALID_P (start, end, prop)
+         && start < pt && end > pt);
+}
+
+
+/* Reconsider the setting of B->clip_changed which is displayed
+   in window W.  */
+
+static INLINE void
+reconsider_clip_changes (w, b)
+     struct window *w;
+     struct buffer *b;
+{
+  if (b->clip_changed
+          && !NILP (w->window_end_valid)
+          && w->current_matrix->buffer == b
+          && w->current_matrix->zv == BUF_ZV (b)
+          && w->current_matrix->begv == BUF_BEGV (b))
+    b->clip_changed = 0;
+
+  /* If display wasn't paused, and W is not a tool bar window, see if
+     point has been moved into or out of a composition.  In that case,
+     we set b->clip_changed to 1 to force updating the screen.  If
+     b->clip_changed has already been set to 1, we can skip this
+     check.  */
+  if (!b->clip_changed
+      && BUFFERP (w->buffer) && !NILP (w->window_end_valid))
+    {
+      int pt;
+
+      if (w == XWINDOW (selected_window))
+       pt = BUF_PT (current_buffer);
+      else
+       pt = marker_position (w->pointm);
+
+      if ((w->current_matrix->buffer != XBUFFER (w->buffer)
           || pt != XINT (w->last_point))
          && check_point_in_composition (w->current_matrix->buffer,
                                         XINT (w->last_point),
@@ -10046,8 +9760,7 @@ redisplay_internal (preserve_echo_area)
 
   /* If specs for an arrow have changed, do thorough redisplay
      to ensure we remove any arrow that should no longer exist.  */
-  if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position)
-      || ! EQ (Voverlay_arrow_string, last_arrow_string))
+  if (overlay_arrows_changed_p ())
     consider_all_windows_p = windows_or_buffers_changed = 1;
 
   /* Normally the message* functions will have already displayed and
@@ -10507,11 +10220,7 @@ redisplay_internal (preserve_echo_area)
       CHARPOS (this_line_start_pos) = 0;
 
       /* Let the overlay arrow be updated the next time.  */
-      if (!NILP (last_arrow_position))
-       {
-         last_arrow_position = Qt;
-         last_arrow_string = Qt;
-       }
+      update_overlay_arrows (0);
 
       /* If we pause after scrolling, some rows in the current
         matrices of some windows are not valid.  */
@@ -10527,8 +10236,8 @@ redisplay_internal (preserve_echo_area)
             consider_all_windows_p is set.  */
          mark_window_display_accurate_1 (w, 1);
 
-         last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
-         last_arrow_string = Voverlay_arrow_string;
+         /* Say overlay arrows are up to date.  */
+         update_overlay_arrows (1);
 
          if (FRAME_DISPLAY (sf)->frame_up_to_date_hook != 0)
            FRAME_DISPLAY (sf)->frame_up_to_date_hook (sf);
@@ -10724,16 +10433,14 @@ mark_window_display_accurate (window, accurate_p)
 
   if (accurate_p)
     {
-      last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
-      last_arrow_string = Voverlay_arrow_string;
+      update_overlay_arrows (1);
     }
   else
     {
       /* Force a thorough redisplay the next time by setting
         last_arrow_position and last_arrow_string to t, which is
         unequal to any useful value of Voverlay_arrow_...  */
-      last_arrow_position = Qt;
-      last_arrow_string = Qt;
+      update_overlay_arrows (-1);
     }
 }
 
@@ -11023,12 +10730,17 @@ run_window_scroll_functions (window, startp)
    A value of 1 means there is nothing to be done.
    (Either the line is fully visible, or it cannot be made so,
    or we cannot tell.)
+
+   If FORCE_P is non-zero, return 0 even if partial visible cursor row
+   is higher than window.
+
    A value of 0 means the caller should do scrolling
    as if point had gone off the screen.  */
 
 static int
-make_cursor_line_fully_visible (w)
+make_cursor_line_fully_visible (w, force_p)
      struct window *w;
+     int force_p;
 {
   struct glyph_matrix *matrix;
   struct glyph_row *row;
@@ -11046,6 +10758,9 @@ make_cursor_line_fully_visible (w)
   if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
     return 1;
 
+  if (force_p)
+    return 0;
+
   /* If the row the cursor is in is taller than the window's height,
      it's not clear what to do, so do nothing.  */
   window_height = window_box_height (w);
@@ -11142,7 +10857,7 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
   int amount_to_scroll = 0;
   Lisp_Object aggressive;
   int height;
-  int end_scroll_margin;
+  int extra_scroll_margin_lines = last_line_misfit ? 1 : 0;
 
 #if GLYPH_DEBUG
   debug_method_add (w, "try_scrolling");
@@ -11160,6 +10875,12 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
   else
     this_scroll_margin = 0;
 
+  /* Force scroll_conservatively to have a reasonable value so it doesn't
+     cause an overflow while computing how much to scroll.  */
+  if (scroll_conservatively)
+    scroll_conservatively = min (scroll_conservatively,
+                                 MOST_POSITIVE_FIXNUM / FRAME_LINE_HEIGHT (f));
+
   /* Compute how much we should try to scroll maximally to bring point
      into view.  */
   if (scroll_step || scroll_conservatively || temp_scroll_step)
@@ -11185,11 +10906,13 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
   CHARPOS (scroll_margin_pos) = XINT (window_end);
   BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
 
-  end_scroll_margin = this_scroll_margin + !!last_line_misfit;
-  if (end_scroll_margin)
+  if (this_scroll_margin || extra_scroll_margin_lines)
     {
       start_display (&it, w, scroll_margin_pos);
-      move_it_vertically (&it, - end_scroll_margin);
+      if (this_scroll_margin)
+       move_it_vertically (&it, - this_scroll_margin);
+      if (extra_scroll_margin_lines)
+       move_it_by_lines (&it, - extra_scroll_margin_lines, 0);
       scroll_margin_pos = it.current.pos;
     }
 
@@ -11324,10 +11047,10 @@ try_scrolling (window, just_this_one_p, scroll_conservatively,
 
       /* If cursor ends up on a partially visible line,
         treat that as being off the bottom of the screen.  */
-      if (! make_cursor_line_fully_visible (w))
+      if (! make_cursor_line_fully_visible (w, extra_scroll_margin_lines <= 1))
        {
          clear_glyph_matrix (w->desired_matrix);
-         last_line_misfit = 1;
+         ++extra_scroll_margin_lines;
          goto too_near_end;
        }
       rc = SCROLLING_SUCCESS;
@@ -11484,8 +11207,7 @@ try_cursor_movement (window, startp, scroll_step)
       && INTEGERP (w->window_end_vpos)
       && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
       && (FRAME_WINDOW_P (f)
-         || !MARKERP (Voverlay_arrow_position)
-         || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
+         || !overlay_arrow_in_current_buffer_p ()))
     {
       int this_scroll_margin;
       struct glyph_row *row = NULL;
@@ -11617,7 +11339,7 @@ try_cursor_movement (window, startp, scroll_step)
              else
                {
                  set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
-                 if (!make_cursor_line_fully_visible (w))
+                 if (!make_cursor_line_fully_visible (w, 0))
                    rc = CURSOR_MOVEMENT_MUST_SCROLL;
                  else
                    rc = CURSOR_MOVEMENT_SUCCESS;
@@ -11647,7 +11369,7 @@ set_vertical_scroll_bar (w)
      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)
@@ -11659,7 +11381,7 @@ set_vertical_scroll_bar (w)
       /* 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))
@@ -11674,136 +11396,6 @@ set_vertical_scroll_bar (w)
       (w, end - start, whole, start);
 }
 
-#ifdef HAVE_WINDOW_SYSTEM
-
-/* Recalculate the bitmaps to show in the fringes of window W.
-   If FORCE_P is 0, only mark rows with modified bitmaps for update in
-   redraw_fringe_bitmaps_p; else mark all rows for update.  */
-
-int
-update_window_fringes (w, force_p)
-     struct window *w;
-     int force_p;
-{
-  struct glyph_row *row, *cur = 0;
-  int yb = window_text_bottom_y (w);
-  int rn, nrows = w->current_matrix->nrows;
-  int y;
-  int redraw_p = 0;
-  Lisp_Object ind;
-
-  if (w->pseudo_window_p)
-    return 0;
-
-  if (!MINI_WINDOW_P (w)
-      && (ind = XBUFFER (w->buffer)->indicate_buffer_boundaries, !NILP (ind)))
-    {
-      int do_eob = 1, do_bob = 1;
-
-      for (y = 0, rn = 0;
-          y < yb && rn < nrows;
-          y += row->height, ++rn)
-       {
-         unsigned indicate_bob_p, indicate_top_line_p;
-         unsigned indicate_eob_p, indicate_bottom_line_p;
-         
-         row = w->desired_matrix->rows + rn;
-         if (!row->enabled_p)
-           row = w->current_matrix->rows + rn;
-
-         indicate_bob_p = row->indicate_bob_p;
-         indicate_top_line_p = row->indicate_top_line_p;
-         indicate_eob_p = row->indicate_eob_p;
-         indicate_bottom_line_p = row->indicate_bottom_line_p;
-         
-         row->indicate_bob_p = row->indicate_top_line_p = 0;
-         row->indicate_eob_p = row->indicate_bottom_line_p = 0;
-
-         if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer)))
-           row->indicate_bob_p = do_bob, do_bob = 0;
-         else if (EQ (ind, Qt)
-                  && (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0) == rn)
-           row->indicate_top_line_p = 1;
-
-         if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer)))
-           row->indicate_eob_p = do_eob, do_eob = 0;
-         else if (EQ (ind, Qt)
-                  && y + row->height >= yb)
-           row->indicate_bottom_line_p = 1;
-
-         if (indicate_bob_p != row->indicate_bob_p
-             || indicate_top_line_p != row->indicate_top_line_p
-             || indicate_eob_p != row->indicate_eob_p
-             || indicate_bottom_line_p != row->indicate_bottom_line_p)
-           row->redraw_fringe_bitmaps_p = 1;
-       }
-    }
-
-  for (y = 0, rn = 0;
-       y < yb && rn < nrows;
-       y += row->height, rn++)
-    {
-      enum fringe_bitmap_type left, right;
-
-      row = w->desired_matrix->rows + rn;
-      cur = w->current_matrix->rows + rn;
-      if (!row->enabled_p)
-       row = cur;
-
-      /* Decide which bitmap to draw in the left fringe.  */
-      if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
-       left = NO_FRINGE_BITMAP;
-      else if (row->overlay_arrow_p)
-       left = OVERLAY_ARROW_BITMAP;
-      else if (row->truncated_on_left_p)
-       left = LEFT_TRUNCATION_BITMAP;
-      else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
-       left = CONTINUATION_LINE_BITMAP;
-      else if (row->indicate_empty_line_p)
-       left = ZV_LINE_BITMAP;
-      else if (row->indicate_bob_p)
-       left = FIRST_LINE_BITMAP;
-      else
-       left = NO_FRINGE_BITMAP;
-
-      /* Decide which bitmap to draw in the right fringe.  */
-      if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
-       right = NO_FRINGE_BITMAP;
-      else if (row->truncated_on_right_p)
-       right = RIGHT_TRUNCATION_BITMAP;
-      else if (row->continued_p)
-       right = CONTINUED_LINE_BITMAP;
-      else if (row->indicate_eob_p)
-       right = LAST_LINE_BITMAP;
-      else if (row->indicate_top_line_p) 
-       right = UP_ARROW_BITMAP;
-      else if (row->indicate_bottom_line_p)
-       right = DOWN_ARROW_BITMAP;
-      else if (row->indicate_empty_line_p && WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
-       right = ZV_LINE_BITMAP;
-      else
-       right = NO_FRINGE_BITMAP;
-
-      if (force_p
-         || row->y != cur->y
-         || row->visible_height != cur->visible_height
-         || left != cur->left_fringe_bitmap
-         || right != cur->right_fringe_bitmap
-         || cur->redraw_fringe_bitmaps_p)
-       {
-         redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1;
-         cur->left_fringe_bitmap = left;
-         cur->right_fringe_bitmap = right;
-       }
-
-      row->left_fringe_bitmap = left;
-      row->right_fringe_bitmap = right;
-    }
-
-  return redraw_p;
-}
-
-#endif /* HAVE_WINDOW_SYSTEM */
 
 /* Redisplay leaf window WINDOW.  JUST_THIS_ONE_P non-zero means only
    selected_window is redisplayed.
@@ -12080,7 +11672,7 @@ redisplay_window (window, just_this_one_p)
          new_vpos = window_box_height (w) / 2;
        }
 
-      if (!make_cursor_line_fully_visible (w))
+      if (!make_cursor_line_fully_visible (w, 0))
        {
          /* Point does appear, but on a line partly visible at end of window.
             Move it back to a fully-visible line.  */
@@ -12217,7 +11809,7 @@ redisplay_window (window, just_this_one_p)
            /* Forget any recorded base line for line number display.  */
            w->base_line_number = Qnil;
 
-         if (!make_cursor_line_fully_visible (w))
+         if (!make_cursor_line_fully_visible (w, 1))
            {
              clear_glyph_matrix (w->desired_matrix);
              last_line_misfit = 1;
@@ -12377,7 +11969,7 @@ redisplay_window (window, just_this_one_p)
       set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
     }
 
-  if (!make_cursor_line_fully_visible (w))
+  if (!make_cursor_line_fully_visible (w, centering_position > 0))
     {
       /* If vscroll is enabled, disable it and try again.  */
       if (w->vscroll)
@@ -12390,6 +11982,7 @@ redisplay_window (window, just_this_one_p)
       /* If centering point failed to make the whole line visible,
         put point at the top instead.  That has to make the whole line
         visible, if it can be done.  */
+      clear_glyph_matrix (w->desired_matrix);
       centering_position = 0;
       goto point_at_top;
     }
@@ -12494,6 +12087,7 @@ redisplay_window (window, just_this_one_p)
 
 #ifdef HAVE_WINDOW_SYSTEM
   if (update_window_fringes (w, 0)
+      && !just_this_one_p
       && (used_current_matrix_p || overlay_arrow_seen)
       && !w->pseudo_window_p)
     {
@@ -13366,8 +12960,7 @@ try_window_id (w)
     GIVE_UP (10);
 
   /* Can use this if overlay arrow position and or string have changed.  */
-  if (!EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
-      || !EQ (last_arrow_string, Voverlay_arrow_string))
+  if (overlay_arrows_changed_p ())
     GIVE_UP (12);
 
 
@@ -13760,36 +13353,36 @@ try_window_id (w)
            {
              /* Scroll last_unchanged_at_beg_row to the end of the
                 window down dvpos lines.  */
-             set_terminal_window (end);
+             set_terminal_window (f, end);
 
              /* On dumb terminals delete dvpos lines at the end
                 before inserting dvpos empty lines.  */
              if (!FRAME_SCROLL_REGION_OK (f))
-               ins_del_lines (end - dvpos, -dvpos);
+               ins_del_lines (f, end - dvpos, -dvpos);
 
              /* Insert dvpos empty lines in front of
                  last_unchanged_at_beg_row.  */
-             ins_del_lines (from, dvpos);
+             ins_del_lines (f, from, dvpos);
            }
          else if (dvpos < 0)
            {
              /* Scroll up last_unchanged_at_beg_vpos to the end of
                 the window to last_unchanged_at_beg_vpos - |dvpos|.  */
-             set_terminal_window (end);
+             set_terminal_window (f, end);
 
              /* Delete dvpos lines in front of
                 last_unchanged_at_beg_vpos.  ins_del_lines will set
                 the cursor to the given vpos and emit |dvpos| delete
                 line sequences.  */
-             ins_del_lines (from + dvpos, dvpos);
+             ins_del_lines (f, from + dvpos, dvpos);
 
              /* On a dumb terminal insert dvpos empty lines at the
                  end.  */
              if (!FRAME_SCROLL_REGION_OK (f))
-               ins_del_lines (end + dvpos, -dvpos);
+               ins_del_lines (f, end + dvpos, -dvpos);
            }
 
-         set_terminal_window (0);
+         set_terminal_window (f, 0);
        }
 
       update_end (f);
@@ -14304,14 +13897,15 @@ usage: (trace-to-stderr STRING &rest OBJECTS)  */)
    arrow.  Only used for non-window-redisplay windows.  */
 
 static struct glyph_row *
-get_overlay_arrow_glyph_row (w)
+get_overlay_arrow_glyph_row (w, overlay_arrow_string)
      struct window *w;
+     Lisp_Object overlay_arrow_string;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   struct buffer *buffer = XBUFFER (w->buffer);
   struct buffer *old = current_buffer;
-  const unsigned char *arrow_string = SDATA (Voverlay_arrow_string);
-  int arrow_len = SCHARS (Voverlay_arrow_string);
+  const unsigned char *arrow_string = SDATA (overlay_arrow_string);
+  int arrow_len = SCHARS (overlay_arrow_string);
   const unsigned char *arrow_end = arrow_string + arrow_len;
   const unsigned char *p;
   struct it it;
@@ -14338,7 +13932,7 @@ get_overlay_arrow_glyph_row (w)
 
       /* Get its face.  */
       ilisp = make_number (p - arrow_string);
-      face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
+      face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
       it.face_id = compute_char_face (f, it.c, face);
 
       /* Compute its width, get its glyphs.  */
@@ -14777,6 +14371,8 @@ display_line (it)
      struct it *it;
 {
   struct glyph_row *row = it->glyph_row;
+  int overlay_arrow_bitmap;
+  Lisp_Object overlay_arrow_string;
 
   /* We always start displaying at hpos zero even if hscrolled.  */
   xassert (it->hpos == 0 && it->current_x == 0);
@@ -14835,6 +14431,11 @@ display_line (it)
             display the cursor there under X.  Set the charpos of the
             first glyph of blank lines not corresponding to any text
             to -1.  */
+#ifdef HAVE_WINDOW_SYSTEM
+         if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
+           row->exact_window_width_line_p = 1;
+         else
+#endif /* HAVE_WINDOW_SYSTEM */
          if ((append_space (it, 1) && row->used[TEXT_AREA] == 1)
              || row->used[TEXT_AREA] == 0)
            {
@@ -14947,8 +14548,14 @@ display_line (it)
 #ifdef HAVE_WINDOW_SYSTEM
                          if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
                            {
-                             get_next_display_element (it);
-                             if (ITERATOR_AT_END_OF_LINE_P (it))
+                             if (!get_next_display_element (it))
+                               {
+                                 row->exact_window_width_line_p = 1;
+                                 it->continuation_lines_width = 0;
+                                 row->continued_p = 0;
+                                 row->ends_at_zv_p = 1;
+                               }
+                             else if (ITERATOR_AT_END_OF_LINE_P (it))
                                {
                                  row->continued_p = 0;
                                  row->exact_window_width_line_p = 1;
@@ -15053,7 +14660,7 @@ display_line (it)
                                  it->max_phys_ascent + it->max_phys_descent);
 
          /* End of this display line if row is continued.  */
-         if (row->continued_p)
+         if (row->continued_p || row->ends_at_zv_p)
            break;
        }
 
@@ -15119,7 +14726,15 @@ display_line (it)
              /* Don't truncate if we can overflow newline into fringe.  */
              if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
                {
-                 get_next_display_element (it);
+                 if (!get_next_display_element (it))
+                   {
+#ifdef HAVE_WINDOW_SYSTEM
+                     it->continuation_lines_width = 0;
+                     row->ends_at_zv_p = 1;
+                     row->exact_window_width_line_p = 1;
+                     break;
+#endif /* HAVE_WINDOW_SYSTEM */
+                   }
                  if (ITERATOR_AT_END_OF_LINE_P (it))
                    {
                      row->exact_window_width_line_p = 1;
@@ -15153,17 +14768,16 @@ display_line (it)
      mark this glyph row as the one containing the overlay arrow.
      This is clearly a mess with variable size fonts.  It would be
      better to let it be displayed like cursors under X.  */
-  if (MARKERP (Voverlay_arrow_position)
-      && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
-      && (MATRIX_ROW_START_CHARPOS (row)
-         == marker_position (Voverlay_arrow_position))
-      && STRINGP (Voverlay_arrow_string)
-      && ! overlay_arrow_seen)
+  if (! overlay_arrow_seen
+      && (overlay_arrow_string
+           = overlay_arrow_at_row (it->f, row, &overlay_arrow_bitmap),
+         !NILP (overlay_arrow_string)))
     {
       /* Overlay arrow in window redisplay is a fringe bitmap.  */
       if (!FRAME_WINDOW_P (it->f))
        {
-         struct glyph_row *arrow_row = get_overlay_arrow_glyph_row (it->w);
+         struct glyph_row *arrow_row
+           = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
          struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
          struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
          struct glyph *p = row->glyphs[TEXT_AREA];
@@ -15187,6 +14801,7 @@ display_line (it)
        }
 
       overlay_arrow_seen = 1;
+      it->w->overlay_arrow_bitmap = overlay_arrow_bitmap;
       row->overlay_arrow_p = 1;
     }
 
@@ -15196,6 +14811,17 @@ display_line (it)
   /* Remember the position at which this line ends.  */
   row->end = it->current;
 
+  /* Save fringe bitmaps in this row.  */
+  row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
+  row->left_user_fringe_face_id = it->left_user_fringe_face_id;
+  row->right_user_fringe_bitmap = it->right_user_fringe_bitmap;
+  row->right_user_fringe_face_id = it->right_user_fringe_face_id;
+
+  it->left_user_fringe_bitmap = 0;
+  it->left_user_fringe_face_id = 0;
+  it->right_user_fringe_bitmap = 0;
+  it->right_user_fringe_face_id = 0;
+
   /* Maybe set the cursor.  */
   if (it->w->cursor.vpos < 0
       && PT >= MATRIX_ROW_START_CHARPOS (row)
@@ -15459,6 +15085,8 @@ display_mode_line (w, face_id, format)
   init_iterator (&it, w, -1, -1, NULL, face_id);
   prepare_desired_row (it.glyph_row);
 
+  it.glyph_row->mode_line_p = 1;
+
   if (! mode_line_inverse_video)
     /* Force the mode-line to be displayed in the default face.  */
     it.base_face_id = it.face_id = DEFAULT_FACE_ID;
@@ -15475,7 +15103,6 @@ display_mode_line (w, face_id, format)
 
   compute_line_metrics (&it);
   it.glyph_row->full_width_p = 1;
-  it.glyph_row->mode_line_p = 1;
   it.glyph_row->continued_p = 0;
   it.glyph_row->truncated_on_left_p = 0;
   it.glyph_row->truncated_on_right_p = 0;
@@ -16675,14 +16302,6 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
       return "T";
 #endif
 
-    case 'T':
-      /* %T is the frame name on a termcap frame, the empty string otherwise. */
-      if (! FRAME_TERMCAP_P (f))
-        return "";
-      if (!NILP (f->title))
-       return (char *) SDATA (f->title);
-      return (char *) SDATA (f->name);
-
     case 'z':
       /* coding-system (not including end-of-line format) */
     case 'Z':
@@ -17097,56 +16716,302 @@ invisible_p (propval, list)
   return 0;
 }
 
-\f
-/***********************************************************************
-                            Glyph Display
- ***********************************************************************/
+/* Calculate a width or height in pixels from a specification using
+   the following elements:
 
-#ifdef HAVE_WINDOW_SYSTEM
+   SPEC ::=
+     NUM      - a (fractional) multiple of the default font width/height
+     (NUM)    - specifies exactly NUM pixels
+     UNIT     - a fixed number of pixels, see below.
+     ELEMENT  - size of a display element in pixels, see below.
+     (NUM . SPEC) - equals NUM * SPEC
+     (+ SPEC SPEC ...)  - add pixel values
+     (- SPEC SPEC ...)  - subtract pixel values
+     (- SPEC)           - negate pixel value
 
-#if GLYPH_DEBUG
+   NUM ::=
+     INT or FLOAT   - a number constant
+     SYMBOL         - use symbol's (buffer local) variable binding.
 
-void
-dump_glyph_string (s)
-     struct glyph_string *s;
-{
-  fprintf (stderr, "glyph string\n");
-  fprintf (stderr, "  x, y, w, h = %d, %d, %d, %d\n",
-          s->x, s->y, s->width, s->height);
-  fprintf (stderr, "  ybase = %d\n", s->ybase);
-  fprintf (stderr, "  hl = %d\n", s->hl);
-  fprintf (stderr, "  left overhang = %d, right = %d\n",
-          s->left_overhang, s->right_overhang);
-  fprintf (stderr, "  nchars = %d\n", s->nchars);
-  fprintf (stderr, "  extends to end of line = %d\n",
-          s->extends_to_end_of_line_p);
-  fprintf (stderr, "  font height = %d\n", FONT_HEIGHT (s->font));
-  fprintf (stderr, "  bg width = %d\n", s->background_width);
-}
+   UNIT ::=
+     in       - pixels per inch  *)
+     mm       - pixels per 1/1000 meter  *)
+     cm       - pixels per 1/100 meter   *)
+     width    - width of current font in pixels.
+     height   - height of current font in pixels.
 
-#endif /* GLYPH_DEBUG */
+     *) using the ratio(s) defined in display-pixels-per-inch.
 
-/* Initialize glyph string S.  CHAR2B is a suitably allocated vector
-   of XChar2b structures for S; it can't be allocated in
-   init_glyph_string because it must be allocated via `alloca'.  W
-   is the window on which S is drawn.  ROW and AREA are the glyph row
-   and area within the row from which S is constructed.  START is the
-   index of the first glyph structure covered by S.  HL is a
-   face-override for drawing S.  */
+   ELEMENT ::=
 
-#ifdef HAVE_NTGUI
-#define OPTIONAL_HDC(hdc)  hdc,
-#define DECLARE_HDC(hdc)   HDC hdc;
-#define ALLOCATE_HDC(hdc, f) hdc = get_frame_dc ((f))
-#define RELEASE_HDC(hdc, f)  release_frame_dc ((f), (hdc))
-#endif
+     left-fringe          - left fringe width in pixels
+     right-fringe         - right fringe width in pixels
 
-#ifndef OPTIONAL_HDC
-#define OPTIONAL_HDC(hdc)
-#define DECLARE_HDC(hdc)
-#define ALLOCATE_HDC(hdc, f)
-#define RELEASE_HDC(hdc, f)
-#endif
+     left-margin          - left margin width in pixels
+     right-margin         - right margin width in pixels
+
+     scroll-bar           - scroll-bar area width in pixels
+
+   Examples:
+
+   Pixels corresponding to 5 inches:
+     (5 . in)
+
+   Total width of non-text areas on left side of window (if scroll-bar is on left):
+     '(space :width (+ left-fringe left-margin scroll-bar))
+
+   Align to first text column (in header line):
+     '(space :align-to 0)
+
+   Align to middle of text area minus half the width of variable `my-image'
+   containing a loaded image:
+     '(space :align-to (0.5 . (- text my-image)))
+
+   Width of left margin minus width of 1 character in the default font:
+     '(space :width (- left-margin 1))
+
+   Width of left margin minus width of 2 characters in the current font:
+     '(space :width (- left-margin (2 . width)))
+
+   Center 1 character over left-margin (in header line):
+     '(space :align-to (+ left-margin (0.5 . left-margin) -0.5))
+
+   Different ways to express width of left fringe plus left margin minus one pixel:
+     '(space :width (- (+ left-fringe left-margin) (1)))
+     '(space :width (+ left-fringe left-margin (- (1))))
+     '(space :width (+ left-fringe left-margin (-1)))
+
+*/
+
+#define NUMVAL(X)                              \
+     ((INTEGERP (X) || FLOATP (X))             \
+      ? XFLOATINT (X)                          \
+      : - 1)
+
+int
+calc_pixel_width_or_height (res, it, prop, font, width_p, align_to)
+     double *res;
+     struct it *it;
+     Lisp_Object prop;
+     void *font;
+     int width_p, *align_to;
+{
+  double pixels;
+
+#define OK_PIXELS(val) ((*res = (double)(val)), 1)
+#define OK_ALIGN_TO(val) ((*align_to = (int)(val)), 1)
+
+  if (NILP (prop))
+    return OK_PIXELS (0);
+
+  if (SYMBOLP (prop))
+    {
+      if (SCHARS (SYMBOL_NAME (prop)) == 2)
+       {
+         char *unit =  SDATA (SYMBOL_NAME (prop));
+
+         if (unit[0] == 'i' && unit[1] == 'n')
+           pixels = 1.0;
+         else if (unit[0] == 'm' && unit[1] == 'm')
+           pixels = 25.4;
+         else if (unit[0] == 'c' && unit[1] == 'm')
+           pixels = 2.54;
+         else
+           pixels = 0;
+         if (pixels > 0)
+           {
+             double ppi;
+             if ((ppi = NUMVAL (Vdisplay_pixels_per_inch), ppi > 0)
+                 || (CONSP (Vdisplay_pixels_per_inch)
+                     && (ppi = (width_p
+                                ? NUMVAL (XCAR (Vdisplay_pixels_per_inch))
+                                : NUMVAL (XCDR (Vdisplay_pixels_per_inch))),
+                         ppi > 0)))
+               return OK_PIXELS (ppi / pixels);
+
+             return 0;
+           }
+       }
+
+#ifdef HAVE_WINDOW_SYSTEM
+      if (EQ (prop, Qheight))
+       return OK_PIXELS (font ? FONT_HEIGHT ((XFontStruct *)font) : FRAME_LINE_HEIGHT (it->f));
+      if (EQ (prop, Qwidth))
+       return OK_PIXELS (font ? FONT_WIDTH ((XFontStruct *)font) : FRAME_COLUMN_WIDTH (it->f));
+#else
+      if (EQ (prop, Qheight) || EQ (prop, Qwidth))
+       return OK_PIXELS (1);
+#endif
+
+      if (EQ (prop, Qtext))
+         return OK_PIXELS (width_p
+                           ? window_box_width (it->w, TEXT_AREA)
+                           : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
+
+      if (align_to && *align_to < 0)
+       {
+         *res = 0;
+         if (EQ (prop, Qleft))
+           return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA));
+         if (EQ (prop, Qright))
+           return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
+         if (EQ (prop, Qcenter))
+           return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
+                               + window_box_width (it->w, TEXT_AREA) / 2);
+         if (EQ (prop, Qleft_fringe))
+           return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
+                               ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
+                               : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
+         if (EQ (prop, Qright_fringe))
+           return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
+                               ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
+                               : window_box_right_offset (it->w, TEXT_AREA));
+         if (EQ (prop, Qleft_margin))
+           return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
+         if (EQ (prop, Qright_margin))
+           return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
+         if (EQ (prop, Qscroll_bar))
+           return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
+                               ? 0
+                               : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
+                                  + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
+                                     ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+                                     : 0)));
+       }
+      else
+       {
+         if (EQ (prop, Qleft_fringe))
+           return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
+         if (EQ (prop, Qright_fringe))
+           return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
+         if (EQ (prop, Qleft_margin))
+           return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
+         if (EQ (prop, Qright_margin))
+           return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
+         if (EQ (prop, Qscroll_bar))
+           return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
+       }
+
+      prop = Fbuffer_local_value (prop, it->w->buffer);
+    }
+
+  if (INTEGERP (prop) || FLOATP (prop))
+    {
+      int base_unit = (width_p
+                      ? FRAME_COLUMN_WIDTH (it->f)
+                      : FRAME_LINE_HEIGHT (it->f));
+      return OK_PIXELS (XFLOATINT (prop) * base_unit);
+    }
+
+  if (CONSP (prop))
+    {
+      Lisp_Object car = XCAR (prop);
+      Lisp_Object cdr = XCDR (prop);
+
+      if (SYMBOLP (car))
+       {
+#ifdef HAVE_WINDOW_SYSTEM
+         if (valid_image_p (prop))
+           {
+             int id = lookup_image (it->f, prop);
+             struct image *img = IMAGE_FROM_ID (it->f, id);
+
+             return OK_PIXELS (width_p ? img->width : img->height);
+           }
+#endif
+         if (EQ (car, Qplus) || EQ (car, Qminus))
+           {
+             int first = 1;
+             double px;
+
+             pixels = 0;
+             while (CONSP (cdr))
+               {
+                 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
+                                                  font, width_p, align_to))
+                   return 0;
+                 if (first)
+                   pixels = (EQ (car, Qplus) ? px : -px), first = 0;
+                 else
+                   pixels += px;
+                 cdr = XCDR (cdr);
+               }
+             if (EQ (car, Qminus))
+               pixels = -pixels;
+             return OK_PIXELS (pixels);
+           }
+
+         car = Fbuffer_local_value (car, it->w->buffer);
+       }
+
+      if (INTEGERP (car) || FLOATP (car))
+       {
+         double fact;
+         pixels = XFLOATINT (car);
+         if (NILP (cdr))
+           return OK_PIXELS (pixels);
+         if (calc_pixel_width_or_height (&fact, it, cdr,
+                                         font, width_p, align_to))
+           return OK_PIXELS (pixels * fact);
+         return 0;
+       }
+
+      return 0;
+    }
+
+  return 0;
+}
+
+\f
+/***********************************************************************
+                            Glyph Display
+ ***********************************************************************/
+
+#ifdef HAVE_WINDOW_SYSTEM
+
+#if GLYPH_DEBUG
+
+void
+dump_glyph_string (s)
+     struct glyph_string *s;
+{
+  fprintf (stderr, "glyph string\n");
+  fprintf (stderr, "  x, y, w, h = %d, %d, %d, %d\n",
+          s->x, s->y, s->width, s->height);
+  fprintf (stderr, "  ybase = %d\n", s->ybase);
+  fprintf (stderr, "  hl = %d\n", s->hl);
+  fprintf (stderr, "  left overhang = %d, right = %d\n",
+          s->left_overhang, s->right_overhang);
+  fprintf (stderr, "  nchars = %d\n", s->nchars);
+  fprintf (stderr, "  extends to end of line = %d\n",
+          s->extends_to_end_of_line_p);
+  fprintf (stderr, "  font height = %d\n", FONT_HEIGHT (s->font));
+  fprintf (stderr, "  bg width = %d\n", s->background_width);
+}
+
+#endif /* GLYPH_DEBUG */
+
+/* Initialize glyph string S.  CHAR2B is a suitably allocated vector
+   of XChar2b structures for S; it can't be allocated in
+   init_glyph_string because it must be allocated via `alloca'.  W
+   is the window on which S is drawn.  ROW and AREA are the glyph row
+   and area within the row from which S is constructed.  START is the
+   index of the first glyph structure covered by S.  HL is a
+   face-override for drawing S.  */
+
+#ifdef HAVE_NTGUI
+#define OPTIONAL_HDC(hdc)  hdc,
+#define DECLARE_HDC(hdc)   HDC hdc;
+#define ALLOCATE_HDC(hdc, f) hdc = get_frame_dc ((f))
+#define RELEASE_HDC(hdc, f)  release_frame_dc ((f), (hdc))
+#endif
+
+#ifndef OPTIONAL_HDC
+#define OPTIONAL_HDC(hdc)
+#define DECLARE_HDC(hdc)
+#define ALLOCATE_HDC(hdc, f)
+#define RELEASE_HDC(hdc, f)
+#endif
 
 static void
 init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl)
@@ -18258,17 +18123,34 @@ produce_image_glyph (it)
   xassert (it->what == IT_IMAGE);
 
   face = FACE_FROM_ID (it->f, it->face_id);
+  xassert (face);
+  /* Make sure X resources of the face is loaded.  */
+  PREPARE_FACE_FOR_DISPLAY (it->f, face);
+
+  if (it->image_id < 0)
+    {
+      /* Fringe bitmap.  */
+      it->ascent = it->phys_ascent = 0;
+      it->descent = it->phys_descent = 0;
+      it->pixel_width = 0;
+      it->nglyphs = 0;
+      return;
+    }
+
   img = IMAGE_FROM_ID (it->f, it->image_id);
   xassert (img);
-
-  /* Make sure X resources of the face and image are loaded.  */
-  PREPARE_FACE_FOR_DISPLAY (it->f, face);
+  /* Make sure X resources of the image is loaded.  */
   prepare_image_for_display (it->f, img);
 
   it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face);
   it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
   it->pixel_width = img->width + 2 * img->hmargin;
 
+  /* It's quite possible for images to have an ascent greater than
+     their height, so don't get confused in that case.  */
+  if (it->descent < 0)
+    it->descent = 0;
+
   /* If this glyph is alone on the last line, adjust it.ascent to minimum row ascent.  */
   face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f);
   if (face_ascent > it->ascent)
@@ -18363,209 +18245,6 @@ append_stretch_glyph (it, object, width, height, ascent)
 }
 
 
-/* Calculate a width or height in pixels from a specification using
-   the following elements:
-
-   SPEC ::= 
-     NUM      - a (fractional) multiple of the default font width/height
-     (NUM)    - specifies exactly NUM pixels
-     UNIT     - a fixed number of pixels, see below.
-     ELEMENT  - size of a display element in pixels, see below.
-     (NUM . SPEC) - equals NUM * SPEC
-     (+ SPEC SPEC ...)  - add pixel values
-     (- SPEC SPEC ...)  - subtract pixel values
-     (- SPEC)           - negate pixel value
-
-   NUM ::= 
-     INT or FLOAT   - a number constant
-     SYMBOL         - use symbol's (buffer local) variable binding.
-
-   UNIT ::=
-     in       - pixels per inch  *)
-     mm       - pixels per 1/1000 meter  *)
-     cm       - pixels per 1/100 meter   *)
-     width    - width of current font in pixels.
-     height   - height of current font in pixels.
-
-     *) using the ratio(s) defined in display-pixels-per-inch.
-
-   ELEMENT ::=
-
-     left-fringe         - left fringe width in pixels
-     (left-fringe . nil) - left fringe width if inside margins, else 0
-     (left-fringe . t)   - left fringe width if outside margins, else 0
-
-     right-fringe         - right fringe width in pixels
-     (right-fringe . nil) - right fringe width if inside margins, else 0
-     (right-fringe . t)   - right fringe width if outside margins, else 0
-
-     left-margin          - left margin width in pixels
-     right-margin         - right margin width in pixels
-
-     scroll-bar           - scroll-bar area width in pixels
-     (scroll-bar . left)  - scroll-bar width if on left, else 0
-     (scroll-bar . right) - scroll-bar width if on right, else 0
-
-   Examples:
-
-   Pixels corresponding to 5 inches:
-     (5 . in)     
-               
-   Total width of non-text areas on left side of window:
-     (+ left-fringe left-margin (scroll-bar . left))
-
-   Total width of fringes if inside display margins:
-     (+ (left-fringe) (right-fringe))
-
-   Width of left margin minus width of 1 character in the default font:
-     (- left-margin 1)
-
-   Width of left margin minus width of 2 characters in the current font:
-     (- left-margin (2 . width))
-
-   Width of left fringe plus left margin minus one pixel:
-     (- (+ left-fringe left-margin) (1))
-     (+ left-fringe left-margin (- (1)))
-     (+ left-fringe left-margin (-1))
-
-*/
-
-#define NUMVAL(X)                              \
-     ((INTEGERP (X) || FLOATP (X))             \
-      ? XFLOATINT (X)                          \
-      : - 1)
-
-static int
-calc_pixel_width_or_height (res, it, prop, font, width_p)
-     double *res;
-     struct it *it;
-     Lisp_Object prop;
-     XFontStruct *font;
-     int width_p;
-{
-  double pixels;
-
-#define OK_PIXELS(val) ((*res = (val)), 1)
-
-  if (SYMBOLP (prop))
-    {
-      if (SCHARS (SYMBOL_NAME (prop)) == 2)
-       {
-         char *unit =  SDATA (SYMBOL_NAME (prop));
-
-         if (unit[0] == 'i' && unit[1] == 'n')
-           pixels = 1.0;
-         else if (unit[0] == 'm' && unit[1] == 'm')
-           pixels = 25.4;
-         else if (unit[0] == 'c' && unit[1] == 'm')
-           pixels = 2.54;
-         else
-           pixels = 0;
-         if (pixels > 0)
-           {
-             double ppi;
-             if ((ppi = NUMVAL (Vdisplay_pixels_per_inch), ppi > 0)
-                 || (CONSP (Vdisplay_pixels_per_inch)
-                     && (ppi = (width_p
-                                ? NUMVAL (XCAR (Vdisplay_pixels_per_inch))
-                                : NUMVAL (XCDR (Vdisplay_pixels_per_inch))),
-                         ppi > 0)))
-               return OK_PIXELS (ppi / pixels);
-
-             return 0;
-           }
-       }
-
-      if (EQ (prop, Qheight))
-       return OK_PIXELS (font ? FONT_HEIGHT (font) : FRAME_LINE_HEIGHT (it->f));
-      if (EQ (prop, Qwidth))
-       return OK_PIXELS (font ? FONT_WIDTH (font) : FRAME_COLUMN_WIDTH (it->f));
-      if (EQ (prop, Qleft_fringe))
-       return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
-      if (EQ (prop, Qright_fringe))
-       return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
-      if (EQ (prop, Qleft_margin))
-       return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
-      if (EQ (prop, Qright_margin))
-       return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
-      if (EQ (prop, Qscroll_bar))
-       return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
-
-      prop = Fbuffer_local_value (prop, it->w->buffer);
-    }
-
-  if (INTEGERP (prop) || FLOATP (prop))
-    {
-      int base_unit = (width_p
-                      ? FRAME_COLUMN_WIDTH (it->f)
-                      : FRAME_LINE_HEIGHT (it->f));
-      return OK_PIXELS (XFLOATINT (prop) * base_unit);
-    }
-
-  if (CONSP (prop))
-    {
-      Lisp_Object car = XCAR (prop);
-      Lisp_Object cdr = XCDR (prop);
-
-      if (SYMBOLP (car))
-       {
-         if (EQ (car, Qplus) || EQ (car, Qminus))
-           {
-             int first = 1;
-             double px;
-
-             pixels = 0;
-             while (CONSP (cdr))
-               {
-                 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr), font, width_p))
-                   return 0;
-                 if (first)
-                   pixels = (EQ (car, Qplus) ? px : -px), first = 0;
-                 else
-                   pixels += px;
-                 cdr = XCDR (cdr);
-               }
-             if (EQ (car, Qminus))
-               pixels = -pixels;
-             return OK_PIXELS (pixels);
-           }
-
-         if (EQ (car, Qleft_fringe))
-           return OK_PIXELS ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
-                              == !NILP (cdr))
-                             ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
-                             : 0);
-         if (EQ (car, Qright_fringe))
-           return OK_PIXELS ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
-                              == !NILP (cdr))
-                             ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
-                             : 0);
-         if (EQ (car, Qscroll_bar))
-           return OK_PIXELS ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
-                               == EQ (cdr, Qleft))
-                              ? WINDOW_SCROLL_BAR_AREA_WIDTH (it->w)
-                              : 0);
-
-         car = Fbuffer_local_value (car, it->w->buffer);
-       }
-
-      if (INTEGERP (car) || FLOATP (car))
-       {
-         double fact;
-         pixels = XFLOATINT (car);
-         if (NILP (cdr))
-           return OK_PIXELS (pixels);
-         if (calc_pixel_width_or_height (&fact, it, cdr, font, width_p))
-           return OK_PIXELS (pixels * fact);
-         return 0;
-       }
-
-      return 0;
-    }
-
-  return 0;
-}
-
 /* Produce a stretch glyph for iterator IT.  IT->object is the value
    of the glyph property displayed.  The value must be a list
    `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
@@ -18603,7 +18282,7 @@ produce_stretch_glyph (it)
 {
   /* (space :width WIDTH :height HEIGHT ...)  */
   Lisp_Object prop, plist;
-  int width = 0, height = 0;
+  int width = 0, height = 0, align_to = -1;
   int zero_width_ok_p = 0, zero_height_ok_p = 0;
   int ascent = 0;
   double tem;
@@ -18618,7 +18297,7 @@ produce_stretch_glyph (it)
 
   /* Compute the width of the stretch.  */
   if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
-      && calc_pixel_width_or_height (&tem, it, prop, font, 1))
+      && calc_pixel_width_or_height (&tem, it, prop, font, 1, 0))
     {
       /* Absolute width `:width WIDTH' specified and valid.  */
       zero_width_ok_p = 1;
@@ -18649,9 +18328,15 @@ produce_stretch_glyph (it)
       width = NUMVAL (prop) * it2.pixel_width;
     }
   else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
-          && calc_pixel_width_or_height (&tem, it, prop, font, 1))
-    {
-      width = max (0, (int)tem - it->current_x);
+          && calc_pixel_width_or_height (&tem, it, prop, font, 1, &align_to))
+    {
+      if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
+       align_to = (align_to < 0
+                   ? 0
+                   : align_to - window_box_left_offset (it->w, TEXT_AREA));
+      else if (align_to < 0)
+       align_to = window_box_left_offset (it->w, TEXT_AREA);
+      width = max (0, (int)tem + align_to - it->current_x);
       zero_width_ok_p = 1;
     }
   else
@@ -18663,7 +18348,7 @@ produce_stretch_glyph (it)
 
   /* Compute height.  */
   if ((prop = Fplist_get (plist, QCheight), !NILP (prop))
-      && calc_pixel_width_or_height (&tem, it, prop, font, 0))
+      && calc_pixel_width_or_height (&tem, it, prop, font, 0, 0))
     {
       height = (int)tem;
       zero_height_ok_p = 1;
@@ -18684,7 +18369,7 @@ produce_stretch_glyph (it)
       NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
     ascent = height * NUMVAL (prop) / 100.0;
   else if (!NILP (prop)
-          && calc_pixel_width_or_height (&tem, it, prop, font, 0))
+          && calc_pixel_width_or_height (&tem, it, prop, font, 0, 0))
     ascent = min (max (0, (int)tem), height);
   else
     ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
@@ -19615,7 +19300,7 @@ get_window_cursor_type (w, glyph, width, active_cursor)
   /* Use normal cursor if not blinked off.  */
   if (!w->cursor_off_p)
     {
-      if (glyph->type == IMAGE_GLYPH) {
+      if (glyph != NULL && glyph->type == IMAGE_GLYPH) {
        if (cursor_type == FILLED_BOX_CURSOR)
          cursor_type = HOLLOW_BOX_CURSOR;
       }
@@ -19932,7 +19617,6 @@ display_and_set_cursor (w, on, hpos, vpos, x, y)
   int new_cursor_type;
   int new_cursor_width;
   int active_cursor;
-  struct glyph_matrix *current_glyphs;
   struct glyph_row *glyph_row;
   struct glyph *glyph;
 
@@ -19950,10 +19634,7 @@ display_and_set_cursor (w, on, hpos, vpos, x, y)
   if (!on && !w->phys_cursor_on_p)
     return;
 
-  current_glyphs = w->current_matrix;
-  glyph_row = MATRIX_ROW (current_glyphs, vpos);
-  glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
-
+  glyph_row = MATRIX_ROW (w->current_matrix, vpos);
   /* If cursor row is not enabled, we don't really know where to
      display the cursor.  */
   if (!glyph_row->enabled_p)
@@ -19962,6 +19643,11 @@ display_and_set_cursor (w, on, hpos, vpos, x, y)
       return;
     }
 
+  glyph = NULL;
+  if (!glyph_row->exact_window_width_line_p
+      || hpos < glyph_row->used[TEXT_AREA])
+    glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
+
   xassert (interrupt_input_blocked);
 
   /* Set new_cursor_type to the cursor we want to be displayed.  */
@@ -20163,7 +19849,7 @@ clear_mouse_face (dpyinfo)
 {
   int cleared = 0;
 
-  if (!NILP (dpyinfo->mouse_face_window))
+  if (!dpyinfo->mouse_face_hidden && !NILP (dpyinfo->mouse_face_window))
     {
       show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
       cleared = 1;
@@ -20240,7 +19926,7 @@ fast_find_position (w, charpos, hpos, vpos, x, y, stop)
       if (charpos < MATRIX_ROW_START_CHARPOS (first))
        {
          *x = *y = *hpos = *vpos = 0;
-         return 0;
+         return 1;
        }
       else
        {
@@ -20280,7 +19966,7 @@ fast_find_position (w, charpos, hpos, vpos, x, y, stop)
     }
 
   *hpos = glyph - row->glyphs[TEXT_AREA];
-  return past_end;
+  return !past_end;
 }
 
 #else /* not 1 */
@@ -20528,7 +20214,7 @@ on_hot_spot_p (hot_spot, x, y)
          int x0, y0;
 
          /* Need an even number of coordinates, and at least 3 edges.  */
-         if (n < 6 || n & 1) 
+         if (n < 6 || n & 1)
            return 0;
 
          /* Count edge segments intersecting line from (X,Y) to (X,infinity).
@@ -20563,8 +20249,7 @@ on_hot_spot_p (hot_spot, x, y)
          return inside;
        }
     }
-  else
-    return 0;
+  return 0;
 }
 
 Lisp_Object
@@ -20579,13 +20264,13 @@ find_hot_spot (map, x, y)
        return XCAR (map);
       map = XCDR (map);
     }
-  
+
   return Qnil;
 }
 
 DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
        3, 3, 0,
-       doc: /* Lookup in image map MAP coordinates X and Y.  
+       doc: /* Lookup in image map MAP coordinates X and Y.
 An image map is an alist where each element has the format (AREA ID PLIST).
 An AREA is specified as either a rectangle, a circle, or a polygon:
 A rectangle is a cons (rect . ((x0 . y0) . (x1 . y1))) specifying the
@@ -20599,14 +20284,11 @@ Returns the alist element for the first matching AREA in MAP.  */)
      Lisp_Object map;
      Lisp_Object x, y;
 {
-  int ix, iy;
   if (NILP (map))
     return Qnil;
 
-  if (!INTEGERP (x))
-    wrong_type_argument (Qintegerp, x);
-  if (!INTEGERP (y))
-    wrong_type_argument (Qintegerp, y);
+  CHECK_NUMBER (x);
+  CHECK_NUMBER (y);
 
   return find_hot_spot (map, XINT (x), XINT (y));
 }
@@ -20667,7 +20349,7 @@ note_mode_line_or_margin_highlight (w, x, y, area)
   Lisp_Object pointer = Qnil;
   int charpos, dx, dy, width, height;
   Lisp_Object string, object = Qnil;
-  Lisp_Object pos, help, image;
+  Lisp_Object pos, help;
 
   if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
     string = mode_line_string (w, area, &x, &y, &charpos,
@@ -20735,7 +20417,7 @@ note_mode_line_or_margin_highlight (w, x, y, area)
        pointer = Fget_text_property (pos, Qpointer, string);
 
      /* Change the mouse pointer according to what is under X/Y.  */
-      if (NILP (pointer) && area == ON_MODE_LINE)
+      if (NILP (pointer) && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)))
        {
          Lisp_Object map;
          map = Fget_text_property (pos, Qlocal_map, string);
@@ -21461,13 +21143,13 @@ phys_cursor_in_rect_p (w, r)
   cursor_glyph = get_phys_cursor_glyph (w);
   if (cursor_glyph)
     {
-      /* r is relative to W's box, but w->phys_cursor.x is relative 
+      /* 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;
-      /* ++KFS: W32 version used W32-specific IntersectRect here, but 
+      /* ++KFS: W32 version used W32-specific IntersectRect here, but
         I assume the effect is the same -- and this is portable.  */
       return x_intersect_rectangles (&cr, r, &result);
     }
@@ -21487,7 +21169,7 @@ x_draw_vertical_border (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 :-( 
+     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
@@ -21911,6 +21593,8 @@ syms_of_xdisp ()
   staticpro (&Qleft_margin);
   Qright_margin = intern ("right-margin");
   staticpro (&Qright_margin);
+  Qcenter = intern ("center");
+  staticpro (&Qcenter);
   QCalign_to = intern (":align-to");
   staticpro (&QCalign_to);
   QCrelative_width = intern (":relative-width");
@@ -21976,13 +21660,20 @@ syms_of_xdisp ()
   Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces");
   staticpro (&Qinhibit_free_realized_faces);
 
-  list_of_error = Fcons (intern ("error"), Qnil);
+  list_of_error = Fcons (Fcons (intern ("error"),
+                               Fcons (intern ("void-variable"), Qnil)),
+                        Qnil);
   staticpro (&list_of_error);
 
-  last_arrow_position = Qnil;
-  last_arrow_string = Qnil;
-  staticpro (&last_arrow_position);
-  staticpro (&last_arrow_string);
+  Qlast_arrow_position = intern ("last-arrow-position");
+  staticpro (&Qlast_arrow_position);
+  Qlast_arrow_string = intern ("last-arrow-string");
+  staticpro (&Qlast_arrow_string);
+
+  Qoverlay_arrow_string = intern ("overlay-arrow-string");
+  staticpro (&Qoverlay_arrow_string);
+  Qoverlay_arrow_bitmap = intern ("overlay-arrow-bitmap");
+  staticpro (&Qoverlay_arrow_bitmap);
 
   echo_buffer[0] = echo_buffer[1] = Qnil;
   staticpro (&echo_buffer[0]);
@@ -22024,21 +21715,10 @@ wide as that tab on the display.  */);
 The face used for trailing whitespace is `trailing-whitespace'.  */);
   Vshow_trailing_whitespace = Qnil;
 
-#ifdef HAVE_WINDOW_SYSTEM
-  DEFVAR_LISP ("overflow-newline-into-fringe", &Voverflow_newline_into_fringe,
-    doc: /* *Non-nil means that newline may flow into the right fringe.
-This means that display lines which are exactly as wide as the window
-(not counting the final newline) will only occupy one screen line, by
-showing (or hiding) the final newline in the right fringe; when point
-is at the final newline, the cursor is shown in the right fringe.
-If nil, also continue lines which are exactly as wide as the window.  */);
-  Voverflow_newline_into_fringe = Qt;
-#endif
-
   DEFVAR_LISP ("void-text-area-pointer", &Vvoid_text_area_pointer,
     doc: /* *The pointer shape to show in void text areas.
 Nil means to show the text pointer.  Other options are `arrow', `text',
-`hand', `vdrag', `hdrag', `modeline', and `hourglass'.  */); 
+`hand', `vdrag', `hdrag', `modeline', and `hourglass'.  */);
   Vvoid_text_area_pointer = Qarrow;
 
   DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
@@ -22057,9 +21737,17 @@ See also `overlay-arrow-string'.  */);
   Voverlay_arrow_position = Qnil;
 
   DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
-    doc: /* String to display as an arrow.  See also `overlay-arrow-position'.  */);
+    doc: /* String to display as an arrow in non-window frames.
+See also `overlay-arrow-position'.  */);
   Voverlay_arrow_string = Qnil;
 
+  DEFVAR_LISP ("overlay-arrow-variable-list", &Voverlay_arrow_variable_list,
+    doc: /* List of variables (symbols) which hold markers for overlay arrows.
+The symbols on this list are examined during redisplay to determine
+where to display overlay arrows.  */);
+  Voverlay_arrow_variable_list
+    = Fcons (intern ("overlay-arrow-position"), Qnil);
+
   DEFVAR_INT ("scroll-step", &scroll_step,
     doc: /* *The number of lines to try scrolling a window by when point moves out.
 If that fails to bring point back on frame, point is centered instead.