]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
(CLEAR_IMAGE_CACHE_COUNT): New const.
[gnu-emacs] / src / xdisp.c
index 952c7110755d4fa8204927c97a383034b1a2b3bf..9c2d3c2554d4bc1cc73b16dd90ebedaad0635176 100644 (file)
@@ -1,6 +1,6 @@
 /* Display generation from window structure and buffer text.
-   Copyright (C) 1985,86,87,88,93,94,95,97,98,99,2000,01,02,03,04
-   Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997, 1998, 1999,
+     2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -318,6 +318,10 @@ extern Lisp_Object Qcursor;
 
 Lisp_Object Vshow_trailing_whitespace;
 
+/* Non-nil means escape non-break space and hyphens.  */
+
+Lisp_Object Vshow_nonbreak_escape;
+
 #ifdef HAVE_WINDOW_SYSTEM
 extern Lisp_Object Voverflow_newline_into_fringe;
 
@@ -345,7 +349,6 @@ Lisp_Object Qtrailing_whitespace;
 /* Name and number of the face used to highlight escape glyphs.  */
 
 Lisp_Object Qescape_glyph;
-int escape_glyph_face;
 
 /* The symbol `image' which is the car of the lists used to represent
    images in Lisp.  */
@@ -778,6 +781,13 @@ enum move_it_result
 #define CLEAR_FACE_CACHE_COUNT 500
 static int clear_face_cache_count;
 
+/* Similarly for the image cache.  */
+
+#ifdef HAVE_WINDOW_SYSTEM
+#define CLEAR_IMAGE_CACHE_COUNT        101
+static int clear_image_cache_count;
+#endif
+
 /* Record the previous terminal frame we displayed.  */
 
 static struct frame *previous_terminal_frame;
@@ -824,7 +834,6 @@ static char *decode_mode_spec_coding P_ ((Lisp_Object, char *, int));
 static int invisible_text_between_p P_ ((struct it *, int, int));
 #endif
 
-static int next_element_from_ellipsis P_ ((struct it *));
 static void pint2str P_ ((char *, int, int));
 static void pint2hrstr P_ ((char *, int, int));
 static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
@@ -861,7 +870,7 @@ 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_for_newline P_ ((struct it *, int));
-static int make_cursor_line_fully_visible P_ ((struct window *, int));
+static int cursor_row_fully_visible_p P_ ((struct window *, int, 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));
@@ -899,6 +908,7 @@ static void reseat_1 P_ ((struct it *, struct text_pos, int));
 static void back_to_previous_visible_line_start P_ ((struct it *));
 void reseat_at_previous_visible_line_start P_ ((struct it *));
 static void reseat_at_next_visible_line_start P_ ((struct it *, int));
+static int next_element_from_ellipsis P_ ((struct it *));
 static int next_element_from_display_vector P_ ((struct it *));
 static int next_element_from_string P_ ((struct it *));
 static int next_element_from_c_string P_ ((struct it *));
@@ -1240,28 +1250,31 @@ line_bottom_y (it)
 }
 
 
-/* Return 1 if position CHARPOS is visible in window W.  Set *FULLY to
-   1 if POS is visible and the line containing POS is fully visible.
+/* Return 1 if position CHARPOS is visible in window W.
+   If visible, set *X and *Y to pixel coordinates of top left corner.
+   Set *RTOP and *RBOT to pixel height of an invisible area of glyph at POS.
    EXACT_MODE_LINE_HEIGHTS_P non-zero means compute exact mode-line
    and header-lines heights.  */
 
 int
-pos_visible_p (w, charpos, fully, x, y, exact_mode_line_heights_p)
+pos_visible_p (w, charpos, x, y, rtop, rbot, exact_mode_line_heights_p)
      struct window *w;
-     int charpos, *fully, *x, *y, exact_mode_line_heights_p;
+     int charpos, *x, *y, *rtop, *rbot, exact_mode_line_heights_p;
 {
   struct it it;
   struct text_pos top;
-  int visible_p;
+  int visible_p = 0;
   struct buffer *old_buffer = NULL;
 
+  if (noninteractive)
+    return visible_p;
+
   if (XBUFFER (w->buffer) != current_buffer)
     {
       old_buffer = current_buffer;
       set_buffer_internal_1 (XBUFFER (w->buffer));
     }
 
-  *fully = visible_p = 0;
   SET_TEXT_POS_FROM_MARKER (top, w->start);
 
   /* Compute exact mode line heights, if requested.  */
@@ -1279,35 +1292,38 @@ pos_visible_p (w, charpos, fully, x, y, exact_mode_line_heights_p)
     }
 
   start_display (&it, w, top);
-  move_it_to (&it, charpos, 0, it.last_visible_y, -1,
-             MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+  move_it_to (&it, charpos, -1, it.last_visible_y, -1,
+             MOVE_TO_POS | MOVE_TO_Y);
 
   /* Note that we may overshoot because of invisible text.  */
   if (IT_CHARPOS (it) >= charpos)
     {
       int top_y = it.current_y;
-      int bottom_y = line_bottom_y (&it);
+      int bottom_y = (last_height = 0, line_bottom_y (&it));
       int window_top_y = WINDOW_HEADER_LINE_HEIGHT (w);
 
       if (top_y < window_top_y)
        visible_p = bottom_y > window_top_y;
       else if (top_y < it.last_visible_y)
-       {
          visible_p = 1;
-         *fully = bottom_y <= it.last_visible_y;
-       }
       if (visible_p && x)
        {
          *x = it.current_x;
-         *y = max (top_y + it.max_ascent - it.ascent, window_top_y);
+         *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
+         if (rtop)
+           {
+             *rtop = max (0, window_top_y - top_y);
+             *rbot = max (0, bottom_y - it.last_visible_y);
+           }
        }
     }
-  else if (it.current_y + it.max_ascent + it.max_descent > it.last_visible_y)
+  else
     {
       struct it it2;
 
       it2 = it;
-      move_it_by_lines (&it, 1, 0);
+      if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
+       move_it_by_lines (&it, 1, 0);
       if (charpos < IT_CHARPOS (it))
        {
          visible_p = 1;
@@ -1316,6 +1332,12 @@ pos_visible_p (w, charpos, fully, x, y, exact_mode_line_heights_p)
              move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
              *x = it2.current_x;
              *y = it2.current_y + it2.max_ascent - it2.ascent;
+             if (rtop)
+               {
+                 *rtop = max (0, -it2.current_y);
+                 *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
+                                  - it.last_visible_y));
+               }
            }
        }
     }
@@ -1773,6 +1795,24 @@ get_glyph_string_clip_rect (s, nr)
       r.height = s->row->visible_height;
     }
 
+  if (s->clip_head)
+    if (r.x < s->clip_head->x)
+      {
+       if (r.width >= s->clip_head->x - r.x)
+         r.width -= s->clip_head->x - r.x;
+       else
+         r.width = 0;
+       r.x = s->clip_head->x;
+      }
+  if (s->clip_tail)
+    if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
+      {
+       if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
+         r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
+       else
+         r.width = 0;
+      }
+
   /* If S draws overlapping rows, it's sufficient to use the top and
      bottom of the window for clipping because this glyph string
      intentionally draws over other lines.  */
