]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
(rmail-resend): Let MAIL-ALIAS-FILE arg override mail-personal-alias-file.
[gnu-emacs] / src / xdisp.c
index 36892a219c03581d2d65dfa8be381e7f26bc1f2c..8ed0adfc89e998aa5c673f9efc2df48b1bae4c53 100644 (file)
@@ -342,6 +342,11 @@ Lisp_Object Vvoid_text_area_pointer;
 
 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.  */
 
@@ -807,9 +812,9 @@ static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
 \f
 /* Function prototypes.  */
 
-static void setup_for_ellipsis P_ ((struct it *));
+static void setup_for_ellipsis P_ ((struct it *, int));
 static void mark_window_display_accurate_1 P_ ((struct window *, int));
-static int single_display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
+static int single_display_spec_string_p P_ ((Lisp_Object, Lisp_Object));
 static int display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
 static int cursor_row_p P_ ((struct window *, struct glyph_row *));
 static int redisplay_mode_lines P_ ((Lisp_Object, int));
@@ -831,7 +836,7 @@ static int store_frame_title P_ ((const unsigned char *, int, int));
 static void x_consider_frame_title P_ ((Lisp_Object));
 static void handle_stop P_ ((struct it *));
 static int tool_bar_lines_needed P_ ((struct frame *));
-static int single_display_prop_intangible_p P_ ((Lisp_Object));
+static int single_display_spec_intangible_p P_ ((Lisp_Object));
 static void ensure_echo_area_buffers P_ ((void));
 static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
 static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
@@ -925,7 +930,7 @@ static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
                                    Lisp_Object));
 static int face_before_or_after_it_pos P_ ((struct it *, int));
 static int next_overlay_change P_ ((int));
-static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
+static int handle_single_display_spec P_ ((struct it *, Lisp_Object,
                                           Lisp_Object, struct text_pos *,
                                           int));
 static int underlying_face_id P_ ((struct it *));
@@ -3227,7 +3232,7 @@ handle_invisible_prop (it)
              it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
            }
          else if (display_ellipsis_p)
-           setup_for_ellipsis (it);
+           setup_for_ellipsis (it, 0);
        }
     }
 
@@ -3235,14 +3240,17 @@ handle_invisible_prop (it)
 }
 
 
-/* Make iterator IT return `...' next.  */
+/* Make iterator IT return `...' next.
+   Replaces LEN characters from buffer.  */
 
 static void
-setup_for_ellipsis (it)
+setup_for_ellipsis (it, len)
      struct it *it;
