Spelling fixes.
[bpt/emacs.git] / src / xdisp.c
index 81cba29..0ddf955 100644 (file)
@@ -954,7 +954,7 @@ static int coords_in_mouse_face_p (struct window *, int, int);
 
    This is the height of W minus the height of a mode line, if any.  */
 
-inline int
+int
 window_text_bottom_y (struct window *w)
 {
   int height = WINDOW_TOTAL_HEIGHT (w);
@@ -968,7 +968,7 @@ window_text_bottom_y (struct window *w)
    means return the total width of W, not including fringes to
    the left and right of the window.  */
 
-inline int
+int
 window_box_width (struct window *w, int area)
 {
   int cols = XFASTINT (w->total_cols);
@@ -1007,7 +1007,7 @@ window_box_width (struct window *w, int area)
 /* Return the pixel height of the display area of window W, not
    including mode lines of W, if any.  */
 
-inline int
+int
 window_box_height (struct window *w)
 {
   struct frame *f = XFRAME (w->frame);
@@ -1054,7 +1054,7 @@ window_box_height (struct window *w)
    area AREA of window W.  AREA < 0 means return the left edge of the
    whole window, to the right of the left fringe of W.  */
 
-inline int
+int
 window_box_left_offset (struct window *w, int area)
 {
   int x;
@@ -1086,7 +1086,7 @@ window_box_left_offset (struct window *w, int area)
    area AREA of window W.  AREA < 0 means return the right edge of the
    whole window, to the left of the right fringe of W.  */
 
-inline int
+int
 window_box_right_offset (struct window *w, int area)
 {
   return window_box_left_offset (w, area) + window_box_width (w, area);
@@ -1096,7 +1096,7 @@ window_box_right_offset (struct window *w, int area)
    area AREA of window W.  AREA < 0 means return the left edge of the
    whole window, to the right of the left fringe of W.  */
 
-inline int
+int
 window_box_left (struct window *w, int area)
 {
   struct frame *f = XFRAME (w->frame);
@@ -1116,7 +1116,7 @@ window_box_left (struct window *w, int area)
    area AREA of window W.  AREA < 0 means return the right edge of the
    whole window, to the left of the right fringe of W.  */
 
-inline int
+int
 window_box_right (struct window *w, int area)
 {
   return window_box_left (w, area) + window_box_width (w, area);
@@ -1129,7 +1129,7 @@ window_box_right (struct window *w, int area)
    coordinates of the upper-left corner of the box.  Return in
    *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box.  */
 
-inline void
+void
 window_box (struct window *w, int area, int *box_x, int *box_y,
            int *box_width, int *box_height)
 {
@@ -1210,6 +1210,34 @@ line_bottom_y (struct it *it)
   return line_top_y + line_height;
 }
 
+/* Subroutine of pos_visible_p below.  Extracts a display string, if
+   any, from the display spec given as its argument.  */
+static Lisp_Object
+string_from_display_spec (Lisp_Object spec)
+{
+  if (CONSP (spec))
+    {
+      while (CONSP (spec))
+       {
+         if (STRINGP (XCAR (spec)))
+           return XCAR (spec);
+         spec = XCDR (spec);
+       }
+    }
+  else if (VECTORP (spec))
+    {
+      ptrdiff_t i;
+
+      for (i = 0; i < ASIZE (spec); i++)
+       {
+         if (STRINGP (AREF (spec, i)))
+           return AREF (spec, i);
+       }
+      return Qnil;
+    }
+
+  return spec;
+}
 
 /* Return 1 if position CHARPOS is visible in window W.
    CHARPOS < 0 means return info about WINDOW_END position.
@@ -1304,6 +1332,136 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y,
                    }
                }
            }
+         else if (IT_CHARPOS (it) != charpos)
+           {
+             Lisp_Object cpos = make_number (charpos);
+             Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
+             Lisp_Object string = string_from_display_spec (spec);
+             int newline_in_string = 0;
+
+             if (STRINGP (string))
+               {
+                 const char *s = SSDATA (string);
+                 const char *e = s + SBYTES (string);
+                 while (s < e)
+                   {
+                     if (*s++ == '\n')
+                       {
+                         newline_in_string = 1;
+                         break;
+                       }
+                   }
+               }
+             /* The tricky code below is needed because there's a
+                discrepancy between move_it_to and how we set cursor
+                when the display line ends in a newline from a
+                display string.  move_it_to will stop _after_ such
+                display strings, whereas set_cursor_from_row
+                conspires with cursor_row_p to place the cursor on
+                the first glyph produced from the display string.  */
+
+             /* We have overshoot PT because it is covered by a
+                display property whose value is a string.  If the
+                string includes embedded newlines, we are also in the
+                wrong display line.  Backtrack to the correct line,
+                where the display string begins.  */
+             if (newline_in_string)
+               {
+                 Lisp_Object startpos, endpos;
+                 EMACS_INT start, end;
+                 struct it it3;
+
+                 /* Find the first and the last buffer positions
+                    covered by the display string.  */
+                 endpos =
+                   Fnext_single_char_property_change (cpos, Qdisplay,
+                                                      Qnil, Qnil);
+                 startpos =
+                   Fprevious_single_char_property_change (endpos, Qdisplay,
+                                                          Qnil, Qnil);
+                 start = XFASTINT (startpos);
+                 end = XFASTINT (endpos);
+                 /* Move to the last buffer position before the
+                    display property.  */
+                 start_display (&it3, w, top);
+                 move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
+                 /* Move forward one more line if the position before
+                    the display string is a newline or if it is the
+                    rightmost character on a line that is
+                    continued or word-wrapped.  */
+                 if (it3.method == GET_FROM_BUFFER
+                     && it3.c == '\n')
+                   move_it_by_lines (&it3, 1);
+                 else if (move_it_in_display_line_to (&it3, -1,
+                                                      it3.current_x
+                                                      + it3.pixel_width,
+                                                      MOVE_TO_X)
+                          == MOVE_LINE_CONTINUED)
+                   {
+                     move_it_by_lines (&it3, 1);
+                     /* When we are under word-wrap, the #$@%!
+                        move_it_by_lines moves 2 lines, so we need to
+                        fix that up.  */
+                     if (it3.line_wrap == WORD_WRAP)
+                       move_it_by_lines (&it3, -1);
+                   }
+
+                 /* Record the vertical coordinate of the display
+                    line where we wound up.  */
+                 top_y = it3.current_y;
+                 if (it3.bidi_p)
+                   {
+                     /* When characters are reordered for display,
+                        the character displayed to the left of the
+                        display string could be _after_ the display
+                        property in the logical order.  Use the
+                        smallest vertical position of these two.  */
+                     start_display (&it3, w, top);
+                     move_it_to (&it3, end + 1, -1, -1, -1, MOVE_TO_POS);
+                     if (it3.current_y < top_y)
+                       top_y = it3.current_y;
+                   }
+                 /* Move from the top of the window to the beginning
+                    of the display line where the display string
+                    begins.  */
+                 start_display (&it3, w, top);
+                 move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
+                 /* Finally, advance the iterator until we hit the
+                    first display element whose character position is
+                    CHARPOS, or until the first newline from the
+                    display string, which signals the end of the
+                    display line.  */
+                 while (get_next_display_element (&it3))
+                   {
+                     PRODUCE_GLYPHS (&it3);
+                     if (IT_CHARPOS (it3) == charpos
+                         || ITERATOR_AT_END_OF_LINE_P (&it3))
+                       break;
+                     set_iterator_to_next (&it3, 0);
+                   }
+                 top_x = it3.current_x - it3.pixel_width;
+                 /* Normally, we would exit the above loop because we
+                    found the display element whose character
+                    position is CHARPOS.  For the contingency that we
+                    didn't, and stopped at the first newline from the
+                    display string, move back over the glyphs
+                    produced from the string, until we find the
+                    rightmost glyph not from the string.  */
+                 if (IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
+                   {
+                     struct glyph *g = it3.glyph_row->glyphs[TEXT_AREA]
+                                       + it3.glyph_row->used[TEXT_AREA];
+
+                     while (EQ ((g - 1)->object, string))
+                       {
+                         --g;
+                         top_x -= g->pixel_width;
+                       }
+                     xassert (g < it3.glyph_row->glyphs[TEXT_AREA]
+                                   + it3.glyph_row->used[TEXT_AREA]);
+                   }
+               }
+           }
 
          *x = top_x;
          *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
@@ -1757,7 +1915,7 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int
         environments with anti-aliased text: if the same text is
         drawn onto the same place multiple times, it gets thicker.
         If the overlap we are processing is for the erased cursor, we
-        take the intersection with the rectagle of the cursor.  */
+        take the intersection with the rectangle of the cursor.  */
       if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
        {
          XRectangle rc, r_save = r;
@@ -2605,9 +2763,13 @@ init_iterator (struct it *it, struct window *w,
       /* Do we need to reorder bidirectional text?  Not if this is a
         unibyte buffer: by definition, none of the single-byte
         characters are strong R2L, so no reordering is needed.  And
-        bidi.c doesn't support unibyte buffers anyway.  */
+        bidi.c doesn't support unibyte buffers anyway.  Also, don't
+        reorder while we are loading loadup.el, since the tables of
+        character properties needed for reordering are not yet
+        available.  */
       it->bidi_p =
-       !NILP (BVAR (current_buffer, bidi_display_reordering))
+       NILP (Vpurify_flag)
+       && !NILP (BVAR (current_buffer, bidi_display_reordering))
        && it->multibyte_p;
 
       /* If we are to reorder bidirectional text, init the bidi
@@ -2684,8 +2846,14 @@ start_display (struct it *it, struct window *w, struct text_pos pos)
                  || (new_x == it->last_visible_x
                      && FRAME_WINDOW_P (it->f))))
            {
-             if (it->current.dpvec_index >= 0
-                 || it->current.overlay_string_index >= 0)
+             if ((it->current.dpvec_index >= 0
+                  || it->current.overlay_string_index >= 0)
+                 /* If we are on a newline from a display vector or
+                    overlay string, then we are already at the end of
+                    a screen line; no need to go to the next line in
+                    that case, as this line is not really continued.
+                    (If we do go to the next line, C-e will not DTRT.)  */
+                 && it->c != '\n')
                {
                  set_iterator_to_next (it, 1);
                  move_it_in_display_line_to (it, -1, -1, 0);
@@ -2693,6 +2861,13 @@ start_display (struct it *it, struct window *w, struct text_pos pos)
 
              it->continuation_lines_width += it->current_x;
            }
+         /* If the character at POS is displayed via a display
+            vector, move_it_to above stops at the final glyph of
+            IT->dpvec.  To make the caller redisplay that character
+            again (a.k.a. start at POS), we need to reset the
+            dpvec_index to the beginning of IT->dpvec.  */
+         else if (it->current.dpvec_index >= 0)
+           it->current.dpvec_index = 0;
 
          /* We're starting a new display line, not affected by the
             height of the continued line, so clear the appropriate
@@ -2997,13 +3172,11 @@ compute_stop_pos (struct it *it)
   Lisp_Object object, limit, position;
   EMACS_INT charpos, bytepos;
 
-  /* If nowhere else, stop at the end.  */
-  it->stop_charpos = it->end_charpos;
-
   if (STRINGP (it->string))
     {
       /* Strings are usually short, so don't limit the search for
         properties.  */
+      it->stop_charpos = it->end_charpos;
       object = it->string;
       limit = Qnil;
       charpos = IT_STRING_CHARPOS (*it);
@@ -3013,6 +3186,12 @@ compute_stop_pos (struct it *it)
     {
       EMACS_INT pos;
 
+      /* If end_charpos is out of range for some reason, such as a
+        misbehaving display function, rationalize it (Bug#5984).  */
+      if (it->end_charpos > ZV)
+       it->end_charpos = ZV;
+      it->stop_charpos = it->end_charpos;
+
       /* If next overlay change is in front of the current stop pos
         (which is IT->end_charpos), stop there.  Note: value of
         next_overlay_change is point-max if no overlay change
@@ -3228,9 +3407,10 @@ compute_display_string_pos (struct text_pos *position,
 }
 
 /* Return the character position of the end of the display string that
-   started at CHARPOS.  A display string is either an overlay with
-   `display' property whose value is a string or a `display' text
-   property whose value is a string.  */
+   started at CHARPOS.  If there's no display string at CHARPOS,
+   return -1.  A display string is either an overlay with `display'
+   property whose value is a string or a `display' text property whose
+   value is a string.  */
 EMACS_INT
 compute_display_string_end (EMACS_INT charpos, struct bidi_string_data *string)
 {
@@ -3244,8 +3424,22 @@ compute_display_string_end (EMACS_INT charpos, struct bidi_string_data *string)
   if (charpos >= eob || (string->s && !STRINGP (object)))
     return eob;
 
+  /* It could happen that the display property or overlay was removed
+     since we found it in compute_display_string_pos above.  One way
+     this can happen is if JIT font-lock was called (through
+     handle_fontified_prop), and jit-lock-functions remove text
+     properties or overlays from the portion of buffer that includes
+     CHARPOS.  Muse mode is known to do that, for example.  In this
+     case, we return -1 to the caller, to signal that no display
+     string is actually present at CHARPOS.  See bidi_fetch_char for
+     how this is handled.
+
+     An alternative would be to never look for display properties past
+     it->stop_charpos.  But neither compute_display_string_pos nor
+     bidi_fetch_char that calls it know or care where the next
+     stop_charpos is.  */
   if (NILP (Fget_char_property (pos, Qdisplay, object)))
-    abort ();
+    return -1;
 
   /* Look forward for the first character where the `display' property
      changes.  */
@@ -3896,42 +4090,81 @@ handle_invisible_prop (struct it *it)
          while (invis_p);
 
          /* The position newpos is now either ZV or on visible text.  */
-         if (it->bidi_p && newpos < ZV)
+         if (it->bidi_p)
            {
-             /* With bidi iteration, the region of invisible text
-                could start and/or end in the middle of a non-base
-                embedding level.  Therefore, we need to skip
-                invisible text using the bidi iterator, starting at
-                IT's current position, until we find ourselves
-                outside the invisible text.  Skipping invisible text
-                _after_ bidi iteration avoids affecting the visual
-                order of the displayed text when invisible properties
-                are added or removed.  */
-             if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
+             EMACS_INT bpos = CHAR_TO_BYTE (newpos);
+             int on_newline =
+               bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
+             int after_newline =
+               newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
+
+             /* If the invisible text ends on a newline or on a
+                character after a newline, we can avoid the costly,
+                character by character, bidi iteration to NEWPOS, and
+                instead simply reseat the iterator there.  That's
+                because all bidi reordering information is tossed at
+                the newline.  This is a big win for modes that hide
+                complete lines, like Outline, Org, etc.  */
+             if (on_newline || after_newline)
                {
-                 /* If we were `reseat'ed to a new paragraph,
-                    determine the paragraph base direction.  We need
-                    to do it now because next_element_from_buffer may
-                    not have a chance to do it, if we are going to
-                    skip any text at the beginning, which resets the
-                    FIRST_ELT flag.  */
-                 bidi_paragraph_init (it->paragraph_embedding,
-                                      &it->bidi_it, 1);
+                 struct text_pos tpos;
+                 bidi_dir_t pdir = it->bidi_it.paragraph_dir;
+
+                 SET_TEXT_POS (tpos, newpos, bpos);
+                 reseat_1 (it, tpos, 0);
+                 /* If we reseat on a newline/ZV, we need to prep the
+                    bidi iterator for advancing to the next character
+                    after the newline/EOB, keeping the current paragraph
+                    direction (so that PRODUCE_GLYPHS does TRT wrt
+                    prepending/appending glyphs to a glyph row).  */
+                 if (on_newline)
+                   {
+                     it->bidi_it.first_elt = 0;
+                     it->bidi_it.paragraph_dir = pdir;
+                     it->bidi_it.ch = (bpos == ZV_BYTE) ? -1 : '\n';
+                     it->bidi_it.nchars = 1;
+                     it->bidi_it.ch_len = 1;
+                   }
                }
-             do
+             else      /* Must use the slow method.  */
                {
-                 bidi_move_to_visually_next (&it->bidi_it);
+                 /* With bidi iteration, the region of invisible text
+                    could start and/or end in the middle of a
+                    non-base embedding level.  Therefore, we need to
+                    skip invisible text using the bidi iterator,
+                    starting at IT's current position, until we find
+                    ourselves outside of the invisible text.
+                    Skipping invisible text _after_ bidi iteration
+                    avoids affecting the visual order of the
+                    displayed text when invisible properties are
+                    added or removed.  */
+                 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
+                   {
+                     /* If we were `reseat'ed to a new paragraph,
+                        determine the paragraph base direction.  We
+                        need to do it now because
+                        next_element_from_buffer may not have a
+                        chance to do it, if we are going to skip any
+                        text at the beginning, which resets the
+                        FIRST_ELT flag.  */
+                     bidi_paragraph_init (it->paragraph_embedding,
+                                          &it->bidi_it, 1);
+                   }
+                 do
+                   {
+                     bidi_move_to_visually_next (&it->bidi_it);
+                   }
+                 while (it->stop_charpos <= it->bidi_it.charpos
+                        && it->bidi_it.charpos < newpos);
+                 IT_CHARPOS (*it) = it->bidi_it.charpos;
+                 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
+                 /* If we overstepped NEWPOS, record its position in
+                    the iterator, so that we skip invisible text if
+                    later the bidi iteration lands us in the
+                    invisible region again. */
+                 if (IT_CHARPOS (*it) >= newpos)
+                   it->prev_stop = newpos;
                }
-             while (it->stop_charpos <= it->bidi_it.charpos
-                    && it->bidi_it.charpos < newpos);
-             IT_CHARPOS (*it) = it->bidi_it.charpos;
-             IT_BYTEPOS (*it) = it->bidi_it.bytepos;
-             /* If we overstepped NEWPOS, record its position in the
-                iterator, so that we skip invisible text if later the
-                bidi iteration lands us in the invisible region
-                again. */
-             if (IT_CHARPOS (*it) >= newpos)
-               it->prev_stop = newpos;
            }
          else
            {
@@ -5459,7 +5692,8 @@ pop_it (struct it *it)
                && IT_BYTEPOS (*it) == it->bidi_it.bytepos)
               || (STRINGP (it->object)
                   && IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
-                  && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos));
+                  && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)
+              || (CONSP (it->object) && it->method == GET_FROM_STRETCH));
     }
 }
 
@@ -5928,8 +6162,12 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string,
     it->multibyte_p = multibyte > 0;
 
   /* Bidirectional reordering of strings is controlled by the default
-     value of bidi-display-reordering.  */
-  it->bidi_p = !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
+     value of bidi-display-reordering.  Don't try to reorder while
+     loading loadup.el, as the necessary character property tables are
+     not yet available.  */
+  it->bidi_p =
+    NILP (Vpurify_flag)
+    && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
 
   if (s == NULL)
     {
@@ -6170,8 +6408,8 @@ get_next_display_element (struct it *it)
        {
          Lisp_Object dv;
          struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
-         enum { char_is_other = 0, char_is_nbsp, char_is_soft_hyphen }
-         nbsp_or_shy = char_is_other;
+         int nonascii_space_p = 0;
+         int nonascii_hyphen_p = 0;
          int c = it->c;        /* This is the character to display.  */
 
          if (! it->multibyte_p && ! ASCII_CHAR_P (c))
@@ -6223,10 +6461,15 @@ get_next_display_element (struct it *it)
              goto get_next;
            }
 
+         /* If `nobreak-char-display' is non-nil, we display
+            non-ASCII spaces and hyphens specially.  */
          if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
-           nbsp_or_shy = (c == 0xA0   ? char_is_nbsp
-                          : c == 0xAD ? char_is_soft_hyphen
-                          :             char_is_other);
+           {
+             if (c == 0xA0)
+               nonascii_space_p = 1;
+             else if (c == 0xAD || c == 0x2010 || c == 0x2011)
+               nonascii_hyphen_p = 1;
+           }
 
          /* Translate control characters into `\003' or `^C' form.
             Control characters coming from a display table entry are
@@ -6234,7 +6477,8 @@ get_next_display_element (struct it *it)
             the translation.  This could easily be changed but I
             don't believe that it is worth doing.
 
-            NBSP and SOFT-HYPEN are property translated too.
+            The characters handled by `nobreak-char-display' must be
+            translated too.
 
             Non-printable characters and raw-byte characters are also
             translated to octal form.  */
@@ -6245,14 +6489,15 @@ get_next_display_element (struct it *it)
                      && it->glyph_row
                      && (it->glyph_row->mode_line_p || it->avoid_cursor_p))
                  || (c != '\n' && c != '\t'))
-              : (nbsp_or_shy
+              : (nonascii_space_p
+                 || nonascii_hyphen_p
                  || CHAR_BYTE8_P (c)
                  || ! CHAR_PRINTABLE_P (c))))
            {
-             /* C is a control character, NBSP, SOFT-HYPEN, raw-byte,
-                or a non-printable character which must be displayed
-                either as '\003' or as `^C' where the '\\' and '^'
-                can be defined in the display table.  Fill
+             /* C is a control character, non-ASCII space/hyphen,
+                raw-byte, or a non-printable character which must be
+                displayed either as '\003' or as `^C' where the '\\'
+                and '^' can be defined in the display table.  Fill
                 IT->ctl_chars with glyphs for what we have to
                 display.  Then, set IT->dpvec to these glyphs.  */
              Lisp_Object gc;
@@ -6301,17 +6546,14 @@ get_next_display_element (struct it *it)
                  goto display_control;
                }
 
-             /* Handle non-break space in the mode where it only gets
+             /* Handle non-ascii space in the mode where it only gets
                 highlighting.  */
 
-             if (EQ (Vnobreak_char_display, Qt)
-                 && nbsp_or_shy == char_is_nbsp)
+             if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
                {
-                 /* Merge the no-break-space face into the current face.  */
+                 /* Merge `nobreak-space' into the current face.  */
                  face_id = merge_faces (it->f, Qnobreak_space, 0,
                                         it->face_id);
-
-                 c = ' ';
                  XSETINT (it->ctl_chars[0], ' ');
                  ctl_len = 1;
                  goto display_control;
@@ -6351,25 +6593,21 @@ get_next_display_element (struct it *it)
                  last_escape_glyph_merged_face_id = face_id;
                }
 
-             /* Handle soft hyphens in the mode where they only get
-                highlighting.  */
+             /* Draw non-ASCII hyphen with just highlighting: */
 
-             if (EQ (Vnobreak_char_display, Qt)
-                 && nbsp_or_shy == char_is_soft_hyphen)
+             if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
                {
                  XSETINT (it->ctl_chars[0], '-');
                  ctl_len = 1;
                  goto display_control;
                }
 
-             /* Handle non-break space and soft hyphen
-                with the escape glyph.  */
+             /* Draw non-ASCII space/hyphen with escape glyph: */
 
-             if (nbsp_or_shy)
+             if (nonascii_space_p || nonascii_hyphen_p)
                {
                  XSETINT (it->ctl_chars[0], escape_glyph);
-                 c = (nbsp_or_shy == char_is_nbsp ? ' ' : '-');
-                 XSETINT (it->ctl_chars[1], c);
+                 XSETINT (it->ctl_chars[1], nonascii_space_p ? ' ' : '-');
                  ctl_len = 2;
                  goto display_control;
                }
@@ -6947,7 +7185,6 @@ get_visually_first_element (struct it *it)
     }
   else if (it->bidi_it.charpos == bob
           || (!string_p
-              /* FIXME: Should support all Unicode line separators.  */
               && (FETCH_CHAR (it->bidi_it.bytepos - 1) == '\n'
                   || FETCH_CHAR (it->bidi_it.bytepos) == '\n')))
     {
@@ -7721,7 +7958,9 @@ move_it_in_display_line_to (struct it *it,
   ((op & MOVE_TO_POS) != 0                                     \
    && BUFFERP (it->object)                                     \
    && (IT_CHARPOS (*it) == to_charpos                          \
-       || (!it->bidi_p && IT_CHARPOS (*it) > to_charpos)       \
+       || ((!it->bidi_p                                                \
+           || BIDI_AT_BASE_LEVEL (it->bidi_it))                \
+          && IT_CHARPOS (*it) > to_charpos)                    \
        || (it->what == IT_COMPOSITION                          \
           && ((IT_CHARPOS (*it) > to_charpos                   \
                && to_charpos >= it->cmp_it.charpos)            \
@@ -7753,7 +7992,13 @@ move_it_in_display_line_to (struct it *it,
       if ((op & MOVE_TO_POS) != 0
          && BUFFERP (it->object)
          && it->method == GET_FROM_BUFFER
-         && ((!it->bidi_p && IT_CHARPOS (*it) > to_charpos)
+         && (((!it->bidi_p
+               /* When the iterator is at base embedding level, we
+                  are guaranteed that characters are delivered for
+                  display in strictly increasing order of their
+                  buffer positions.  */
+               || BIDI_AT_BASE_LEVEL (it->bidi_it))
+              && IT_CHARPOS (*it) > to_charpos)
              || (it->bidi_p
                  && (prev_method == GET_FROM_IMAGE
                      || prev_method == GET_FROM_STRETCH
@@ -8520,7 +8765,16 @@ move_it_vertically_backward (struct it *it, int dy)
       move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
                  MOVE_TO_POS | MOVE_TO_VPOS);
     }
-  while (!IT_POS_VALID_AFTER_MOVE_P (&it2));
+  while (!(IT_POS_VALID_AFTER_MOVE_P (&it2)
+          /* If we are in a display string which starts at START_POS,
+             and that display string includes a newline, and we are
+             right after that newline (i.e. at the beginning of a
+             display line), exit the loop, because otherwise we will
+             infloop, since move_it_to will see that it is already at
+             START_POS and will not move.  */
+          || (it2.method == GET_FROM_STRING
+              && IT_CHARPOS (it2) == start_pos
+              && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
   xassert (IT_CHARPOS (*it) >= BEGV);
   SAVE_IT (it3, it2, it3data);
 
@@ -8551,7 +8805,10 @@ move_it_vertically_backward (struct it *it, int dy)
         reordering.  We want to get to the character position
         that is immediately after the newline of the previous
         line.  */
-      if (it->bidi_p && IT_CHARPOS (*it) > BEGV
+      if (it->bidi_p
+         && !it->continuation_lines_width
+         && !STRINGP (it->string)
+         && IT_CHARPOS (*it) > BEGV
          && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
        {
          EMACS_INT nl_pos =
@@ -9978,7 +10235,7 @@ current_message_1 (EMACS_INT a1, Lisp_Object a2, EMACS_INT a3, EMACS_INT a4)
 }
 
 
-/* Push the current message on Vmessage_stack for later restauration
+/* Push the current message on Vmessage_stack for later restoration
    by restore_message.  Value is non-zero if the current message isn't
    empty.  This is a relatively infrequent operation, so it's not
    worth optimizing.  */
@@ -11847,6 +12104,7 @@ hscroll_window_tree (Lisp_Object window)
            = (desired_cursor_row->enabled_p
               ? desired_cursor_row
               : current_cursor_row);
+         int row_r2l_p = cursor_row->reversed_p;
 
          text_area_width = window_box_width (w, TEXT_AREA);
 
@@ -11854,11 +12112,31 @@ hscroll_window_tree (Lisp_Object window)
          h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
 
          if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->buffer))
-             && ((XFASTINT (w->hscroll)
-                  && w->cursor.x <= h_margin)
-                 || (cursor_row->enabled_p
-                     && cursor_row->truncated_on_right_p
-                     && (w->cursor.x >= text_area_width - h_margin))))
+             /* For left-to-right rows, hscroll when cursor is either
+                (i) inside the right hscroll margin, or (ii) if it is
+                inside the left margin and the window is already
+                hscrolled. */
+             && ((!row_r2l_p
+                  && ((XFASTINT (w->hscroll)
+                       && w->cursor.x <= h_margin)
+                      || (cursor_row->enabled_p
+                          && cursor_row->truncated_on_right_p
+                          && (w->cursor.x >= text_area_width - h_margin))))
+                 /* For right-to-left rows, the logic is similar,
+                    except that rules for scrolling to left and right
+                    are reversed.  E.g., if cursor.x <= h_margin, we
+                    need to hscroll "to the right" unconditionally,
+                    and that will scroll the screen to the left so as
+                    to reveal the next portion of the row.  */
+                 || (row_r2l_p
+                     && ((cursor_row->enabled_p
+                          /* FIXME: It is confusing to set the
+                             truncated_on_right_p flag when R2L rows
+                             are actually truncated on the left. */
+                          && cursor_row->truncated_on_right_p
+                          && w->cursor.x <= h_margin)
+                         || (XFASTINT (w->hscroll)
+                             && (w->cursor.x >= text_area_width - h_margin))))))
            {
              struct it it;
              int hscroll;
@@ -11893,7 +12171,9 @@ hscroll_window_tree (Lisp_Object window)
                                      ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
                                      : (text_area_width / 2))))
                          / FRAME_COLUMN_WIDTH (it.f);
-             else if (w->cursor.x >= text_area_width - h_margin)
+             else if ((!row_r2l_p
+                       && w->cursor.x >= text_area_width - h_margin)
+                      || (row_r2l_p && w->cursor.x <= h_margin))
                {
                  if (hscroll_relative_p)
                    wanted_x = text_area_width * (1 - hscroll_step_rel)
@@ -13365,7 +13645,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
   /* Non-zero means we've seen at least one glyph that came from a
      display string.  */
   int string_seen = 0;
-  /* Largest and smalles buffer positions seen so far during scan of
+  /* Largest and smallest buffer positions seen so far during scan of
      glyph row.  */
   EMACS_INT bpos_max = pos_before;
   EMACS_INT bpos_min = pos_after;
@@ -13633,21 +13913,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
              glyph--;
            }
        }
-      else if (match_with_avoid_cursor
-              /* A truncated row may not include PT among its
-                 character positions.  Setting the cursor inside the
-                 scroll margin will trigger recalculation of hscroll
-                 in hscroll_window_tree.  But if a display string
-                 covers point, defer to the string-handling code
-                 below to figure this out.  */
-              || (!string_seen
-                  && ((row->truncated_on_left_p && pt_old < bpos_min)
-                      || (row->truncated_on_right_p && pt_old > bpos_max)
-                      /* Zero-width characters produce no glyphs.  */
-                      || (!empty_line_p
-                          && (row->reversed_p
-                              ? glyph_after > glyphs_end
-                              : glyph_after < glyphs_end)))))
+      else if (match_with_avoid_cursor)
        {
          cursor = glyph_after;
          x = -1;
@@ -13788,6 +14054,26 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
              && row->continued_p)
            return 0;
        }
+      /* A truncated row may not include PT among its character positions.
+        Setting the cursor inside the scroll margin will trigger
+        recalculation of hscroll in hscroll_window_tree.  But if a
+        display string covers point, defer to the string-handling
+        code below to figure this out.  */
+      else if (row->truncated_on_left_p && pt_old < bpos_min)
+       {
+         cursor = glyph_before;
+         x = -1;
+       }
+      else if ((row->truncated_on_right_p && pt_old > bpos_max)
+              /* Zero-width characters produce no glyphs.  */
+              || (!empty_line_p
+                  && (row->reversed_p
+                      ? glyph_after > glyphs_end
+                      : glyph_after < glyphs_end)))
+       {
+         cursor = glyph_after;
+         x = -1;
+       }
     }
 
  compute_x:
@@ -13845,7 +14131,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
              || (STRINGP (g1->object)
                  && (!NILP (Fget_char_property (make_number (g1->charpos),
                                                Qcursor, g1->object))
-                     /* pevious candidate is from the same display
+                     /* previous candidate is from the same display
                         string as this one, and the display string
                         came from a text property */
                      || (EQ (g1->object, glyph->object)
@@ -14075,7 +14361,7 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
     {
       int scroll_margin_y;
 
-      /* Compute the pixel ypos of the scroll margin, then move it to
+      /* Compute the pixel ypos of the scroll margin, then move IT to
         either that ypos or PT, whichever comes first.  */
       start_display (&it, w, startp);
       scroll_margin_y = it.last_visible_y - this_scroll_margin
@@ -14105,7 +14391,8 @@ try_scrolling (Lisp_Object window, int just_this_one_p,
          if (dy > scroll_max)
            return SCROLLING_FAILED;
 
-         scroll_down_p = 1;
+         if (dy > 0)
+           scroll_down_p = 1;
        }
     }
 
@@ -14573,8 +14860,6 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
                 bidi-reordered rows.  */
              while (MATRIX_ROW_CONTINUATION_LINE_P (row))
                {
-                 xassert (row->enabled_p);
-                 --row;
                  /* If we hit the beginning of the displayed portion
                     without finding the first row of a continued
                     line, give up.  */
@@ -14583,7 +14868,8 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
                      rc = CURSOR_MOVEMENT_MUST_SCROLL;
                      break;
                    }
-
+                 xassert (row->enabled_p);
+                 --row;
                }
            }
          if (must_scroll)
@@ -14768,7 +15054,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
   int current_matrix_up_to_date_p = 0;
   int used_current_matrix_p = 0;
   /* This is less strict than current_matrix_up_to_date_p.
-     It indictes that the buffer contents and narrowing are unchanged.  */
+     It indicates that the buffer contents and narrowing are unchanged.  */
   int buffer_unchanged_p = 0;
   int temp_scroll_step = 0;
   int count = SPECPDL_INDEX ();
@@ -15290,8 +15576,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
        ? min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
        : 0;
       EMACS_INT margin_pos = CHARPOS (startp);
-      int scrolling_up;
       Lisp_Object aggressive;
+      int scrolling_up;
 
       /* If there is a scroll margin at the top of the window, find
         its character position.  */
@@ -15333,7 +15619,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
              pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
              if (pt_offset == 0 && float_amount > 0)
                pt_offset = 1;
-             if (pt_offset)
+             if (pt_offset && margin > 0)
                margin -= 1;
            }
          /* Compute how much to move the window start backward from
@@ -15453,6 +15739,25 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
          goto recenter;
        }
 
+      /* Users who set scroll-conservatively to a large number want
+        point just above/below the scroll margin.  If we ended up
+        with point's row partially visible, move the window start to
+        make that row fully visible and out of the margin.  */
+      if (scroll_conservatively > SCROLL_LIMIT)
+       {
+         int margin =
+           scroll_margin > 0
+           ? min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4)
+           : 0;
+         int move_down = w->cursor.vpos >= WINDOW_TOTAL_LINES (w) / 2;
+
+         move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
+         clear_glyph_matrix (w->desired_matrix);
+         if (1 == try_window (window, it.current.pos,
+                              TRY_WINDOW_CHECK_MARGINS))
+           goto done;
+       }
+
       /* 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.  */
@@ -15822,13 +16127,20 @@ try_window_reusing_current_matrix (struct window *w)
 
              start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
            }
-         /* If we have reached alignment,
-            we can copy the rest of the rows.  */
-         if (IT_CHARPOS (it) == CHARPOS (start))
+         /* If we have reached alignment, we can copy the rest of the
+            rows.  */
+         if (IT_CHARPOS (it) == CHARPOS (start)
+             /* Don't accept "alignment" inside a display vector,
+                since start_row could have started in the middle of
+                that same display vector (thus their character
+                positions match), and we have no way of telling if
+                that is the case.  */
+             && it.current.dpvec_index < 0)
            break;
 
          if (display_line (&it))
            last_text_row = it.glyph_row - 1;
+
        }
 
       /* A value of current_y < last_visible_y means that we stopped
@@ -16750,7 +17062,7 @@ try_window_id (struct window *w)
   last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
   if (last_unchanged_at_beg_row)
     {
-      /* Avoid starting to display in the moddle of a character, a TAB
+      /* Avoid starting to display in the middle of a character, a TAB
         for instance.  This is easier than to set up the iterator
         exactly, and it's not a frequent case, so the additional
         effort wouldn't really pay off.  */
@@ -17679,6 +17991,23 @@ insert_left_trunc_glyphs (struct it *it)
     }
 }
 
+/* Compute the hash code for ROW.  */
+unsigned
+row_hash (struct glyph_row *row)
+{
+  int area, k;
+  unsigned hashval = 0;
+
+  for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
+    for (k = 0; k < row->used[area]; ++k)
+      hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
+                 + row->glyphs[area][k].u.val
+                 + row->glyphs[area][k].face_id
+                 + row->glyphs[area][k].padding_p
+                 + (row->glyphs[area][k].type << 2));
+
+  return hashval;
+}
 
 /* Compute the pixel height and width of IT->glyph_row.
 
@@ -17765,17 +18094,7 @@ compute_line_metrics (struct it *it)
     }
 
   /* Compute a hash code for this row.  */
-  {
-    int area, i;
-    row->hash = 0;
-    for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
-      for (i = 0; i < row->used[area]; ++i)
-       row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
-                    + row->glyphs[area][i].u.val
-                    + row->glyphs[area][i].face_id
-                    + row->glyphs[area][i].padding_p
-                    + (row->glyphs[area][i].type << 2));
-  }
+  row->hash = row_hash (row);
 
   it->max_ascent = it->max_descent = 0;
   it->max_phys_ascent = it->max_phys_descent = 0;
@@ -18181,9 +18500,10 @@ static int
 push_display_prop (struct it *it, Lisp_Object prop)
 {
   struct text_pos pos =
-    (it->method == GET_FROM_STRING) ? it->current.string_pos : it->current.pos;
+    STRINGP (it->string) ? it->current.string_pos : it->current.pos;
 
   xassert (it->method == GET_FROM_BUFFER
+          || it->method == GET_FROM_DISPLAY_VECTOR
           || it->method == GET_FROM_STRING);
 
   /* We need to save the current buffer/string position, so it will be
@@ -18400,7 +18720,12 @@ find_row_edges (struct it *it, struct glyph_row *row,
                    seen_this_string = 1;
                }
              else
-               abort ();
+               /* If all the glyphs of the previous row were inserted
+                  by redisplay, it means the previous row was
+                  produced from a single newline, which is only
+                  possible if that newline came from the same string
+                  as the one which produced this ROW.  */
+               seen_this_string = 1;
            }
          else
            {
@@ -18416,7 +18741,7 @@ find_row_edges (struct it *it, struct glyph_row *row,
                    seen_this_string = 1;
                }
              else
-               abort ();
+               seen_this_string = 1;
            }
        }
       /* Take note of each display string that covers a newline only
@@ -18563,7 +18888,8 @@ display_line (struct it *it)
 #define RECORD_MAX_MIN_POS(IT)                                 \
   do                                                           \
     {                                                          \
-      int composition_p = (IT)->what == IT_COMPOSITION;                \
+      int composition_p = !STRINGP ((IT)->string)              \
+       && ((IT)->what == IT_COMPOSITION);                      \
       EMACS_INT current_pos =                                  \
        composition_p ? (IT)->cmp_it.charpos                    \
                      : IT_CHARPOS (*(IT));                     \
@@ -19106,9 +19432,18 @@ display_line (struct it *it)
       overlay_arrow_seen = 1;
     }
 
+  /* Highlight trailing whitespace.  */
+  if (!NILP (Vshow_trailing_whitespace))
+    highlight_trailing_whitespace (it->f, it->glyph_row);
+
   /* Compute pixel dimensions of this line.  */
   compute_line_metrics (it);
 
+  /* Implementation note: No changes in the glyphs of ROW or in their
+     faces can be done past this point, because compute_line_metrics
+     computes ROW's hash value and stores it within the glyph_row
+     structure.  */
+
   /* Record whether this row ends inside an ellipsis.  */
   row->ends_in_ellipsis_p
     = (it->method == GET_FROM_DISPLAY_VECTOR
@@ -19143,10 +19478,6 @@ display_line (struct it *it)
       && cursor_row_p (row))
     set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
 
-  /* Highlight trailing whitespace.  */
-  if (!NILP (Vshow_trailing_whitespace))
-    highlight_trailing_whitespace (it->f, it->glyph_row);
-
   /* Prepare for the next line.  This line starts horizontally at (X
      HPOS) = (0 0).  Vertical positions are incremented.  As a
      convenience for the caller, IT->glyph_row is set to the next
@@ -19192,7 +19523,10 @@ See also `bidi-paragraph-direction'.  */)
     }
 
   if (NILP (BVAR (buf, bidi_display_reordering))
-      || NILP (BVAR (buf, enable_multibyte_characters)))
+      || NILP (BVAR (buf, enable_multibyte_characters))
+      /* When we are loading loadup.el, the character property tables
+        needed for bidi iteration are not yet available.  */
+      || !NILP (Vpurify_flag))
     return Qleft_to_right;
   else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
     return BVAR (buf, bidi_paragraph_direction);