@@ -1806,7 +1846,7 @@ get_glyph_string_clip_rect (s, nr)
   if (s->hl == DRAW_CURSOR)
     {
       struct glyph *glyph = s->first_glyph;
-      int height;
+      int height, max_y;
 
       if (s->x > r.x)
        {
@@ -1815,13 +1855,26 @@ get_glyph_string_clip_rect (s, nr)
        }
       r.width = min (r.width, glyph->pixel_width);
 
-      /* Don't draw cursor glyph taller than our actual glyph.  */
-      height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
-      if (height < r.height)
+      /* If r.y is below window bottom, ensure that we still see a cursor.  */
+      height = min (glyph->ascent + glyph->descent,
+                   min (FRAME_LINE_HEIGHT (s->f), s->row->visible_height));
+      max_y = window_text_bottom_y (s->w) - height;
+      max_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, max_y);
+      if (s->ybase - glyph->ascent > max_y)
        {
-         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);
+         r.y = max_y;
+         r.height = height;
+       }
+      else
+       {
+         /* Don't draw cursor glyph taller than our actual glyph.  */
+         height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
+         if (height < r.height)
+           {
+             max_y = r.y + r.height;
+             r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
+             r.height = min (max_y - r.y, height);
+           }
        }
     }
 
@@ -1832,6 +1885,64 @@ get_glyph_string_clip_rect (s, nr)
 #endif
 }
 
+
+/* EXPORT:
+   Return the position and height of the phys cursor in window W.
+   Set w->phys_cursor_width to width of phys cursor.
+*/
+
+int
+get_phys_cursor_geometry (w, row, glyph, heightp)
+     struct window *w;
+     struct glyph_row *row;
+     struct glyph *glyph;
+     int *heightp;
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  int x, y, wd, h, h0, y0;
+
+  /* Compute the width of the rectangle to draw.  If on a stretch
+     glyph, and `x-stretch-block-cursor' is nil, don't draw a
+     rectangle as wide as the glyph, but use a canonical character
+     width instead.  */
+  wd = glyph->pixel_width - 1;
+#ifdef HAVE_NTGUI
+  wd++; /* Why? */
+#endif
+  if (glyph->type == STRETCH_GLYPH
+      && !x_stretch_cursor_p)
+    wd = min (FRAME_COLUMN_WIDTH (f), wd);
+  w->phys_cursor_width = wd;
+
+  y = w->phys_cursor.y + row->ascent - glyph->ascent;
+
+  /* If y is below window bottom, ensure that we still see a cursor.  */
+  h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
+
+  h = max (h0, glyph->ascent + glyph->descent);
+  h0 = min (h0, glyph->ascent + glyph->descent);
+
+  y0 = WINDOW_HEADER_LINE_HEIGHT (w);
+  if (y < y0)
+    {
+      h = max (h - (y0 - y) + 1, h0);
+      y = y0 - 1;
+    }
+  else
+    {
+      y0 = window_text_bottom_y (w) - h0;
+      if (y > y0)
+       {
+         h += y - y0;
+         y = y0;
+       }
+    }
+
+  *heightp = h - 1;
+  return WINDOW_TO_FRAME_PIXEL_Y (w, y);
+}
+
+
 #endif /* HAVE_WINDOW_SYSTEM */
 
 \f