+     int len;
 {
-  if (it->dp
-      && VECTORP (DISP_INVIS_VECTOR (it->dp)))
+  /* Use the display table definition for `...'.  Invalid glyphs
+     will be handled by the method returning elements from dpvec.  */
+  if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
     {
       struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
       it->dpvec = v->contents;
@@ -3255,12 +3263,12 @@ setup_for_ellipsis (it)
       it->dpend = default_invis_vector + 3;
     }
 
-  /* The ellipsis display does not replace the display of the
-     character at the new position.  Indicate this by setting
-     IT->dpvec_char_len to zero.  */
-  it->dpvec_char_len = 0;
-
+  it->dpvec_char_len = len;
   it->current.dpvec_index = 0;
+
+  /* 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;
 }
 
@@ -3271,7 +3279,10 @@ setup_for_ellipsis (it)
  ***********************************************************************/
 
 /* Set up iterator IT from `display' property at its current position.
-   Called from handle_stop.  */
+   Called from handle_stop.
+   We return HANDLED_RETURN if some part of the display property
+   overrides the display of the buffer text itself.
+   Otherwise we return HANDLED_NORMALLY.  */
 
 static enum prop_handled
 handle_display_prop (it)
@@ -3279,6 +3290,7 @@ handle_display_prop (it)
 {
   Lisp_Object prop, object;
   struct text_pos *position;
+  /* Nonzero if some property replaces the display of the text itself.  */ 
   int display_replaced_p = 0;
 
   if (STRINGP (it->string))
@@ -3326,7 +3338,7 @@ handle_display_prop (it)
     {
       for (; CONSP (prop); prop = XCDR (prop))
        {
-         if (handle_single_display_prop (it, XCAR (prop), object,
+         if (handle_single_display_spec (it, XCAR (prop), object,
                                          position, display_replaced_p))
            display_replaced_p = 1;
        }
@@ -3335,13 +3347,13 @@ handle_display_prop (it)
     {
       int i;
       for (i = 0; i < ASIZE (prop); ++i)
-       if (handle_single_display_prop (it, AREF (prop, i), object,
+       if (handle_single_display_spec (it, AREF (prop, i), object,
                                        position, display_replaced_p))
          display_replaced_p = 1;
     }
   else
     {
-      if (handle_single_display_prop (it, prop, object, position, 0))
+      if (handle_single_display_spec (it, prop, object, position, 0))
        display_replaced_p = 1;
     }
 
@@ -3373,42 +3385,44 @@ display_prop_end (it, object, start_pos)
 }
 
 
-/* Set up IT from a single `display' sub-property value PROP.  OBJECT
+/* Set up IT from a single `display' specification PROP.  OBJECT
    is the object in which the `display' property was found.  *POSITION
    is the position at which it was found.  DISPLAY_REPLACED_P non-zero
-   means that we previously saw a display sub-property which already
+   means that we previously saw a display specification which already
    replaced text display with something else, for example an image;
-   ignore such properties after the first one has been processed.
+   we ignore such properties after the first one has been processed.
 
-   If PROP is a `space' or `image' sub-property, set *POSITION to the
-   end position of the `display' property.
+   If PROP is a `space' or `image' specification, and in some other
+   cases too, set *POSITION to the position where the `display'
+   property ends.
 
    Value is non-zero if something was found which replaces the display
    of buffer or string text.  */
 
 static int
-handle_single_display_prop (it, prop, object, position,
+handle_single_display_spec (it, spec, object, position,
                            display_replaced_before_p)
      struct it *it;
-     Lisp_Object prop;
+     Lisp_Object spec;
      Lisp_Object object;
      struct text_pos *position;
      int display_replaced_before_p;
 {
-  Lisp_Object value;
-  int replaces_text_display_p = 0;
   Lisp_Object form;
+  Lisp_Object location, value;
+  struct text_pos start_pos;
+  int valid_p;
 
-  /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
-     evaluated.  If the result is nil, VALUE is ignored.  */
+  /* If SPEC is a list of the form `(when FORM . VALUE)', evaluate FORM.
+     If the result is non-nil, use VALUE instead of SPEC.  */
   form = Qt;
-  if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
+  if (CONSP (spec) && EQ (XCAR (spec), Qwhen))
     {
-      prop = XCDR (prop);
-      if (!CONSP (prop))
+      spec = XCDR (spec);
+      if (!CONSP (spec))
        return 0;
-      form = XCAR (prop);
-      prop = XCDR (prop);
+      form = XCAR (spec);
+      spec = XCDR (spec);
     }
 
   if (!NILP (form) && !EQ (form, Qt))
@@ -3434,15 +3448,15 @@ handle_single_display_prop (it, prop, object, position,
   if (NILP (form))
     return 0;
 
-  if (CONSP (prop)
-      && EQ (XCAR (prop), Qheight)
-      && CONSP (XCDR (prop)))
+  /* Handle `(height HEIGHT)' specifications.  */
+  if (CONSP (spec)
+      && EQ (XCAR (spec), Qheight)
+      && CONSP (XCDR (spec)))
     {
       if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
        return 0;
-
-      /* `(height HEIGHT)'.  */
-      it->font_height = XCAR (XCDR (prop));
+      
+      it->font_height = XCAR (XCDR (spec));
       if (!NILP (it->font_height))
        {
          struct face *face = FACE_FROM_ID (it->f, it->face_id);
@@ -3483,7 +3497,6 @@ handle_single_display_prop (it, prop, object, position,
            {
              /* Evaluate IT->font_height with `height' bound to the
                 current specified height to get the new height.  */
-             Lisp_Object value;
              int count = SPECPDL_INDEX ();
 
              specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
@@ -3497,29 +3510,35 @@ handle_single_display_prop (it, prop, object, position,
          if (new_height > 0)
            it->face_id = face_with_height (it->f, it->face_id, new_height);
        }
+
+      return 0;
     }
-  else if (CONSP (prop)
-          && EQ (XCAR (prop), Qspace_width)
-          && CONSP (XCDR (prop)))
+
+  /* Handle `(space_width WIDTH)'.  */
+  if (CONSP (spec)
+      && EQ (XCAR (spec), Qspace_width)
+      && CONSP (XCDR (spec)))
     {
-      /* `(space_width WIDTH)'.  */
       if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
        return 0;
 
-      value = XCAR (XCDR (prop));
+      value = XCAR (XCDR (spec));
       if (NUMBERP (value) && XFLOATINT (value) > 0)
        it->space_width = value;
+
+      return 0;
     }
-  else if (CONSP (prop)
-          && EQ (XCAR (prop), Qslice))
+
+  /* Handle `(slice X Y WIDTH HEIGHT)'.  */
+  if (CONSP (spec)
+      && EQ (XCAR (spec), Qslice))
     {
-      /* `(slice X Y WIDTH HEIGHT)'.  */
       Lisp_Object tem;
 
       if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
        return 0;
 
-      if (tem = XCDR (prop), CONSP (tem))
+      if (tem = XCDR (spec), CONSP (tem))
        {
          it->slice.x = XCAR (tem);
          if (tem = XCDR (tem), CONSP (tem))
@@ -3533,17 +3552,20 @@ handle_single_display_prop (it, prop, object, position,
                }
            }
        }
+
+      return 0;
     }
-  else if (CONSP (prop)
-          && EQ (XCAR (prop), Qraise)
-          && CONSP (XCDR (prop)))
+
+  /* Handle `(raise FACTOR)'.  */
+  if (CONSP (spec)
+      && EQ (XCAR (spec), Qraise)
+      && CONSP (XCDR (spec)))
     {
-      /* `(raise FACTOR)'.  */
       if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
        return 0;
 
 #ifdef HAVE_WINDOW_SYSTEM
-      value = XCAR (XCDR (prop));
+      value = XCAR (XCDR (spec));
       if (NUMBERP (value))
        {
          struct face *face = FACE_FROM_ID (it->f, it->face_id);
@@ -3551,185 +3573,194 @@ handle_single_display_prop (it, prop, object, position,
                           * (FONT_HEIGHT (face->font)));
        }
 #endif /* HAVE_WINDOW_SYSTEM */
+
+      return 0;
     }
-  else if (!it->string_from_display_prop_p)
-    {
-      /* `((margin left-margin) VALUE)' or `((margin right-margin)
-        VALUE) or `((margin nil) VALUE)' or VALUE.  */
-      Lisp_Object location, value;
-      struct text_pos start_pos;
-      int valid_p;
 
-      /* Characters having this form of property are not displayed, so
-         we have to find the end of the property.  */
-      start_pos = *position;
-      *position = display_prop_end (it, object, start_pos);
-      value = Qnil;
+  /* Don't handle the other kinds of display specifications
+     inside a string that we got from a `display' property.  */
+  if (it->string_from_display_prop_p)
+    return 0;
 
-      /* Let's stop at the new position and assume that all
-        text properties change there.  */
-      it->stop_charpos = position->charpos;
+  /* Characters having this form of property are not displayed, so
+     we have to find the end of the property.  */
+  start_pos = *position;
+  *position = display_prop_end (it, object, start_pos);
+  value = Qnil;
 
-      if (CONSP (prop)
-         && (EQ (XCAR (prop), Qleft_fringe)
-             || EQ (XCAR (prop), Qright_fringe))
-         && CONSP (XCDR (prop)))
-       {
-         int face_id = DEFAULT_FACE_ID;
-         int fringe_bitmap;
+  /* Stop the scan at that end position--we assume that all
+     text properties change there.  */
+  it->stop_charpos = position->charpos;
 
-         /* Save current settings of IT so that we can restore them
-            when we are finished with the glyph property value.  */
+  /* Handle `(left-fringe BITMAP [FACE])'
+     and `(right-fringe BITMAP [FACE])'.  */
+  if (CONSP (spec)
+      && (EQ (XCAR (spec), Qleft_fringe)
+         || EQ (XCAR (spec), Qright_fringe))
+      && CONSP (XCDR (spec)))
+    {
+      int face_id = DEFAULT_FACE_ID;
+      int fringe_bitmap;
 
-         /* `(left-fringe BITMAP FACE)'.  */
-         if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
-           return 0;
+      if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
+       /* If we return here, POSITION has been advanced
+          across the text with this property.  */
+       return 0;
 
 #ifdef HAVE_WINDOW_SYSTEM
-         value = XCAR (XCDR (prop));
-         if (!SYMBOLP (value)
-             || !(fringe_bitmap = lookup_fringe_bitmap (value)))
-           return 0;
+      value = XCAR (XCDR (spec));
+      if (!SYMBOLP (value)
+         || !(fringe_bitmap = lookup_fringe_bitmap (value)))
+       /* If we return here, POSITION has been advanced
+          across the text with this property.  */
+       return 0;
 
-         if (CONSP (XCDR (XCDR (prop))))
-           {
-             Lisp_Object face_name = XCAR (XCDR (XCDR (prop)));
-             int face_id2 = lookup_named_face (it->f, face_name, 'A', 0);
-             if (face_id2 >= 0)
-               face_id = face_id2;
-           }
+      if (CONSP (XCDR (XCDR (spec))))
+       {
+         Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
+         int face_id2 = lookup_named_face (it->f, face_name, 'A', 0);
+         if (face_id2 >= 0)
+           face_id = face_id2;
+       }
 
-         push_it (it);
+      /* Save current settings of IT so that we can restore them
+        when we are finished with the glyph property value.  */
 
-         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;
+      push_it (it);
 
-         /* 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;
+      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;
 
-         if (EQ (XCAR (prop), Qleft_fringe))
-           {
-             it->left_user_fringe_bitmap = fringe_bitmap;
-             it->left_user_fringe_face_id = face_id;
-           }
-         else
-           {
-             it->right_user_fringe_bitmap = fringe_bitmap;
-             it->right_user_fringe_face_id = face_id;
-           }
-#endif /* HAVE_WINDOW_SYSTEM */
-         return 1;
-       }
+      /* 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;
 
-      location = Qunbound;
-      if (CONSP (prop) && CONSP (XCAR (prop)))
+      if (EQ (XCAR (spec), Qleft_fringe))
        {
-         Lisp_Object tem;
-
-         value = XCDR (prop);
-         if (CONSP (value))
-           value = XCAR (value);
-
-         tem = XCAR (prop);
-         if (EQ (XCAR (tem), Qmargin)
-             && (tem = XCDR (tem),
-                 tem = CONSP (tem) ? XCAR (tem) : Qnil,
-                 (NILP (tem)
-                  || EQ (tem, Qleft_margin)
-                  || EQ (tem, Qright_margin))))
-           location = tem;
+         it->left_user_fringe_bitmap = fringe_bitmap;
+         it->left_user_fringe_face_id = face_id;
        }
-
-      if (EQ (location, Qunbound))
+      else
        {
-         location = Qnil;
-         value = prop;
+         it->right_user_fringe_bitmap = fringe_bitmap;
+         it->right_user_fringe_face_id = face_id;
        }
+#endif /* HAVE_WINDOW_SYSTEM */
+      return 1;
+    }
 
-      valid_p = (STRINGP (value)
-#ifdef HAVE_WINDOW_SYSTEM
-                || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
-#endif /* not HAVE_WINDOW_SYSTEM */
-                || (CONSP (value) && EQ (XCAR (value), Qspace)));
+  /* Prepare to handle `((margin left-margin) ...)',
+     `((margin right-margin) ...)' and `((margin nil) ...)'
+     prefixes for display specifications.  */
+  location = Qunbound;
+  if (CONSP (spec) && CONSP (XCAR (spec)))
+    {
+      Lisp_Object tem;
 
-      if ((EQ (location, Qleft_margin)
-          || EQ (location, Qright_margin)
-          || NILP (location))
-         && valid_p
-         && !display_replaced_before_p)
-       {
-         replaces_text_display_p = 1;
+      value = XCDR (spec);
+      if (CONSP (value))
+       value = XCAR (value);
 
-         /* Save current settings of IT so that we can restore them
-            when we are finished with the glyph property value.  */
-         push_it (it);
+      tem = XCAR (spec);
+      if (EQ (XCAR (tem), Qmargin)
+         && (tem = XCDR (tem),
+             tem = CONSP (tem) ? XCAR (tem) : Qnil,
+             (NILP (tem)
+              || EQ (tem, Qleft_margin)
+              || EQ (tem, Qright_margin))))
+       location = tem;
+    }
 
-         if (NILP (location))
-           it->area = TEXT_AREA;
-         else if (EQ (location, Qleft_margin))
-           it->area = LEFT_MARGIN_AREA;
-         else
-           it->area = RIGHT_MARGIN_AREA;
+  if (EQ (location, Qunbound))
+    {
+      location = Qnil;
+      value = spec;
+    }
 
-         if (STRINGP (value))
-           {
-             it->string = value;
-             it->multibyte_p = STRING_MULTIBYTE (it->string);
-             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->stop_charpos = 0;
-             it->string_from_display_prop_p = 1;
-             /* 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;
-           }
-         else if (CONSP (value) && EQ (XCAR (value), Qspace))
-           {
-             it->method = next_element_from_stretch;
-             it->object = value;
-             it->current.pos = it->position = start_pos;
-           }
+  /* After this point, VALUE is the property after any
+     margin prefix has been stripped.  It must be a string,
+     an image specification, or `(space ...)'.
+
+     LOCATION specifies where to display: `left-margin',
+     `right-margin' or nil.  */
+
+  valid_p = (STRINGP (value)
 #ifdef HAVE_WINDOW_SYSTEM
-         else
-           {
-             it->what = IT_IMAGE;
-             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;
-
-             /* 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;
-           }
-#endif /* HAVE_WINDOW_SYSTEM */
+            || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
+#endif /* not HAVE_WINDOW_SYSTEM */
+            || (CONSP (value) && EQ (XCAR (value), Qspace)));
+
+  if (valid_p && !display_replaced_before_p)
+    {
+      /* Save current settings of IT so that we can restore them
+        when we are finished with the glyph property value.  */
+      push_it (it);
+
+      if (NILP (location))
+       it->area = TEXT_AREA;
+      else if (EQ (location, Qleft_margin))
+       it->area = LEFT_MARGIN_AREA;
+      else
+       it->area = RIGHT_MARGIN_AREA;
+
+      if (STRINGP (value))
+       {
+         it->string = value;
+         it->multibyte_p = STRING_MULTIBYTE (it->string);
+         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->stop_charpos = 0;
+         it->string_from_display_prop_p = 1;
+         /* 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;
        }
+      else if (CONSP (value) && EQ (XCAR (value), Qspace))
+       {
+         it->method = next_element_from_stretch;
+         it->object = value;
+         it->current.pos = it->position = start_pos;
+       }
+#ifdef HAVE_WINDOW_SYSTEM
       else
-       /* Invalid property or property not supported.  Restore
-          the position to what it was before.  */
-       *position = start_pos;
+       {
+         it->what = IT_IMAGE;
+         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;
+
+         /* 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;
+       }
+#endif /* HAVE_WINDOW_SYSTEM */
+
+      return 1;
     }
 
-  return replaces_text_display_p;
+  /* Invalid property or property not supported.  Restore
+     POSITION to what it was before.  */
+  *position = start_pos;
+  return 0;
 }
 
 
-/* Check if PROP is a display sub-property value whose text should be
+/* Check if SPEC is a display specification value whose text should be
    treated as intangible.  */
 
 static int
-single_display_prop_intangible_p (prop)
+single_display_spec_intangible_p (prop)
      Lisp_Object prop;
 {
   /* Skip over `when FORM'.  */
@@ -3782,7 +3813,7 @@ display_prop_intangible_p (prop)
       /* A list of sub-properties.  */
       while (CONSP (prop))
        {
-         if (single_display_prop_intangible_p (XCAR (prop)))
+         if (single_display_spec_intangible_p (XCAR (prop)))
            return 1;
          prop = XCDR (prop);
        }
@@ -3792,11 +3823,11 @@ display_prop_intangible_p (prop)
       /* A vector of sub-properties.  */
       int i;
       for (i = 0; i < ASIZE (prop); ++i)
-       if (single_display_prop_intangible_p (AREF (prop, i)))
+       if (single_display_spec_intangible_p (AREF (prop, i)))
          return 1;
     }
   else
-    return single_display_prop_intangible_p (prop);
+    return single_display_spec_intangible_p (prop);
 
   return 0;
 }
@@ -3805,7 +3836,7 @@ display_prop_intangible_p (prop)
 /* Return 1 if PROP is a display sub-property value containing STRING.  */
 
 static int
-single_display_prop_string_p (prop, string)
+single_display_spec_string_p (prop, string)
      Lisp_Object prop, string;
 {
   if (EQ (string, prop))
@@ -3850,7 +3881,7 @@ display_prop_string_p (prop, string)
       /* A list of sub-properties.  */
       while (CONSP (prop))
        {
-         if (single_display_prop_string_p (XCAR (prop), string))
+         if (single_display_spec_string_p (XCAR (prop), string))
            return 1;
          prop = XCDR (prop);
        }
@@ -3860,11 +3891,11 @@ display_prop_string_p (prop, string)
       /* A vector of sub-properties.  */
       int i;
       for (i = 0; i < ASIZE (prop); ++i)
-       if (single_display_prop_string_p (AREF (prop, i), string))
+       if (single_display_spec_string_p (AREF (prop, i), string))
          return 1;
     }
   else
-    return single_display_prop_string_p (prop, string);
+    return single_display_spec_string_p (prop, string);
 
   return 0;
 }
@@ -4048,7 +4079,7 @@ next_overlay_string (it)
       /* If we have to display `...' for invisible text, set
         the iterator up for that.  */
       if (display_ellipsis_p)
-       setup_for_ellipsis (it);
+       setup_for_ellipsis (it, 0);
     }
   else
     {
@@ -4840,7 +4871,10 @@ get_next_display_element (it)
      we hit the end of what we iterate over.  Performance note: the
      function pointer `method' used here turns out to be faster than
      using a sequence of if-statements.  */
-  int success_p = (*it->method) (it);
+  int success_p;
+
+ get_next:
+  success_p = (*it->method) (it);
 
   if (it->what == IT_CHARACTER)
     {
@@ -4872,14 +4906,14 @@ get_next_display_element (it)
                  it->dpvec = v->contents;
                  it->dpend = v->contents + v->size;
                  it->current.dpvec_index = 0;
+                 it->saved_face_id = it->face_id;
                  it->method = next_element_from_display_vector;
-                 success_p = get_next_display_element (it);
                }
              else
                {
                  set_iterator_to_next (it, 0);
-                 success_p = get_next_display_element (it);
                }
+             goto get_next;
            }
 
          /* Translate control characters into `\003' or `^C' form.
@@ -4904,7 +4938,9 @@ get_next_display_element (it)
                   || (it->multibyte_p
                       ? ((it->c >= 127
                           && it->len == 1)
-                         || !CHAR_PRINTABLE_P (it->c))
+                         || !CHAR_PRINTABLE_P (it->c)
+                         || it->c == 0x8ad
+                         || it->c == 0x8a0)
                       : (it->c >= 127
                          && (!unibyte_display_via_language_environment
                              || it->c == unibyte_char_to_multibyte (it->c)))))
@@ -4915,6 +4951,22 @@ get_next_display_element (it)
                 IT->ctl_chars with glyphs for what we have to
                 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;
+               }
 
              if (it->c < 128 && it->ctl_arrow_p)
                {
@@ -4924,19 +4976,27 @@ get_next_display_element (it)
                      && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
                    g = XINT (DISP_CTRL_GLYPH (it->dp));
                  else
-                   g = FAST_MAKE_GLYPH ('^', 0);
+                   g = FAST_MAKE_GLYPH ('^', face_id);
                  XSETINT (it->ctl_chars[0], g);
 
-                 g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
+                 g = FAST_MAKE_GLYPH (it->c ^ 0100, face_id);
                  XSETINT (it->ctl_chars[1], g);
+                 ctl_len = 2;
+               }
+             else if (it->c == 0x8a0 || it->c == 0x8ad)
+               {
+                 /* 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);
 
-                 /* 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 + 2;
-                 it->current.dpvec_index = 0;
-                 it->method = next_element_from_display_vector;
-                 get_next_display_element (it);
+                 g = FAST_MAKE_GLYPH (it->c == 0x8ad ? '-' : ' ', face_id);
+                 XSETINT (it->ctl_chars[1], g);
+                 ctl_len = 2;
                }
              else
                {
@@ -4951,7 +5011,7 @@ get_next_display_element (it)
                      && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
                    escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
                  else
-                   escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
+                   escape_glyph = FAST_MAKE_GLYPH ('\\', face_id);
 
                  if (SINGLE_BYTE_CHAR_P (it->c))
                    str[0] = it->c, len = 1;
@@ -4978,23 +5038,27 @@ get_next_display_element (it)
                      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', 0);
+                     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', 0);
+                     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', 0);
+                     g = FAST_MAKE_GLYPH ((str[i] & 7) + '0',
+                                          face_id);
                      XSETINT (it->ctl_chars[i * 4 + 3], g);
                    }
-
-                 /* Set up IT->dpvec and return the first character
-                     from it.  */
-                 it->dpvec_char_len = it->len;
-                 it->dpvec = it->ctl_chars;
-                 it->dpend = it->dpvec + len * 4;
-                 it->current.dpvec_index = 0;
-                 it->method = next_element_from_display_vector;
-                 get_next_display_element (it);
+                 ctl_len = len * 4;
                }
+
+             /* 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->saved_face_id = it->face_id;
+             it->method = next_element_from_display_vector;
+             goto get_next;
            }
        }
 
@@ -5116,6 +5180,9 @@ set_iterator_to_next (it, reseat_p)
          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);
@@ -5184,11 +5251,14 @@ set_iterator_to_next (it, reseat_p)
               && IT_STRING_CHARPOS (*it) >= 0));
 }
 
-
 /* Load IT's display element fields with information about the next
    display element which comes from a display table entry or from the
    result of translating a control character to one of the forms `^C'
-   or `\003'.  IT->dpvec holds the glyphs to return as characters.  */
+   or `\003'.
+
+   IT->dpvec holds the glyphs to return as characters.
+   IT->saved_face_id holds the face id before the display vector--
+   it is restored into IT->face_idin set_iterator_to_next.  */
 
 static int
 next_element_from_display_vector (it)
@@ -5197,10 +5267,6 @@ next_element_from_display_vector (it)
   /* Precondition.  */
   xassert (it->dpvec && it->current.dpvec_index >= 0);
 
-  /* 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;
-
   if (INTEGERP (*it->dpvec)
       && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
     {
@@ -5384,28 +5450,7 @@ next_element_from_ellipsis (it)
      struct it *it;
 {
   if (it->selective_display_ellipsis_p)
-    {
-      if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
-       {
-         /* Use the display table definition for `...'.  Invalid glyphs
-            will be handled by the method returning elements from dpvec.  */
-         struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
-         it->dpvec_char_len = it->len;
-         it->dpvec = v->contents;
-         it->dpend = v->contents + v->size;
-         it->current.dpvec_index = 0;
-         it->method = next_element_from_display_vector;
-       }
-      else
-       {
-         /* Use default `...' which is stored in default_invis_vector.  */
-         it->dpvec_char_len = it->len;
-         it->dpvec = default_invis_vector;
-         it->dpend = default_invis_vector + 3;
-         it->current.dpvec_index = 0;
-         it->method = next_element_from_display_vector;
-       }
-    }
+    setup_for_ellipsis (it, it->len);
   else
     {
       /* The face at the current position may be different from the
@@ -5776,8 +5821,6 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
                                  result = MOVE_NEWLINE_OR_CR;
                                  break;
                                }
-                             if (it->method == next_element_from_display_vector)
-                               it->face_id = it->saved_face_id;
                            }
 #endif /* HAVE_WINDOW_SYSTEM */
                        }
@@ -5862,8 +5905,6 @@ move_it_in_display_line_to (it, to_charpos, to_x, op)
                  result = MOVE_NEWLINE_OR_CR;
                  break;
                }
-             if (it->method == next_element_from_display_vector)
-               it->face_id = it->saved_face_id;
            }
 #endif /* HAVE_WINDOW_SYSTEM */
          result = MOVE_LINE_TRUNCATED;
@@ -6607,7 +6648,7 @@ message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
     }
   return 0;
 }
-
+\f
 
 /* Display an echo area message M with a specified length of NBYTES
    bytes.  The string may include null characters.  If M is 0, clear
@@ -11603,6 +11644,9 @@ 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);
@@ -14633,8 +14677,6 @@ display_line (it)
     {
       move_it_in_display_line_to (it, ZV, it->first_visible_x,
                                  MOVE_TO_POS | MOVE_TO_X);
-      if (it->method == next_element_from_display_vector)
-       it->face_id = it->saved_face_id;
     }
 
   /* Get the initial row height.  This is either the height of the
@@ -14794,8 +14836,6 @@ display_line (it)
                                  row->continued_p = 0;
                                  row->exact_window_width_line_p = 1;
                                }
-                             else if (it->method == next_element_from_display_vector)
-                               it->face_id = it->saved_face_id;
                            }
 #endif /* HAVE_WINDOW_SYSTEM */
                        }
@@ -14976,8 +15016,6 @@ display_line (it)
                      row->exact_window_width_line_p = 1;
                      goto at_end_of_line;
                    }
-                 if (it->method == next_element_from_display_vector)
-                   it->face_id = it->saved_face_id;
                }
            }
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -22176,6 +22214,8 @@ syms_of_xdisp ()
   staticpro (&Qfontification_functions);
   Qtrailing_whitespace = intern ("trailing-whitespace");
   staticpro (&Qtrailing_whitespace);
+  Qescape_glyph = intern ("escape-glyph");
+  staticpro (&Qescape_glyph);
   Qimage = intern ("image");
   staticpro (&Qimage);
   QCmap = intern (":map");