@@ -19205,6 +19539,7 @@ See also `bidi-paragraph-direction'.  */)
       EMACS_INT pos = BUF_PT (buf);
       EMACS_INT bytepos = BUF_PT_BYTE (buf);
       int c;
+      void *itb_data = bidi_shelve_cache ();
 
       set_buffer_temp (buf);
       /* bidi_paragraph_init finds the base direction of the paragraph
@@ -19217,27 +19552,28 @@ See also `bidi-paragraph-direction'.  */)
          pos--;
          bytepos = CHAR_TO_BYTE (pos);
        }
-      while ((c = FETCH_BYTE (bytepos)) == '\n'
-            || c == ' ' || c == '\t' || c == '\f')
+      if (fast_looking_at (build_string ("[\f\t ]*\n"),
+                          pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
        {
-         if (bytepos <= BEGV_BYTE)
-           break;
-         bytepos--;
-         pos--;
+         while ((c = FETCH_BYTE (bytepos)) == '\n'
+                || c == ' ' || c == '\t' || c == '\f')
+           {
+             if (bytepos <= BEGV_BYTE)
+               break;
+             bytepos--;
+             pos--;
+           }
+         while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
+           bytepos--;
        }
-      while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
-       bytepos--;
-      itb.charpos = pos;
-      itb.bytepos = bytepos;
-      itb.nchars = -1;
+      bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
+      itb.paragraph_dir = NEUTRAL_DIR;
       itb.string.s = NULL;
       itb.string.lstring = Qnil;
-      itb.frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ()); /* guesswork */
-      itb.first_elt = 1;
-      itb.separator_limit = -1;
-      itb.paragraph_dir = NEUTRAL_DIR;
-
+      itb.string.bufpos = 0;
+      itb.string.unibyte = 0;
       bidi_paragraph_init (NEUTRAL_DIR, &itb, 1);
+      bidi_unshelve_cache (itb_data, 0);
       set_buffer_temp (old);
       switch (itb.paragraph_dir)
        {
@@ -21768,7 +22104,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
 
 
 /* Get glyph code of character C in FONT in the two-byte form CHAR2B.
-   Retunr 1 if FONT has a glyph for C, otherwise return 0.  */
+   Return 1 if FONT has a glyph for C, otherwise return 0.  */
 
 static inline int
 get_char_glyph_code (int c, struct font *font, XChar2b *char2b)
@@ -21840,6 +22176,12 @@ fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
     }
   s->cmp_to = i;
 
+  if (s->face == NULL)
+    {
+      s->face = base_face->ascii_face;
+      s->font = s->face->font;
+    }
+
   /* All glyph strings for the same composition has the same width,
      i.e. the width set for the first component of the composition.  */
   s->width = s->first_glyph->pixel_width;
@@ -23335,7 +23677,7 @@ produce_stretch_glyph (struct it *it)
     {
       width = it->last_visible_x - it->current_x;
 #ifdef HAVE_WINDOW_SYSTEM
-      /* Subtact one more pixel from the stretch width, but only on
+      /* Subtract one more pixel from the stretch width, but only on
         GUI frames, since on a TTY each glyph is one "pixel" wide.  */
       width -= FRAME_WINDOW_P (it->f);
 #endif
@@ -24372,9 +24714,17 @@ x_produce_glyphs (struct it *it)
 void
 x_write_glyphs (struct glyph *start, int len)
 {
-  int x, hpos;
+  int x, hpos, chpos = updated_window->phys_cursor.hpos;
 
   xassert (updated_window && updated_row);
+  /* When the window is hscrolled, cursor hpos can legitimately be out
+     of bounds, but we draw the cursor at the corresponding window
+     margin in that case.  */
+  if (!updated_row->reversed_p && chpos < 0)
+    chpos = 0;
+  if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
+    chpos = updated_row->used[TEXT_AREA] - 1;
+
   BLOCK_INPUT;
 
   /* Write glyphs.  */
@@ -24389,8 +24739,8 @@ x_write_glyphs (struct glyph *start, int len)
   if (updated_area == TEXT_AREA
       && updated_window->phys_cursor_on_p
       && updated_window->phys_cursor.vpos == output_cursor.vpos
-      && updated_window->phys_cursor.hpos >= hpos
-      && updated_window->phys_cursor.hpos < hpos + len)
+      && chpos >= hpos
+      && chpos < hpos + len)
     updated_window->phys_cursor_on_p = 0;
 
   UNBLOCK_INPUT;
@@ -24900,8 +25250,17 @@ draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
     {
       int on_p = w->phys_cursor_on_p;
       int x1;
-      x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
-                       w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
+      int hpos = w->phys_cursor.hpos;
+
+      /* When the window is hscrolled, cursor hpos can legitimately be
+        out of bounds, but we draw the cursor at the corresponding
+        window margin in that case.  */
+      if (!row->reversed_p && hpos < 0)
+       hpos = 0;
+      if (row->reversed_p && hpos >= row->used[TEXT_AREA])
+       hpos = row->used[TEXT_AREA] - 1;
+
+      x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, hpos, hpos + 1,
                        hl, 0);
       w->phys_cursor_on_p = on_p;
 
@@ -24989,6 +25348,14 @@ erase_phys_cursor (struct window *w)
        : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
     goto mark_cursor_off;
 
+  /* When the window is hscrolled, cursor hpos can legitimately be out
+     of bounds, but we draw the cursor at the corresponding window
+     margin in that case.  */
+  if (!cursor_row->reversed_p && hpos < 0)
+    hpos = 0;
+  if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
+    hpos = cursor_row->used[TEXT_AREA] - 1;
+
   /* If the cursor is in the mouse face area, redisplay that when
      we clear the cursor.  */
   if (! NILP (hlinfo->mouse_face_window)
@@ -25132,8 +25499,26 @@ update_window_cursor (struct window *w, int on)
      of being deleted.  */
   if (w->current_matrix)
     {
+      int hpos = w->phys_cursor.hpos;
+      int vpos = w->phys_cursor.vpos;
+      struct glyph_row *row;
+
+      if (vpos >= w->current_matrix->nrows
+         || hpos >= w->current_matrix->matrix_w)
+       return;
+
+      row = MATRIX_ROW (w->current_matrix, vpos);
+
+      /* When the window is hscrolled, cursor hpos can legitimately be
+        out of bounds, but we draw the cursor at the corresponding
+        window margin in that case.  */
+      if (!row->reversed_p && hpos < 0)
+       hpos = 0;
+      if (row->reversed_p && hpos >= row->used[TEXT_AREA])
+       hpos = row->used[TEXT_AREA] - 1;
+
       BLOCK_INPUT;
-      display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
+      display_and_set_cursor (w, on, hpos, vpos,
                              w->phys_cursor.x, w->phys_cursor.y);
       UNBLOCK_INPUT;
     }
@@ -25303,9 +25688,18 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
       if (FRAME_WINDOW_P (f)
          && phys_cursor_on_p && !w->phys_cursor_on_p)
        {
+         int hpos = w->phys_cursor.hpos;
+
+         /* When the window is hscrolled, cursor hpos can legitimately be
+            out of bounds, but we draw the cursor at the corresponding
+            window margin in that case.  */
+         if (!row->reversed_p && hpos < 0)
+           hpos = 0;
+         if (row->reversed_p && hpos >= row->used[TEXT_AREA])
+           hpos = row->used[TEXT_AREA] - 1;
+
          BLOCK_INPUT;
-         display_and_set_cursor (w, 1,
-                                 w->phys_cursor.hpos, w->phys_cursor.vpos,
+         display_and_set_cursor (w, 1, hpos, w->phys_cursor.vpos,
                                  w->phys_cursor.x, w->phys_cursor.y);
          UNBLOCK_INPUT;
        }
@@ -25404,7 +25798,19 @@ coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
 int
 cursor_in_mouse_face_p (struct window *w)
 {
-  return coords_in_mouse_face_p (w, w->phys_cursor.hpos, w->phys_cursor.vpos);
+  int hpos = w->phys_cursor.hpos;
+  int vpos = w->phys_cursor.vpos;
+  struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
+
+  /* When the window is hscrolled, cursor hpos can legitimately be out
+     of bounds, but we draw the cursor at the corresponding window
+     margin in that case.  */
+  if (!row->reversed_p && hpos < 0)
+    hpos = 0;
+  if (row->reversed_p && hpos >= row->used[TEXT_AREA])
+    hpos = row->used[TEXT_AREA] - 1;
+
+  return coords_in_mouse_face_p (w, hpos, vpos);
 }
 
 
@@ -25538,7 +25944,7 @@ rows_from_pos_range (struct window *w,
    for the overlay or run of text properties specifying the mouse
    face.  BEFORE_STRING and AFTER_STRING, if non-nil, are a
    before-string and after-string that must also be highlighted.
-   COVER_STRING, if non-nil, is a display string that may cover some
+   DISP_STRING, if non-nil, is a display string that may cover some
    or all of the highlighted text.  */
 
 static void
@@ -25549,7 +25955,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
                            EMACS_INT end_charpos,
                            Lisp_Object before_string,
                            Lisp_Object after_string,
-                           Lisp_Object cover_string)
+                           Lisp_Object disp_string)
 {
   struct window *w = XWINDOW (window);
   struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
@@ -25558,7 +25964,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
   EMACS_INT ignore, pos;
   int x;
 
-  xassert (NILP (cover_string) || STRINGP (cover_string));
+  xassert (NILP (disp_string) || STRINGP (disp_string));
   xassert (NILP (before_string) || STRINGP (before_string));
   xassert (NILP (after_string) || STRINGP (after_string));
 
@@ -25568,7 +25974,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
     r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
   /* If the before-string or display-string contains newlines,
      rows_from_pos_range skips to its last row.  Move back.  */
-  if (!NILP (before_string) || !NILP (cover_string))
+  if (!NILP (before_string) || !NILP (disp_string))
     {
       struct glyph_row *prev;
       while ((prev = r1 - 1, prev >= first)
@@ -25580,7 +25986,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
          while (--glyph >= beg && INTEGERP (glyph->object));
          if (glyph < beg
              || !(EQ (glyph->object, before_string)
-                  || EQ (glyph->object, cover_string)))
+                  || EQ (glyph->object, disp_string)))
            break;
          r1 = prev;
        }
@@ -25605,10 +26011,10 @@ mouse_face_from_buffer_pos (Lisp_Object window,
        r2 = next;
     }
   /* The rest of the display engine assumes that mouse_face_beg_row is
-     either above below mouse_face_end_row or identical to it.  But
-     with bidi-reordered continued lines, the row for START_CHARPOS
-     could be below the row for END_CHARPOS.  If so, swap the rows and
-     store them in correct order.  */
+     either above mouse_face_end_row or identical to it.  But with
+     bidi-reordered continued lines, the row for START_CHARPOS could
+     be below the row for END_CHARPOS.  If so, swap the rows and store
+     them in correct order.  */
   if (r1->y > r2->y)
     {
       struct glyph_row *tem = r2;
@@ -25623,7 +26029,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
   hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
 
   /* For a bidi-reordered row, the positions of BEFORE_STRING,
-     AFTER_STRING, COVER_STRING, START_CHARPOS, and END_CHARPOS
+     AFTER_STRING, DISP_STRING, START_CHARPOS, and END_CHARPOS
      could be anywhere in the row and in any order.  The strategy
      below is to find the leftmost and the rightmost glyph that
      belongs to either of these 3 strings, or whose position is
@@ -25649,11 +26055,11 @@ mouse_face_from_buffer_pos (Lisp_Object window,
          x += glyph->pixel_width;
 
       /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING,
-        or COVER_STRING, and the first glyph from buffer whose
+        or DISP_STRING, and the first glyph from buffer whose
         position is between START_CHARPOS and END_CHARPOS.  */
       for (; glyph < end
             && !INTEGERP (glyph->object)
-            && !EQ (glyph->object, cover_string)
+            && !EQ (glyph->object, disp_string)
             && !(BUFFERP (glyph->object)
                  && (glyph->charpos >= start_charpos
                      && glyph->charpos < end_charpos));
@@ -25700,11 +26106,11 @@ mouse_face_from_buffer_pos (Lisp_Object window,
          ;
 
       /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING,
-        or COVER_STRING, and the first glyph from buffer whose
+        or DISP_STRING, and the first glyph from buffer whose
         position is between START_CHARPOS and END_CHARPOS.  */
       for (; glyph > end
             && !INTEGERP (glyph->object)
-            && !EQ (glyph->object, cover_string)
+            && !EQ (glyph->object, disp_string)
             && !(BUFFERP (glyph->object)
                  && (glyph->charpos >= start_charpos
                      && glyph->charpos < end_charpos));
@@ -25760,17 +26166,16 @@ mouse_face_from_buffer_pos (Lisp_Object window,
         row, and also blanks and stretch glyphs inserted by
         extend_face_to_end_of_line.  */
       while (end > glyph
-            && INTEGERP ((end - 1)->object)
-            && (end - 1)->charpos <= 0)
+            && INTEGERP ((end - 1)->object))
        --end;
       /* Scan the rest of the glyph row from the end, looking for the
         first glyph that comes from BEFORE_STRING, AFTER_STRING, or
-        COVER_STRING, or whose position is between START_CHARPOS
+        DISP_STRING, or whose position is between START_CHARPOS
         and END_CHARPOS */
       for (--end;
             end > glyph
             && !INTEGERP (end->object)
-            && !EQ (end->object, cover_string)
+            && !EQ (end->object, disp_string)
             && !(BUFFERP (end->object)
                  && (end->charpos >= start_charpos
                      && end->charpos < end_charpos));
@@ -25807,20 +26212,19 @@ mouse_face_from_buffer_pos (Lisp_Object window,
       x = r2->x;
       end++;
       while (end < glyph
-            && INTEGERP (end->object)
-            && end->charpos <= 0)
+            && INTEGERP (end->object))
        {
          x += end->pixel_width;
          ++end;
        }
       /* Scan the rest of the glyph row from the end, looking for the
         first glyph that comes from BEFORE_STRING, AFTER_STRING, or
-        COVER_STRING, or whose position is between START_CHARPOS
+        DISP_STRING, or whose position is between START_CHARPOS
         and END_CHARPOS */
       for ( ;
             end < glyph
             && !INTEGERP (end->object)
-            && !EQ (end->object, cover_string)
+            && !EQ (end->object, disp_string)
             && !(BUFFERP (end->object)
                  && (end->charpos >= start_charpos
                      && end->charpos < end_charpos));
@@ -26530,7 +26934,7 @@ void
 note_mouse_highlight (struct frame *f, int x, int y)
 {
   Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
-  enum window_part part;
+  enum window_part part = ON_NOTHING;
   Lisp_Object window;
   struct window *w;
   Cursor cursor = No_Cursor;
@@ -26564,11 +26968,14 @@ note_mouse_highlight (struct frame *f, int x, int y)
   /* Which window is that in?  */
   window = window_from_coordinates (f, x, y, &part, 1);
 
-  /* If we were displaying active text in another window, clear that.
-     Also clear if we move out of text area in same window.  */
+  /* If displaying active text in another window, clear that.  */
   if (! EQ (window, hlinfo->mouse_face_window)
-      || (part != ON_TEXT && part != ON_MODE_LINE && part != ON_HEADER_LINE
-         && !NILP (hlinfo->mouse_face_window)))
+      /* Also clear if we move out of text area in same window.  */
+      || (!NILP (hlinfo->mouse_face_window)
+         && !NILP (window)
+         && part != ON_TEXT
+         && part != ON_MODE_LINE
+         && part != ON_HEADER_LINE))
     clear_mouse_face (hlinfo);
 
   /* Not on a window -> return.  */
@@ -26621,7 +27028,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
       && XFASTINT (w->last_modified) == BUF_MODIFF (b)
       && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
     {
-      int hpos, vpos, dx, dy, area;
+      int hpos, vpos, dx, dy, area = LAST_AREA;
       EMACS_INT pos;
       struct glyph *glyph;
       Lisp_Object object;
@@ -26812,7 +27219,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
              /* The mouse-highlighting, if any, comes from an overlay
                 or text property in the buffer.  */
              Lisp_Object buffer IF_LINT (= Qnil);
-             Lisp_Object cover_string IF_LINT (= Qnil);
+             Lisp_Object disp_string IF_LINT (= Qnil);
 
              if (STRINGP (object))
                {
@@ -26826,13 +27233,13 @@ note_mouse_highlight (struct frame *f, int x, int y)
                      mouse_face = get_char_property_and_overlay
                        (make_number (pos), Qmouse_face, w->buffer, &overlay);
                      buffer = w->buffer;
-                     cover_string = object;
+                     disp_string = object;
                    }
                }
              else
                {
                  buffer = object;
-                 cover_string = Qnil;
+                 disp_string = Qnil;
                }
 
              if (!NILP (mouse_face))
@@ -26881,10 +27288,14 @@ note_mouse_highlight (struct frame *f, int x, int y)
                    }
 
                  mouse_face_from_buffer_pos (window, hlinfo, pos,
-                                             XFASTINT (before),
-                                             XFASTINT (after),
+                                             NILP (before)
+                                             ? 1
+                                             : XFASTINT (before),
+                                             NILP (after)
+                                             ? BUF_Z (XBUFFER (buffer))
+                                             : XFASTINT (after),
                                              before_string, after_string,
-                                             cover_string);
+                                             disp_string);
                  cursor = No_Cursor;
                }
            }
@@ -27682,7 +28093,6 @@ syms_of_xdisp (void)
   DEFSYM (Qhollow, "hollow");
   DEFSYM (Qhand, "hand");
   DEFSYM (Qarrow, "arrow");
-  DEFSYM (Qtext, "text");
   DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
 
   list_of_error = Fcons (Fcons (intern_c_string ("error"),
@@ -27744,12 +28154,18 @@ The face used for trailing whitespace is `trailing-whitespace'.  */);
   Vshow_trailing_whitespace = Qnil;
 
   DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
-    doc: /* *Control highlighting of nobreak space and soft hyphen.
-A value of t means highlight the character itself (for nobreak space,
-use face `nobreak-space').
-A value of nil means no highlighting.
-Other values mean display the escape glyph followed by an ordinary
-space or ordinary hyphen.  */);
+    doc: /* Control highlighting of non-ASCII space and hyphen chars.
+If the value is t, Emacs highlights non-ASCII chars which have the
+same appearance as an ASCII space or hyphen, using the `nobreak-space'
+or `escape-glyph' face respectively.
+
+U+00A0 (no-break space), U+00AD (soft hyphen), U+2010 (hyphen), and
+U+2011 (non-breaking hyphen) are affected.
+
+Any other non-nil value means to display these characters as a escape
+glyph followed by an ordinary space or hyphen.
+
+A value of nil means no special handling of these characters.  */);
   Vnobreak_char_display = Qt;
 
   DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
@@ -28145,7 +28561,7 @@ To add a prefix to continuation lines, use `wrap-prefix'.  */);
   DEFVAR_INT ("overline-margin", overline_margin,
               doc: /* *Space between overline and text, in pixels.
 The default value is 2: the height of the overline (1 pixel) plus 1 pixel
-margin to the caracter height.  */);
+margin to the character height.  */);
   overline_margin = 2;
 
   DEFVAR_INT ("underline-minimum-offset",
@@ -28260,7 +28676,8 @@ init_xdisp (void)
 
 /* Platform-independent portion of hourglass implementation. */
 
-/* Return non-zero if houglass timer has been started or hourglass is shown.  */
+/* Return non-zero if hourglass timer has been started or hourglass is
+   shown.  */
 int
 hourglass_started (void)
 {