@@ -1941,7 +2052,7 @@ static void
 check_it (it)
      struct it *it;
 {
-  if (it->method == next_element_from_string)
+  if (it->method == GET_FROM_STRING)
     {
       xassert (STRINGP (it->string));
       xassert (IT_STRING_CHARPOS (*it) >= 0);
@@ -1949,7 +2060,7 @@ check_it (it)
   else
     {
       xassert (IT_STRING_CHARPOS (*it) < 0);
-      if (it->method == next_element_from_buffer)
+      if (it->method == GET_FROM_BUFFER)
        {
          /* Check that character and byte positions agree.  */
          xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
@@ -2434,7 +2545,10 @@ init_from_display_pos (it, w, pos)
      after-string.  */
   init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
 
-  for (i = 0; i < it->n_overlay_strings; ++i)
+  /* This only scans the current chunk -- it should scan all chunks.
+     However, OVERLAY_STRING_CHUNK_SIZE has been increased from 3 in 21.1
+     to 16 in 22.1 to make this a lesser problem.  */
+  for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
     {
       const char *s = SDATA (it->overlay_strings[i]);
       const char *e = s + SBYTES (it->overlay_strings[i]);
@@ -2459,7 +2573,7 @@ init_from_display_pos (it, w, pos)
         property for an image, the iterator will be set up for that
         image, and we have to undo that setup first before we can
         correct the overlay string index.  */
-      if (it->method == next_element_from_image)
+      if (it->method == GET_FROM_IMAGE)
        pop_it (it);
 
       /* We already have the first chunk of overlay strings in
@@ -2482,7 +2596,7 @@ init_from_display_pos (it, w, pos)
       it->string = it->overlay_strings[relative_index];
       xassert (STRINGP (it->string));
       it->current.string_pos = pos->string_pos;
-      it->method = next_element_from_string;
+      it->method = GET_FROM_STRING;
     }
 
 #if 0 /* This is bogus because POS not having an overlay string
@@ -2498,7 +2612,7 @@ init_from_display_pos (it, w, pos)
       while (it->sp)
        pop_it (it);
       it->current.overlay_string_index = -1;
-      it->method = next_element_from_buffer;
+      it->method = GET_FROM_BUFFER;
       if (CHARPOS (pos->pos) == ZV)
        it->overlay_strings_at_end_processed_p = 1;
     }
@@ -2612,7 +2726,7 @@ handle_stop (it)
        {
          /* Don't check for overlay strings below when set to deliver
             characters from a display vector.  */
-         if (it->method == next_element_from_display_vector)
+         if (it->method == GET_FROM_DISPLAY_VECTOR)
            handle_overlay_change_p = 0;
 
          /* Handle overlay changes.  */
@@ -3265,11 +3379,13 @@ setup_for_ellipsis (it, len)
 
   it->dpvec_char_len = len;
   it->current.dpvec_index = 0;
+  it->dpvec_face_id = -1;
 
   /* Remember the current face id in case glyphs specify faces.
      IT's face is restored in set_iterator_to_next.  */
   it->saved_face_id = it->face_id;
-  it->method = next_element_from_display_vector;
+  it->method = GET_FROM_DISPLAY_VECTOR;
+  it->ellipsis_p = 1;
 }
 
 
@@ -3633,7 +3749,7 @@ handle_single_display_spec (it, spec, object, position,
       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->method = GET_FROM_IMAGE;
       it->face_id = face_id;
 
       /* Say that we haven't consumed the characters with
@@ -3716,7 +3832,7 @@ handle_single_display_spec (it, spec, object, position,
          it->current.overlay_string_index = -1;
          IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
          it->end_charpos = it->string_nchars = SCHARS (it->string);
-         it->method = next_element_from_string;
+         it->method = GET_FROM_STRING;
          it->stop_charpos = 0;
          it->string_from_display_prop_p = 1;
          /* Say that we haven't consumed the characters with
@@ -3726,7 +3842,7 @@ handle_single_display_spec (it, spec, object, position,
        }
       else if (CONSP (value) && EQ (XCAR (value), Qspace))
        {
-         it->method = next_element_from_stretch;
+         it->method = GET_FROM_STRETCH;
          it->object = value;
          it->current.pos = it->position = start_pos;
        }
@@ -3737,7 +3853,7 @@ handle_single_display_spec (it, spec, object, position,
          it->image_id = lookup_image (it->f, value);
          it->position = start_pos;
          it->object = NILP (object) ? it->w->buffer : object;
-         it->method = next_element_from_image;
+         it->method = GET_FROM_IMAGE;
 
          /* Say that we haven't consumed the characters with
             `display' property yet.  The call to pop_it in
@@ -3993,7 +4109,7 @@ handle_composition_prop (it)
 
       if (id >= 0)
        {
-         it->method = next_element_from_composition;
+         it->method = GET_FROM_COMPOSITION;
          it->cmp_id = id;
          it->cmp_len = COMPOSITION_LENGTH (prop);
          /* For a terminal, draw only the first character of the
@@ -4068,7 +4184,7 @@ next_overlay_string (it)
       it->current.overlay_string_index = -1;
       SET_TEXT_POS (it->current.string_pos, -1, -1);
       it->n_overlay_strings = 0;
-      it->method = next_element_from_buffer;
+      it->method = GET_FROM_BUFFER;
 
       /* If we're at the end of the buffer, record that we have
         processed the overlay strings there already, so that
@@ -4097,7 +4213,7 @@ next_overlay_string (it)
       it->string = it->overlay_strings[i];
       it->multibyte_p = STRING_MULTIBYTE (it->string);
       SET_TEXT_POS (it->current.string_pos, 0, 0);
-      it->method = next_element_from_string;
+      it->method = GET_FROM_STRING;
       it->stop_charpos = 0;
     }
 
@@ -4362,13 +4478,13 @@ get_overlay_strings (it, charpos)
       xassert (STRINGP (it->string));
       it->end_charpos = SCHARS (it->string);
       it->multibyte_p = STRING_MULTIBYTE (it->string);
-      it->method = next_element_from_string;
+      it->method = GET_FROM_STRING;
     }
   else
     {
       it->string = Qnil;
       it->current.overlay_string_index = -1;
-      it->method = next_element_from_buffer;
+      it->method = GET_FROM_BUFFER;
     }
 
   CHECK_IT (it);
@@ -4568,51 +4684,57 @@ static void
 back_to_previous_visible_line_start (it)
      struct it *it;
 {
-  int visible_p = 0;
-
-  /* Go back one newline if not on BEGV already.  */
-  if (IT_CHARPOS (*it) > BEGV)
-    back_to_previous_line_start (it);
-
-  /* Move over lines that are invisible because of selective display
-     or text properties.  */
-  while (IT_CHARPOS (*it) > BEGV
-        && !visible_p)
+  while (IT_CHARPOS (*it) > BEGV)
     {
-      visible_p = 1;
+      back_to_previous_line_start (it);
+      if (IT_CHARPOS (*it) <= BEGV)
+       break;
 
       /* If selective > 0, then lines indented more than that values
         are invisible.  */
       if (it->selective > 0
          && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
                                (double) it->selective)) /* iftc */
-       visible_p = 0;
-      else
-       {
-         Lisp_Object prop;
+       continue;
 
-         /* Check the newline before point for invisibility.  */
-         prop = Fget_char_property (make_number (IT_CHARPOS (*it) - 1),
+      /* Check the newline before point for invisibility.  */
+      {
+       Lisp_Object prop;
+       prop = Fget_char_property (make_number (IT_CHARPOS (*it) - 1),
                                     Qinvisible, it->window);
-         if (TEXT_PROP_MEANS_INVISIBLE (prop))
-           visible_p = 0;
-       }
+       if (TEXT_PROP_MEANS_INVISIBLE (prop))
+         continue;
+      }
 
-#if 0
-      /* Commenting this out fixes the bug described in
-        http://www.math.ku.dk/~larsh/emacs/emacs-loops-on-large-images/test-case.txt.  */
-      if (visible_p)
+      /* If newline has a display property that replaces the newline with something
+        else (image or text), find start of overlay or interval and continue search
+        from that point.  */
+      if (IT_CHARPOS (*it) > BEGV)
        {
          struct it it2 = *it;
-
-         if (handle_display_prop (&it2) == HANDLED_RETURN)
-           visible_p = 0;
+         int pos;
+         int beg, end;
+         Lisp_Object val, overlay;
+
+         pos = --IT_CHARPOS (it2);
+         --IT_BYTEPOS (it2);
+         it2.sp = 0;
+         if (handle_display_prop (&it2) == HANDLED_RETURN
+             && !NILP (val = get_char_property_and_overlay
+                       (make_number (pos), Qdisplay, Qnil, &overlay))
+             && (OVERLAYP (overlay)
+                 ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay)))
+                 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
+           {
+             if (beg < BEGV)
+               beg = BEGV;
+             IT_CHARPOS (*it) = beg;
+             IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
+             continue;
+           }
        }
-#endif
 
-      /* Back one more newline if the current one is invisible.  */
-      if (!visible_p)
-       back_to_previous_line_start (it);
+      break;
     }
 
   xassert (IT_CHARPOS (*it) >= BEGV);
@@ -4744,7 +4866,7 @@ reseat_1 (it, pos, set_stop_p)
   IT_STRING_CHARPOS (*it) = -1;
   IT_STRING_BYTEPOS (*it) = -1;
   it->string = Qnil;
-  it->method = next_element_from_buffer;
+  it->method = GET_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
@@ -4810,7 +4932,7 @@ reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
       it->string = string;
       it->s = NULL;
       it->end_charpos = it->string_nchars = SCHARS (string);
-      it->method = next_element_from_string;
+      it->method = GET_FROM_STRING;
       it->current.string_pos = string_pos (charpos, string);
     }
   else
@@ -4832,7 +4954,7 @@ reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
          it->end_charpos = it->string_nchars = strlen (s);
        }
 
-      it->method = next_element_from_c_string;
+      it->method = GET_FROM_C_STRING;
     }
 
   /* PRECISION > 0 means don't return more than PRECISION characters
@@ -4863,6 +4985,20 @@ reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
                              Iteration
  ***********************************************************************/
 
+/* Map enum it_method value to corresponding next_element_from_* function.  */
+
+static int (* get_next_element[NUM_IT_METHODS]) P_ ((struct it *it)) =
+{
+  next_element_from_buffer,
+  next_element_from_display_vector,
+  next_element_from_composition,
+  next_element_from_string,
+  next_element_from_c_string,
+  next_element_from_image,
+  next_element_from_stretch
+};
+
+
 /* Load IT's display element fields with information about the next
    display element from the current position of IT.  Value is zero if
    end of buffer (or C string) is reached.  */
@@ -4878,7 +5014,7 @@ get_next_display_element (it)
   int success_p;
 
  get_next:
-  success_p = (*it->method) (it);
+  success_p = (*get_next_element[it->method]) (it);
 
   if (it->what == IT_CHARACTER)
     {
@@ -4910,8 +5046,10 @@ get_next_display_element (it)
                  it->dpvec = v->contents;
                  it->dpend = v->contents + v->size;
                  it->current.dpvec_index = 0;
+                 it->dpvec_face_id = -1;
                  it->saved_face_id = it->face_id;
-                 it->method = next_element_from_display_vector;
+                 it->method = GET_FROM_DISPLAY_VECTOR;
+                 it->ellipsis_p = 0;
                }
              else
                {
@@ -4936,15 +5074,15 @@ get_next_display_element (it)
          else if ((it->c < ' '
                    && (it->area != TEXT_AREA
                        /* In mode line, treat \n like other crl chars.  */
-                       || (it->c != '\n'
+                       || (it->c != '\t'
                            && it->glyph_row && it->glyph_row->mode_line_p)
                        || (it->c != '\n' && it->c != '\t')))
                   || (it->multibyte_p
                       ? ((it->c >= 127
                           && it->len == 1)
                          || !CHAR_PRINTABLE_P (it->c)
-                         || it->c == 0x8ad
-                         || it->c == 0x8a0)
+                         || (!NILP (Vshow_nonbreak_escape)
+                             && (it->c == 0x8ad || it->c == 0x8a0)))
                       : (it->c >= 127
                          && (!unibyte_display_via_language_environment
                              || it->c == unibyte_char_to_multibyte (it->c)))))
@@ -4956,79 +5094,87 @@ get_next_display_element (it)
                 display.  Then, set IT->dpvec to these glyphs.  */
              GLYPH g;
              int ctl_len;
-             int face_id = escape_glyph_face;
-
-             /* Find the face id if `escape-glyph' unless we recently did.  */
-             if (face_id < 0)
-               {
-                 Lisp_Object tem = Fget (Qescape_glyph, Qface);
-                 if (INTEGERP (tem))
-                   face_id = XINT (tem);
-                 else
-                   face_id = 0;
-                 /* If there's overflow, use 0 instead.  */
-                 if (FAST_GLYPH_FACE (FAST_MAKE_GLYPH (0, face_id)) != face_id)
-                   face_id = 0;
-                 escape_glyph_face = face_id;
-               }
+             int face_id, lface_id = 0 ;
+             GLYPH escape_glyph;
 
              if (it->c < 128 && it->ctl_arrow_p)
                {
+                 g = '^';           /* default glyph for Control */
                  /* Set IT->ctl_chars[0] to the glyph for `^'.  */
                  if (it->dp
                      && INTEGERP (DISP_CTRL_GLYPH (it->dp))
                      && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
-                   g = XINT (DISP_CTRL_GLYPH (it->dp));
+                   {
+                     g = XINT (DISP_CTRL_GLYPH (it->dp));
+                     lface_id = FAST_GLYPH_FACE (g);
+                   }
+                 if (lface_id)
+                   {
+                      g = FAST_GLYPH_CHAR (g);
+                      face_id = merge_faces (it->f, Qt, lface_id,
+                                             it->face_id);
+                   }
                  else
-                   g = FAST_MAKE_GLYPH ('^', face_id);
-                 XSETINT (it->ctl_chars[0], g);
+                   {
+                     /* Merge the escape-glyph face into the current face.  */
+                     face_id = merge_faces (it->f, Qescape_glyph, 0,
+                                            it->face_id);
+                   }
 
-                 g = FAST_MAKE_GLYPH (it->c ^ 0100, face_id);
+                 XSETINT (it->ctl_chars[0], g);
+                 g = it->c ^ 0100;
                  XSETINT (it->ctl_chars[1], g);
                  ctl_len = 2;
+                 goto display_control;
                }
-             else if (it->c == 0x8a0 || it->c == 0x8ad)
+
+             escape_glyph = '\\';    /* default for Octal display */
+             if (it->dp
+                 && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
+                 && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
                {
-                 /* Set IT->ctl_chars[0] to the glyph for `\\'.  */
-                 if (it->dp
-                     && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
-                     && GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (it->dp))))
-                   g = XINT (DISP_ESCAPE_GLYPH (it->dp));
-                 else
-                   g = FAST_MAKE_GLYPH ('\\', face_id);
-                 XSETINT (it->ctl_chars[0], g);
+                 escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
+                 lface_id = FAST_GLYPH_FACE (escape_glyph);
+               }
+             if (lface_id)
+               {
+                 escape_glyph = FAST_GLYPH_CHAR (escape_glyph);
+                 face_id = merge_faces (it->f, Qt, lface_id,
+                                        it->face_id);
+               }
+             else
+               {
+                 /* Merge the escape-glyph face into the current face.  */
+                 face_id = merge_faces (it->f, Qescape_glyph, 0,
+                                        it->face_id);
+               }
 
-                 g = FAST_MAKE_GLYPH (it->c == 0x8ad ? '-' : ' ', face_id);
+             if (it->c == 0x8a0 || it->c == 0x8ad)
+               {
+                 XSETINT (it->ctl_chars[0], escape_glyph);
+                 g = it->c == 0x8ad ? '-' : ' ';
                  XSETINT (it->ctl_chars[1], g);
                  ctl_len = 2;
+                 goto display_control;
                }
-             else
-               {
-                 unsigned char str[MAX_MULTIBYTE_LENGTH];
-                 int len;
-                 int i;
-                 GLYPH escape_glyph;
 
-                 /* Set IT->ctl_chars[0] to the glyph for `\\'.  */
-                 if (it->dp
-                     && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
-                     && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
-                   escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
-                 else
-                   escape_glyph = FAST_MAKE_GLYPH ('\\', face_id);
+             {
+               unsigned char str[MAX_MULTIBYTE_LENGTH];
+               int len;
+               int i;
 
-                 if (SINGLE_BYTE_CHAR_P (it->c))
-                   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.  */
+               /* Set IT->ctl_chars[0] to the glyph for `\\'.  */
+               if (SINGLE_BYTE_CHAR_P (it->c))
+                 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;
@@ -5037,31 +5183,31 @@ get_next_display_element (it)
                        }
                    }
 
-                 for (i = 0; i < len; i++)
-                   {
-                     XSETINT (it->ctl_chars[i * 4], escape_glyph);
-                     /* Insert three more glyphs into IT->ctl_chars for
-                        the octal display of the character.  */
-                     g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0',
-                                          face_id);
-                     XSETINT (it->ctl_chars[i * 4 + 1], g);
-                     g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0',
-                                          face_id);
-                     XSETINT (it->ctl_chars[i * 4 + 2], g);
-                     g = FAST_MAKE_GLYPH ((str[i] & 7) + '0',
-                                          face_id);
-                     XSETINT (it->ctl_chars[i * 4 + 3], g);
-                   }
-                 ctl_len = len * 4;
-               }
+               for (i = 0; i < len; i++)
+                 {
+                   XSETINT (it->ctl_chars[i * 4], escape_glyph);
+                   /* Insert three more glyphs into IT->ctl_chars for
+                      the octal display of the character.  */
+                   g = ((str[i] >> 6) & 7) + '0';
+                   XSETINT (it->ctl_chars[i * 4 + 1], g);
+                   g = ((str[i] >> 3) & 7) + '0';
+                   XSETINT (it->ctl_chars[i * 4 + 2], g);
+                   g = (str[i] & 7) + '0';
+                   XSETINT (it->ctl_chars[i * 4 + 3], g);
+                 }
+               ctl_len = len * 4;
+             }
 
+           display_control:
              /* Set up IT->dpvec and return first character from it.  */
              it->dpvec_char_len = it->len;
              it->dpvec = it->ctl_chars;
              it->dpend = it->dpvec + ctl_len;
              it->current.dpvec_index = 0;
+             it->dpvec_face_id = face_id;
              it->saved_face_id = it->face_id;
-             it->method = next_element_from_display_vector;
+             it->method = GET_FROM_DISPLAY_VECTOR;
+             it->ellipsis_p = 0;
              goto get_next;
            }
        }
@@ -5122,8 +5268,9 @@ set_iterator_to_next (it, reseat_p)
      moving the iterator to a new position might set them.  */
   it->start_of_box_run_p = it->end_of_box_run_p = 0;
 
-  if (it->method == next_element_from_buffer)
+  switch (it->method)
     {
+    case GET_FROM_BUFFER:
       /* The current display element of IT is a character from
         current_buffer.  Advance in the buffer, and maybe skip over
         invisible lines that are so because of selective display.  */
@@ -5136,32 +5283,32 @@ set_iterator_to_next (it, reseat_p)
          IT_CHARPOS (*it) += 1;
          xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
        }
-    }
-  else if (it->method == next_element_from_composition)
-    {
-      xassert (it->cmp_id >= 0 && it ->cmp_id < n_compositions);
+      break;
+
+    case GET_FROM_COMPOSITION:
+      xassert (it->cmp_id >= 0 && it->cmp_id < n_compositions);
       if (STRINGP (it->string))
        {
          IT_STRING_BYTEPOS (*it) += it->len;
          IT_STRING_CHARPOS (*it) += it->cmp_len;
-         it->method = next_element_from_string;
+         it->method = GET_FROM_STRING;
          goto consider_string_end;
        }
       else
        {
          IT_BYTEPOS (*it) += it->len;
          IT_CHARPOS (*it) += it->cmp_len;
-         it->method = next_element_from_buffer;
+         it->method = GET_FROM_BUFFER;
        }
-    }
-  else if (it->method == next_element_from_c_string)
-    {
+      break;
+
+    case GET_FROM_C_STRING:
       /* Current display element of IT is from a C string.  */
       IT_BYTEPOS (*it) += it->len;
       IT_CHARPOS (*it) += 1;
-    }
-  else if (it->method == next_element_from_display_vector)
-    {
+      break;
+
+    case GET_FROM_DISPLAY_VECTOR:
       /* Current display element of IT is from a display table entry.
         Advance in the display table definition.  Reset it to null if
         end reached, and continue with characters from buffers/
@@ -5175,18 +5322,15 @@ set_iterator_to_next (it, reseat_p)
       if (it->dpvec + it->current.dpvec_index == it->dpend)
        {
          if (it->s)
-           it->method = next_element_from_c_string;
+           it->method = GET_FROM_C_STRING;
          else if (STRINGP (it->string))
-           it->method = next_element_from_string;
+           it->method = GET_FROM_STRING;
          else
-           it->method = next_element_from_buffer;
+           it->method = GET_FROM_BUFFER;
 
          it->dpvec = NULL;
          it->current.dpvec_index = -1;
 
-         /* Recheck faces after display vector */
-         it->stop_charpos = 0;
-
          /* Skip over characters which were displayed via IT->dpvec.  */
          if (it->dpvec_char_len < 0)
            reseat_at_next_visible_line_start (it, 1);
@@ -5195,10 +5339,13 @@ set_iterator_to_next (it, reseat_p)
              it->len = it->dpvec_char_len;
              set_iterator_to_next (it, reseat_p);
            }
+
+         /* Recheck faces after display vector */
+         it->stop_charpos = IT_CHARPOS (*it);
        }
-    }
-  else if (it->method == next_element_from_string)
-    {
+      break;
+
+    case GET_FROM_STRING:
       /* Current display element is a character from a Lisp string.  */
       xassert (it->s == NULL && STRINGP (it->string));
       IT_STRING_BYTEPOS (*it) += it->len;
@@ -5223,34 +5370,35 @@ set_iterator_to_next (it, reseat_p)
              && it->sp > 0)
            {
              pop_it (it);
-             if (!STRINGP (it->string))
-               it->method = next_element_from_buffer;
-             else
+             if (STRINGP (it->string))
                goto consider_string_end;
+             it->method = GET_FROM_BUFFER;
            }
        }
-    }
-  else if (it->method == next_element_from_image
-          || it->method == next_element_from_stretch)
-    {
+      break;
+
+    case GET_FROM_IMAGE:
+    case GET_FROM_STRETCH:
       /* The position etc with which we have to proceed are on
         the stack.  The position may be at the end of a string,
          if the `display' property takes up the whole string.  */
+      xassert (it->sp > 0);
       pop_it (it);
       it->image_id = 0;
       if (STRINGP (it->string))
        {
-         it->method = next_element_from_string;
+         it->method = GET_FROM_STRING;
          goto consider_string_end;
        }
-      else
-       it->method = next_element_from_buffer;
+      it->method = GET_FROM_BUFFER;
+      break;
+
+    default:
+      /* There are no other methods defined, so this should be a bug.  */
+      abort ();
     }
-  else
-    /* There are no other methods defined, so this should be a bug.  */
-    abort ();
 
-  xassert (it->method != next_element_from_string
+  xassert (it->method != GET_FROM_STRING
           || (STRINGP (it->string)
               && IT_STRING_CHARPOS (*it) >= 0));
 }
@@ -5274,7 +5422,6 @@ next_element_from_display_vector (it)
   if (INTEGERP (*it->dpvec)
       && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
     {
-      int lface_id;
       GLYPH g;
 
       g = XFASTINT (it->dpvec[it->current.dpvec_index]);
@@ -5284,13 +5431,14 @@ next_element_from_display_vector (it)
       /* The entry may contain a face id to use.  Such a face id is
         the id of a Lisp face, not a realized face.  A face id of
         zero means no face is specified.  */
-      lface_id = FAST_GLYPH_FACE (g);
-      if (lface_id)
+      if (it->dpvec_face_id >= 0)
+       it->face_id = it->dpvec_face_id;
+      else
        {
-         /* The function returns -1 if lface_id is invalid.  */
-         int face_id = ascii_face_of_lisp_face (it->f, lface_id);
-         if (face_id >= 0)
-           it->face_id = face_id;
+         int lface_id = FAST_GLYPH_FACE (g);
+         if (lface_id > 0)
+           it->face_id = merge_faces (it->f, Qt, lface_id,
+                                      it->saved_face_id);
        }
     }
   else
@@ -5462,7 +5610,7 @@ next_element_from_ellipsis (it)
         was in IT->saved_face_id, and signal that it's there by
         setting face_before_selective_p.  */
       it->saved_face_id = it->face_id;
-      it->method = next_element_from_buffer;
+      it->method = GET_FROM_BUFFER;
       reseat_at_next_visible_line_start (it, 1);
       it->face_before_selective_p = 1;
     }
@@ -5703,10 +5851,14 @@ 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)
+#define BUFFER_POS_REACHED_P()                                 \
+  ((op & MOVE_TO_POS) != 0                                     \
+   && BUFFERP (it->object)                                     \
+   && IT_CHARPOS (*it) >= to_charpos                           \
+   && (it->method == GET_FROM_BUFFER                           \
+       || (it->method == GET_FROM_DISPLAY_VECTOR               \
+          && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
+
 
   while (1)
     {
@@ -6176,7 +6328,11 @@ move_it_vertically_backward (it, dy)
         value of nlines is > 0 if continuation lines were involved.  */
       if (nlines > 0)
        move_it_by_lines (it, nlines, 1);
+#if 0
+      /* I think this assert is bogus if buffer contains
+        invisible text or images.  KFS.  */
       xassert (IT_CHARPOS (*it) <= start_pos);
+#endif
     }
   else
     {
@@ -6194,7 +6350,8 @@ move_it_vertically_backward (it, dy)
             a line height of 13 pixels each, recentering with point
             on the bottom line will try to move -39/2 = 19 pixels
             backward.  Try to avoid moving into the first line.  */
-         && it->current_y - target_y > line_height * 2 / 3
+         && (it->current_y - target_y
+             > min (window_box_height (it->w), line_height * 2 / 3))
          && IT_CHARPOS (*it) > BEGV)
        {
          TRACE_MOVE ((stderr, "  not far enough -> move_vert %d\n",
@@ -6224,7 +6381,11 @@ move_it_vertically_backward (it, dy)
              while (target_y >= line_bottom_y (it) && IT_CHARPOS (*it) < ZV);
            }
 
+#if 0
+         /* I think this assert is bogus if buffer contains
+            invisible text or images.  KFS.  */
          xassert (IT_CHARPOS (*it) >= BEGV);
+#endif
        }
     }
 }
@@ -6368,11 +6529,15 @@ move_it_by_lines (it, dvpos, need_y_p)
       it->current_y -= it2.current_y;
       it->current_x = it->hpos = 0;
 
-      /* If we moved too far, move IT some lines forward.  */
+      /* If we moved too far back, move IT some lines forward.  */
       if (it2.vpos > -dvpos)
        {
          int delta = it2.vpos + dvpos;
+         it2 = *it;
          move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
+         /* Move back again if we got too far ahead.  */
+         if (IT_CHARPOS (*it) >= start_charpos)
+           *it = it2;
        }
     }
 }
@@ -6383,7 +6548,7 @@ int
 in_display_vector_p (it)
      struct it *it;
 {
-  return (it->method == next_element_from_display_vector
+  return (it->method == GET_FROM_DISPLAY_VECTOR
          && it->current.dpvec_index > 0
          && it->dpvec + it->current.dpvec_index != it->dpend);
 }
@@ -7965,6 +8130,8 @@ echo_area_display (update_frame_p)
 
   /* Last displayed message is now the current message.  */
   echo_area_buffer[1] = echo_area_buffer[0];
+  /* Inform read_char that we're not echoing.  */
+  echo_message_buffer = Qnil;
 
   /* Prevent redisplay optimization in redisplay_internal by resetting
      this_line_start_pos.  This is done because the mini-buffer now
@@ -10205,7 +10372,9 @@ redisplay_internal (preserve_echo_area)
   CHARPOS (this_line_start_pos) = 0;
   consider_all_windows_p |= buffer_shared > 1;
   ++clear_face_cache_count;
-
+#ifdef HAVE_WINDOW_SYSTEM
+  ++clear_image_cache_count;
+#endif
 
   /* Build desired matrices, and update the display.  If
      consider_all_windows_p is non-zero, do it for all windows on all
@@ -10218,13 +10387,6 @@ redisplay_internal (preserve_echo_area)
       struct frame **updated
        = (struct frame **) alloca (size * sizeof *updated);
 
-      /* Clear the face cache eventually.  */
-      if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
-       {
-         clear_face_cache (0);
-         clear_face_cache_count = 0;
-       }
-
       /* Recompute # windows showing selected buffer.  This will be
         incremented each time such a window is displayed.  */
       buffer_shared = 0;
@@ -10240,12 +10402,6 @@ redisplay_internal (preserve_echo_area)
                   variables.  */
                select_frame_for_redisplay (frame);
 
-#ifdef HAVE_WINDOW_SYSTEM
-             if (clear_face_cache_count % 50 == 0
-                 && FRAME_WINDOW_P (f))
-               clear_image_cache (f, 0);
-#endif /* HAVE_WINDOW_SYSTEM */
-
              /* Mark all the scroll bars to be removed; we'll redeem
                 the ones we want when we redisplay their windows.  */
              if (condemn_scroll_bars_hook)
@@ -10449,6 +10605,29 @@ redisplay_internal (preserve_echo_area)
   if (windows_or_buffers_changed && !pause)
     goto retry;
 
+  /* Clear the face cache eventually.  */
+  if (consider_all_windows_p)
+    {
+      if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
+       {
+         clear_face_cache (0);
+         clear_face_cache_count = 0;
+       }
+#ifdef HAVE_WINDOW_SYSTEM
+      if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
+       {
+         Lisp_Object tail, frame;
+         FOR_EACH_FRAME (tail, frame)
+           {
+             struct frame *f = XFRAME (frame);
+             if (FRAME_WINDOW_P (f))
+               clear_image_cache (f, 0);
+           }
+         clear_image_cache_count = 0;
+       }
+#endif /* HAVE_WINDOW_SYSTEM */
+    }
+
  end_of_redisplay:
   unbind_to (count, Qnil);
   RESUME_POLLING;
@@ -10812,6 +10991,18 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
       glyph = cursor;
       x = cursor_x;
     }
+  else if (row->ends_in_ellipsis_p && glyph == end)
+    {
+      /* Scan back over the ellipsis glyphs, decrementing positions.  */
+      while (glyph > row->glyphs[TEXT_AREA]
+            && (glyph - 1)->charpos == last_pos)
+       glyph--, x -= glyph->pixel_width;
+      /* That loop always goes one position too far,
+        including the glyph before the ellipsis.
+        So scan forward over that one.  */
+      x += glyph->pixel_width;
+      glyph++;
+    }
   else if (string_start
           && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
     {
@@ -10934,7 +11125,7 @@ run_window_scroll_functions (window, startp)
    as if point had gone off the screen.  */
 
 static int
-make_cursor_line_fully_visible (w, force_p)
+cursor_row_fully_visible_p (w, force_p, current_matrix_p)
      struct window *w;
      int force_p;
 {
@@ -10950,7 +11141,7 @@ make_cursor_line_fully_visible (w, force_p)
   if (w->cursor.vpos < 0)
     return 1;
 
-  matrix = w->desired_matrix;
+  matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
   row = MATRIX_ROW (matrix, w->cursor.vpos);
 
   /* If the cursor row is not partially visible, there's nothing to do.  */
@@ -11255,7 +11446,7 @@ 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, extra_scroll_margin_lines <= 1))
+      if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1, 0))
        {
          clear_glyph_matrix (w->desired_matrix);
          ++extra_scroll_margin_lines;
@@ -11525,6 +11716,12 @@ try_cursor_movement (window, startp, scroll_step)
                  && CHARPOS (startp) != BEGV)
                scroll_p = 1;
            }
+         else
+           {
+             /* Cursor did not move.  So don't scroll even if cursor line
+                is partially visible, as it was so before.  */
+                rc = CURSOR_MOVEMENT_SUCCESS;
+           }
 
          if (PT < MATRIX_ROW_START_CHARPOS (row)
              || PT > MATRIX_ROW_END_CHARPOS (row))
@@ -11532,7 +11729,8 @@ try_cursor_movement (window, startp, scroll_step)
              /* if PT is not in the glyph row, give up.  */
              rc = CURSOR_MOVEMENT_MUST_SCROLL;
            }
-         else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
+         else if (rc != CURSOR_MOVEMENT_SUCCESS
+                  && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
                   && make_cursor_line_fully_visible_p)
            {
              if (PT == MATRIX_ROW_END_CHARPOS (row)
@@ -11551,7 +11749,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, 0))
+                 if (!cursor_row_fully_visible_p (w, 0, 1))
                    rc = CURSOR_MOVEMENT_MUST_SCROLL;
                  else
                    rc = CURSOR_MOVEMENT_SUCCESS;
@@ -11636,7 +11834,7 @@ redisplay_window (window, just_this_one_p)
   int temp_scroll_step = 0;
   int count = SPECPDL_INDEX ();
   int rc;
-  int centering_position;
+  int centering_position = -1;
   int last_line_misfit = 0;
 
   SET_TEXT_POS (lpoint, PT, PT_BYTE);
@@ -11648,9 +11846,6 @@ redisplay_window (window, just_this_one_p)
   *w->desired_matrix->method = 0;
 #endif
 
-  /* Force this to be looked up again for each redisp of each window.  */
-  escape_glyph_face = -1;
-
   specbind (Qinhibit_point_motion_hooks, Qt);
 
   reconsider_clip_changes (w, buffer);
@@ -11885,7 +12080,7 @@ redisplay_window (window, just_this_one_p)
          new_vpos = window_box_height (w) / 2;
        }
 
-      if (!make_cursor_line_fully_visible (w, 0))
+      if (!cursor_row_fully_visible_p (w, 0, 0))
        {
          /* Point does appear, but on a line partly visible at end of window.
             Move it back to a fully-visible line.  */
@@ -12022,7 +12217,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, 1))
+         if (!cursor_row_fully_visible_p (w, 1, 0))
            {
              clear_glyph_matrix (w->desired_matrix);
              last_line_misfit = 1;
@@ -12082,10 +12277,8 @@ redisplay_window (window, just_this_one_p)
   /* Finally, just choose place to start which centers point */
 
  recenter:
-  centering_position = window_box_height (w) / 2;
-
- point_at_top:
-  /* Jump here with centering_position already set to 0.  */
+  if (centering_position < 0)
+    centering_position = window_box_height (w) / 2;
 
 #if GLYPH_DEBUG
   debug_method_add (w, "recenter");
@@ -12112,7 +12305,11 @@ redisplay_window (window, just_this_one_p)
     {
       init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
       move_it_vertically_backward (&it, 0);
+#if 0
+      /* I think this assert is bogus if buffer contains
+        invisible text or images.  KFS.  */
       xassert (IT_CHARPOS (it) <= PT);
+#endif
       it.current_y = 0;
     }
 
@@ -12182,7 +12379,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, centering_position > 0))
+  if (!cursor_row_fully_visible_p (w, 0, 0))
     {
       /* If vscroll is enabled, disable it and try again.  */
       if (w->vscroll)
@@ -12195,9 +12392,12 @@ 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.  */
+      if (centering_position == 0)
+       goto done;
+
       clear_glyph_matrix (w->desired_matrix);
       centering_position = 0;
-      goto point_at_top;
+      goto recenter;
     }
 
  done:
@@ -12982,8 +13182,10 @@ find_first_unchanged_at_end_row (w, delta, delta_bytes)
         starts at a minimum position >= last_unchanged_pos_old.  */
       for (; row > first_text_row; --row)
        {
+         /* This used to abort, but it can happen.
+            It is ok to just stop the search instead here.  KFS.  */
          if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
-           abort ();
+           break;
 
          if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
            row_found = row;
@@ -13690,7 +13892,12 @@ try_window_id (w)
                        bottom_vpos, dy);
 
   if (first_unchanged_at_end_row)
-    first_unchanged_at_end_row += dvpos;
+    {
+      first_unchanged_at_end_row += dvpos;
+      if (first_unchanged_at_end_row->y >= it.last_visible_y
+         || !MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row))
+       first_unchanged_at_end_row = NULL;
+    }
 
   /* If scrolling up, there may be some lines to display at the end of
      the window.  */
@@ -13747,7 +13954,6 @@ try_window_id (w)
 
   /* Update window_end_pos and window_end_vpos.  */
   if (first_unchanged_at_end_row
-      && first_unchanged_at_end_row->y < it.last_visible_y
       && !last_text_row_at_end)
     {
       /* Window end line if one of the preserved rows from the current
@@ -14613,10 +14819,22 @@ cursor_row_p (w, row)
       /* If the row ends with a newline from a string, we don't want
         the cursor there (if the row is continued it doesn't end in a
         newline).  */
-      if (CHARPOS (row->end.string_pos) >= 0
-         || MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
+      if (CHARPOS (row->end.string_pos) >= 0)
        cursor_row_p = row->continued_p;
-
+      else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
+       {
+         /* If the row ends in middle of a real character,
+            and the line is continued, we want the cursor here.
+            That's because MATRIX_ROW_END_CHARPOS would equal
+            PT if PT is before the character.  */
+         if (!row->ends_in_ellipsis_p)
+           cursor_row_p = row->continued_p;
+         else
+         /* If the row ends in an ellipsis, then
+            MATRIX_ROW_END_CHARPOS will equal point after the invisible text.
+            We want that position to be displayed after the ellipsis.  */
+           cursor_row_p = 0;
+       }
       /* If the row ends at ZV, display the cursor at the end of that
         row instead of at the start of the row below.  */
       else if (row->ends_at_zv_p)
@@ -15093,6 +15311,11 @@ display_line (it)
   /* Remember the position at which this line ends.  */
   row->end = it->current;
 
+  /* Record whether this row ends inside an ellipsis.  */
+  row->ends_in_ellipsis_p
+    = (it->method == GET_FROM_DISPLAY_VECTOR
+       && it->ellipsis_p);
+
   /* 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;
@@ -15936,22 +16159,30 @@ store_mode_line_string (string, lisp_string, copy_string, field_width, precision
 
 
 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
-       0, 4, 0,
-       doc: /* Return the mode-line of selected window as a string.
-First optional arg FORMAT specifies a different format string (see
-`mode-line-format' for details) to use.  If FORMAT is t, return
-the buffer's header-line.  Second optional arg WINDOW specifies a
-different window to use as the context for the formatting.
-If third optional arg NO-PROPS is non-nil, string is not propertized.
-Fourth optional arg BUFFER specifies which buffer to use.  */)
-  (format, window, no_props, buffer)
-     Lisp_Object format, window, no_props, buffer;
+       1, 4, 0,
+       doc: /* Format a string out of a mode line format specification.
+First arg FORMAT specifies the mode line format (see `mode-line-format'
+for details) to use.
+
+Optional second arg FACE specifies the face property to put
+on all characters for which no face is specified.
+t means whatever face the window's mode line currently uses
+\(either `mode-line' or `mode-line-inactive', depending).
+nil means the default is no face property.
+If FACE is an integer, the value string has no text properties.
+
+Optional third and fourth args WINDOW and BUFFER specify the window
+and buffer to use as the context for the formatting (defaults
+are the selected window and the window's buffer).  */)
+  (format, face, window, buffer)
+     Lisp_Object format, face, window, buffer;
 {
   struct it it;
   int len;
   struct window *w;
   struct buffer *old_buffer = NULL;
-  enum face_id face_id = DEFAULT_FACE_ID;
+  int face_id = -1;
+  int no_props = INTEGERP (face);
 
   if (NILP (window))
     window = selected_window;
@@ -15960,37 +16191,37 @@ Fourth optional arg BUFFER specifies which buffer to use.  */)
 
   if (NILP (buffer))
     buffer = w->buffer;
-
   CHECK_BUFFER (buffer);
 
-  if (XBUFFER (buffer) != current_buffer)
+  if (NILP (format))
+    return build_string ("");
+
+  if (no_props)
+    face = Qnil;
+
+  if (!NILP (face))
     {
-      old_buffer = current_buffer;
-      set_buffer_internal_1 (XBUFFER (buffer));
+      if (EQ (face, Qt))
+       face = (EQ (window, selected_window) ? Qmode_line : Qmode_line_inactive);
+      face_id = lookup_named_face (XFRAME (WINDOW_FRAME (w)), face, 0, 0);
     }
 
-  if (NILP (format) || EQ (format, Qt))
+  if (face_id < 0)
+    face_id = DEFAULT_FACE_ID;
+
+  if (XBUFFER (buffer) != current_buffer)
     {
-      face_id = (NILP (format)
-                ? CURRENT_MODE_LINE_FACE_ID (w)
-                : HEADER_LINE_FACE_ID);
-      format = (NILP (format)
-               ? current_buffer->mode_line_format
-               : current_buffer->header_line_format);
+      old_buffer = current_buffer;
+      set_buffer_internal_1 (XBUFFER (buffer));
     }
 
   init_iterator (&it, w, -1, -1, NULL, face_id);
 
-  if (NILP (no_props))
+  if (!no_props)
     {
-      mode_line_string_face
-       = (face_id == MODE_LINE_FACE_ID ? Qmode_line
-          : face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive
-          : face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil);
-
+      mode_line_string_face = face;
       mode_line_string_face_prop
-       = (NILP (mode_line_string_face) ? Qnil
-          : Fcons (Qface, Fcons (mode_line_string_face, Qnil)));
+       = (NILP (face) ? Qnil : Fcons (Qface, Fcons (face, Qnil)));
 
       /* We need a dummy last element in mode_line_string_list to
         indicate we are building the propertized mode-line string.
@@ -16013,7 +16244,7 @@ Fourth optional arg BUFFER specifies which buffer to use.  */)
   if (old_buffer)
     set_buffer_internal_1 (old_buffer);
 
-  if (NILP (no_props))
+  if (!no_props)
     {
       Lisp_Object str;
       mode_line_string_list = Fnreverse (mode_line_string_list);
@@ -18170,6 +18401,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
 {
   struct glyph_string *head, *tail;
   struct glyph_string *s;
+  struct glyph_string *clip_head = NULL, *clip_tail = NULL;
   int last_x, area_width;
   int x_reached;
   int i, j;
@@ -18238,6 +18470,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
          start = i;
          compute_overhangs_and_x (t, head->x, 1);
          prepend_glyph_string_lists (&head, &tail, h, t);
+         clip_head = head;
        }
 
       /* Prepend glyph strings for glyphs in front of the first glyph
@@ -18250,6 +18483,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
       i = left_overwriting (head);
       if (i >= 0)
        {
+         clip_head = head;
          BUILD_GLYPH_STRINGS (i, start, h, t,
                               DRAW_NORMAL_TEXT, dummy_x, last_x);
          for (s = h; s; s = s->next)
@@ -18269,6 +18503,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
                               DRAW_NORMAL_TEXT, x, last_x);
          compute_overhangs_and_x (h, tail->x + tail->width, 0);
          append_glyph_string_lists (&head, &tail, h, t);
+         clip_tail = tail;
        }
 
       /* Append glyph strings for glyphs following the last glyph
@@ -18279,6 +18514,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
       i = right_overwriting (tail);
       if (i >= 0)
        {
+         clip_tail = tail;
          BUILD_GLYPH_STRINGS (end, i, h, t,
                               DRAW_NORMAL_TEXT, x, last_x);
          for (s = h; s; s = s->next)
@@ -18286,6 +18522,12 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
          compute_overhangs_and_x (h, tail->x + tail->width, 0);
          append_glyph_string_lists (&head, &tail, h, t);
        }
+      if (clip_head || clip_tail)
+       for (s = head; s; s = s->next)
+         {
+           s->clip_head = clip_head;
+           s->clip_tail = clip_tail;
+         }
     }
 
   /* Draw all strings.  */
@@ -18299,8 +18541,9 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
         completely. */
       && !overlaps_p)
     {
-      int x0 = head ? head->x : x;
-      int x1 = tail ? tail->x + tail->background_width : x;
+      int x0 = clip_head ? clip_head->x : (head ? head->x : x);
+      int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
+               : (tail ? tail->x + tail->background_width : x));
 
       int text_left = window_box_left (w, TEXT_AREA);
       x0 -= text_left;
@@ -19110,7 +19353,9 @@ x_produce_glyphs (it)
 
          height = get_line_height_property(it, Qline_height);
          /* Split (line-height total-height) list */
-         if (CONSP (height) && CONSP (XCDR (height)))
+         if (CONSP (height)
+             && CONSP (XCDR (height))
+             && NILP (XCDR (XCDR (height))))
            {
              total_height = XCAR (XCDR (height));
              height = XCAR (height);
@@ -19975,8 +20220,10 @@ notice_overwritten_cursor (w, area, x0, x1, y0, y1)
   if (area != TEXT_AREA)
     return;
 
-  row = w->current_matrix->rows + w->phys_cursor.vpos;
-  if (!row->displays_text_p)
+  if (w->phys_cursor.vpos < 0
+      || w->phys_cursor.vpos >= w->current_matrix->nrows
+      || (row = w->current_matrix->rows + w->phys_cursor.vpos,
+         !(row->enabled_p && row->displays_text_p)))
     return;
 
   if (row->cursor_in_fringe_p)
@@ -20550,6 +20797,30 @@ fast_find_position (w, charpos, hpos, vpos, x, y, stop)
       past_end = 1;
     }
 
+  /* If whole rows or last part of a row came from a display overlay,
+     row_containing_pos will skip over such rows because their end pos
+     equals the start pos of the overlay or interval.
+
+     Move back if we have a STOP object and previous row's
+     end glyph came from STOP.  */
+  if (!NILP (stop))
+    {
+      struct glyph_row *prev;
+      while ((prev = row - 1, prev >= first)
+            && MATRIX_ROW_END_CHARPOS (prev) == charpos
+            && prev->used[TEXT_AREA] > 0)
+       {
+         struct glyph *beg = prev->glyphs[TEXT_AREA];
+         glyph = beg + prev->used[TEXT_AREA];
+         while (--glyph >= beg
+                && INTEGERP (glyph->object));
+         if (glyph < beg
+             || !EQ (stop, glyph->object))
+           break;
+         row = prev;
+       }
+    }
+
   *x = row->x;
   *y = row->y;
   *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
@@ -21011,9 +21282,9 @@ note_mode_line_or_margin_highlight (w, x, y, area)
                  help_echo_pos = charpos;
                }
            }
-         if (NILP (pointer))
-           pointer = Fsafe_plist_get (XCDR (object), QCpointer);
        }
+      if (NILP (pointer))
+       pointer = Fsafe_plist_get (XCDR (object), QCpointer);
     }
 
   if (STRINGP (string))
@@ -21891,7 +22162,9 @@ expose_window (w, fr)
              || (r.y >= y0 && r.y < y1)
              || (r.y + r.height > y0 && r.y + r.height < y1))
            {
-             if (row->overlapping_p)
+             /* A header line may be overlapping, but there is no need
+                to fix overlapping areas for them.  KFS 2005-02-12 */
+             if (row->overlapping_p && !row->mode_line_p)
                {
                  if (first_overlapping_row == NULL)
                    first_overlapping_row = row;
@@ -22315,6 +22588,10 @@ wide as that tab on the display.  */);
 The face used for trailing whitespace is `trailing-whitespace'.  */);
   Vshow_trailing_whitespace = Qnil;
 
+  DEFVAR_LISP ("show-nonbreak-escape", &Vshow_nonbreak_escape,
+    doc: /* *Non-nil means display escape character before non-break space and hyphen.  */);
+  Vshow_nonbreak_escape = Qt;
+
   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',
@@ -22565,8 +22842,10 @@ Bind this around calls to `message' to let it take effect.  */);
   message_truncate_lines = 0;
 
   DEFVAR_LISP ("menu-bar-update-hook",  &Vmenu_bar_update_hook,
-    doc: /* Normal hook run for clicks on menu bar, before displaying a submenu.
-Can be used to update submenus whose contents should vary.  */);
+    doc: /* Normal hook run to update the menu bar definitions.
+Redisplay runs this hook before it redisplays the menu bar.
+This is used to update submenus such as Buffers,
+whose contents depend on various data.  */);
   Vmenu_bar_update_hook = Qnil;
 
   DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,