Fix bug #11063 with move_it_by_lines when there's a before-string at bol.
[bpt/emacs.git] / src / xdisp.c
index 6129c5e..dcd14a1 100644 (file)
@@ -1,6 +1,6 @@
 /* Display generation from window structure and buffer text.
 
-Copyright (C) 1985-1988, 1993-1995, 1997-2011  Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-1995, 1997-2012  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -1445,7 +1445,7 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y,
                     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
-                    prfoduced from the string, until we find the
+                    produced from the string, until we find the
                     rightmost glyph not from the string.  */
                  if (IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
                    {
@@ -1915,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;
@@ -2750,9 +2750,12 @@ init_iterator (struct it *it, struct window *w,
   if (charpos >= BUF_BEG (current_buffer))
     {
       it->end_charpos = ZV;
-      it->face_id = -1;
       IT_CHARPOS (*it) = charpos;
 
+      /* We will rely on `reseat' to set this up properly, via
+        handle_face_prop.  */
+      it->face_id = it->base_face_id;
+
       /* Compute byte position if not specified.  */
       if (bytepos < charpos)
        IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
@@ -2846,8 +2849,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);
@@ -3166,13 +3175,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);
@@ -3182,6 +3189,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
@@ -3660,7 +3673,9 @@ handle_face_prop (struct it *it)
             with, so that overlay strings appear in the same face as
             surrounding text, unless they specify their own
             faces.  */
-         base_face_id = underlying_face_id (it);
+         base_face_id = it->string_from_prefix_prop_p
+           ? DEFAULT_FACE_ID
+           : underlying_face_id (it);
        }
 
       new_face_id = face_at_string_position (it->w,
@@ -4080,29 +4095,41 @@ 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)
            {
              EMACS_INT bpos = CHAR_TO_BYTE (newpos);
-
-             if (FETCH_BYTE (bpos) == '\n'
-                 || (newpos > BEGV && FETCH_BYTE (bpos - 1) == '\n'))
+             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 the invisible text ends on a newline or the
-                    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.  (Implementation note: the
-                    call to reseat_1 is necessary, because it signals
-                    to the bidi iterator that it needs to reinit its
-                    internal information when the next element for
-                    display is requested.  */
                  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;
+                   }
                }
              else      /* Must use the slow method.  */
                {
@@ -4111,11 +4138,11 @@ handle_invisible_prop (struct it *it)
                     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.  */
+                    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,
@@ -4317,7 +4344,7 @@ handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
   int rv;
 
   if (CONSP (spec)
-      /* Simple specerties.  */
+      /* Simple specifications.  */
       && !EQ (XCAR (spec), Qimage)
       && !EQ (XCAR (spec), Qspace)
       && !EQ (XCAR (spec), Qwhen)
@@ -5131,6 +5158,12 @@ next_overlay_string (struct it *it)
       it->current.overlay_string_index = -1;
       it->n_overlay_strings = 0;
       it->overlay_strings_charpos = -1;
+      /* If there's an empty display string on the stack, pop the
+        stack, to resync the bidi iterator with IT's position.  Such
+        empty strings are pushed onto the stack in
+        get_overlay_strings_1.  */
+      if (it->sp > 0 && STRINGP (it->string) && !SCHARS (it->string))
+       pop_it (it);
 
       /* If we're at the end of the buffer, record that we have
         processed the overlay strings there already, so that
@@ -5428,8 +5461,15 @@ get_overlay_strings_1 (struct it *it, EMACS_INT charpos, int compute_stop_p)
       xassert (!compute_stop_p || it->sp == 0);
 
       /* When called from handle_stop, there might be an empty display
-         string loaded.  In that case, don't bother saving it.  */
-      if (!STRINGP (it->string) || SCHARS (it->string))
+         string loaded.  In that case, don't bother saving it.  But
+         don't use this optimization with the bidi iterator, since we
+         need the corresponding pop_it call to resync the bidi
+         iterator's position with IT's position, after we are done
+         with the overlay strings.  (The corresponding call to pop_it
+         in case of an empty display string is in
+         next_overlay_string.)  */
+      if (!(!it->bidi_p
+           && STRINGP (it->string) && !SCHARS (it->string)))
        push_it (it, NULL);
 
       /* Set up IT to deliver display elements from the first overlay
@@ -5538,6 +5578,7 @@ push_it (struct it *it, struct text_pos *position)
   p->font_height = it->font_height;
   p->voffset = it->voffset;
   p->string_from_display_prop_p = it->string_from_display_prop_p;
+  p->string_from_prefix_prop_p = it->string_from_prefix_prop_p;
   p->display_ellipsis_p = 0;
   p->line_wrap = it->line_wrap;
   p->bidi_p = it->bidi_p;
@@ -5647,6 +5688,7 @@ pop_it (struct it *it)
   it->font_height = p->font_height;
   it->voffset = p->voffset;
   it->string_from_display_prop_p = p->string_from_display_prop_p;
+  it->string_from_prefix_prop_p = p->string_from_prefix_prop_p;
   it->line_wrap = p->line_wrap;
   it->bidi_p = p->bidi_p;
   it->paragraph_embedding = p->paragraph_embedding;
@@ -6077,6 +6119,8 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
   it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
   it->sp = 0;
   it->string_from_display_prop_p = 0;
+  it->string_from_prefix_prop_p = 0;
+
   it->from_disp_prop_p = 0;
   it->face_before_selective_p = 0;
   if (it->bidi_p)
@@ -7324,7 +7368,7 @@ next_element_from_string (struct it *it)
   if (it->current.overlay_string_index >= 0)
     {
       /* Get the next character from an overlay string.  In overlay
-        strings, There is no field width or padding with spaces to
+        strings, there is no field width or padding with spaces to
         do.  */
       if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
        {
@@ -8922,7 +8966,6 @@ move_it_by_lines (struct it *it, int dvpos)
     {
       /* DVPOS == 0 means move to the start of the screen line.  */
       move_it_vertically_backward (it, 0);
-      xassert (it->current_x == 0 && it->hpos == 0);
       /* Let next call to line_bottom_y calculate real line height */
       last_height = 0;
     }
@@ -8930,7 +8973,20 @@ move_it_by_lines (struct it *it, int dvpos)
     {
       move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
       if (!IT_POS_VALID_AFTER_MOVE_P (it))
-       move_it_to (it, IT_CHARPOS (*it) + 1, -1, -1, -1, MOVE_TO_POS);
+       {
+         /* Only move to the next buffer position if we ended up in a
+            string from display property, not in an overlay string
+            (before-string or after-string).  That is because the
+            latter don't conceal the underlying buffer position, so
+            we can ask to move the iterator to the exact position we
+            are interested in.  Note that, even if we are already at
+            IT_CHARPOS (*it), the call below is not a no-op, as it
+            will detect that we are at the end of the string, pop the
+            iterator, and compute it->current_x and it->hpos
+            correctly.  */
+         move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
+                     -1, -1, -1, MOVE_TO_POS);
+       }
     }
   else
     {
@@ -10213,7 +10269,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.  */
@@ -13623,7 +13679,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;
@@ -13756,16 +13812,31 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
 
            chprop = Fget_char_property (make_number (glyph_pos), Qcursor,
                                         glyph->object);
+           if (!NILP (chprop))
+             {
+               /* If the string came from a `display' text property,
+                  look up the buffer position of that property and
+                  use that position to update bpos_max, as if we
+                  actually saw such a position in one of the row's
+                  glyphs.  This helps with supporting integer values
+                  of `cursor' property on the display string in
+                  situations where most or all of the row's buffer
+                  text is completely covered by display properties,
+                  so that no glyph with valid buffer positions is
+                  ever seen in the row.  */
+               EMACS_INT prop_pos =
+                 string_buffer_position_lim (glyph->object, pos_before,
+                                             pos_after, 0);
+
+               if (prop_pos >= pos_before)
+                 bpos_max = prop_pos - 1;
+             }
            if (INTEGERP (chprop))
              {
                bpos_covered = bpos_max + XINT (chprop);
                /* If the `cursor' property covers buffer positions up
                   to and including point, we should display cursor on
-                  this glyph.  Note that overlays and text properties
-                  with string values stop bidi reordering, so every
-                  buffer position to the left of the string is always
-                  smaller than any position to the right of the
-                  string.  Therefore, if a `cursor' property on one
+                  this glyph.  Note that, if a `cursor' property on one
                   of the string's characters has an integer value, we
                   will break out of the loop below _before_ we get to
                   the position match above.  IOW, integer values of
@@ -13825,6 +13896,15 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
 
            chprop = Fget_char_property (make_number (glyph_pos), Qcursor,
                                         glyph->object);
+           if (!NILP (chprop))
+             {
+               EMACS_INT prop_pos =
+                 string_buffer_position_lim (glyph->object, pos_before,
+                                             pos_after, 0);
+
+               if (prop_pos >= pos_before)
+                 bpos_max = prop_pos - 1;
+             }
            if (INTEGERP (chprop))
              {
                bpos_covered = bpos_max + XINT (chprop);
@@ -14109,7 +14189,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)
@@ -14339,7 +14419,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
@@ -14369,7 +14449,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;
        }
     }
 
@@ -15031,7 +15112,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 ();
@@ -15553,8 +15634,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.  */
@@ -15563,7 +15644,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
             accessible region of the buffer.  This can happen when we
             have just switched to a different buffer and/or changed
             its restriction.  In that case, startp is initialized to
-            the character position 1 (BEG) because we did not yet
+            the character position 1 (BEGV) because we did not yet
             have chance to display the buffer even once.  */
          && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
        {
@@ -15572,7 +15653,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
 
          SAVE_IT (it1, it, it1data);
          start_display (&it1, w, startp);
-         move_it_vertically (&it1, margin);
+         move_it_vertically (&it1, margin * FRAME_LINE_HEIGHT (f));
          margin_pos = IT_CHARPOS (it1);
          RESTORE_IT (&it, &it, it1data);
        }
@@ -15596,7 +15677,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
@@ -15716,6 +15797,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.  */
@@ -16264,7 +16364,10 @@ try_window_reusing_current_matrix (struct window *w)
           ++first_row_to_display)
        {
          if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
-             && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display))
+             && (PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)
+                 || (PT == MATRIX_ROW_END_CHARPOS (first_row_to_display)
+                     && first_row_to_display->ends_at_zv_p
+                     && pt_row == NULL)))
            pt_row = first_row_to_display;
        }
 
@@ -16356,7 +16459,9 @@ try_window_reusing_current_matrix (struct window *w)
       if (pt_row)
        {
          for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
-              row < bottom_row && PT >= MATRIX_ROW_END_CHARPOS (row);
+              row < bottom_row
+                && PT >= MATRIX_ROW_END_CHARPOS (row)
+                && !row->ends_at_zv_p;
               row++)
            {
              w->cursor.vpos++;
@@ -17020,7 +17125,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.  */
@@ -17949,6 +18054,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.
 
@@ -18035,17 +18157,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;
@@ -18096,8 +18208,10 @@ append_space_for_newline (struct it *it, int default_face_p)
          it->c = it->char_to_display = ' ';
          it->len = 1;
 
+         /* If the default face was remapped, be sure to use the
+            remapped face for the appended newline. */
          if (default_face_p)
-           it->face_id = DEFAULT_FACE_ID;
+           it->face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);
          else if (it->face_before_selective_p)
            it->face_id = it->saved_face_id;
          face = FACE_FROM_ID (it->f, it->face_id);
@@ -18133,7 +18247,7 @@ append_space_for_newline (struct it *it, int default_face_p)
 static void
 extend_face_to_end_of_line (struct it *it)
 {
-  struct face *face;
+  struct face *face, *default_face;
   struct frame *f = it->f;
 
   /* If line is already filled, do nothing.  Non window-system frames
@@ -18147,6 +18261,9 @@ extend_face_to_end_of_line (struct it *it)
         && !it->glyph_row->continued_p))
     return;
 
+  /* The default face, possibly remapped. */
+  default_face = FACE_FROM_ID (f, lookup_basic_face (f, DEFAULT_FACE_ID));
+
   /* Face extension extends the background and box of IT->face_id
      to the end of the line.  If the background equals the background
      of the frame, we don't have to do anything.  */
@@ -18184,7 +18301,7 @@ extend_face_to_end_of_line (struct it *it)
       if (it->glyph_row->used[TEXT_AREA] == 0)
        {
          it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
-         it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id;
+         it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
          it->glyph_row->used[TEXT_AREA] = 1;
        }
 #ifdef HAVE_WINDOW_SYSTEM
@@ -18220,7 +18337,7 @@ extend_face_to_end_of_line (struct it *it)
                 face, to avoid painting the rest of the window with
                 the region face, if the region ends at ZV.  */
              if (it->glyph_row->ends_at_zv_p)
-               it->face_id = DEFAULT_FACE_ID;
+               it->face_id = default_face->id;
              else
                it->face_id = face->id;
              append_stretch_glyph (it, make_number (0), stretch_width,
@@ -18253,7 +18370,7 @@ extend_face_to_end_of_line (struct it *it)
         avoid painting the rest of the window with the region face,
         if the region ends at ZV.  */
       if (it->glyph_row->ends_at_zv_p)
-       it->face_id = DEFAULT_FACE_ID;
+       it->face_id = default_face->id;
       else
        it->face_id = face->id;
 
@@ -18386,9 +18503,11 @@ cursor_row_p (struct glyph_row *row)
       /* Suppose the row ends on a string.
         Unless the row is continued, that means it ends on a newline
         in the string.  If it's anything other than a display string
-        (e.g. a before-string from an overlay), we don't want the
+        (e.g., a before-string from an overlay), we don't want the
         cursor there.  (This heuristic seems to give the optimal
-        behavior for the various types of multi-line strings.)  */
+        behavior for the various types of multi-line strings.)
+        One exception: if the string has `cursor' property on one of
+        its characters, we _do_ want the cursor there.  */
       if (CHARPOS (row->end.string_pos) >= 0)
        {
          if (row->continued_p)
@@ -18410,6 +18529,25 @@ cursor_row_p (struct glyph_row *row)
                    result =
                      (!NILP (prop)
                       && display_prop_string_p (prop, glyph->object));
+                   /* If there's a `cursor' property on one of the
+                      string's characters, this row is a cursor row,
+                      even though this is not a display string.  */
+                   if (!result)
+                     {
+                       Lisp_Object s = glyph->object;
+
+                       for ( ; glyph >= beg && EQ (glyph->object, s); --glyph)
+                         {
+                           EMACS_INT gpos = glyph->charpos;
+
+                           if (!NILP (Fget_char_property (make_number (gpos),
+                                                          Qcursor, s)))
+                             {
+                               result = 1;
+                               break;
+                             }
+                         }
+                     }
                    break;
                  }
            }
@@ -18448,7 +18586,7 @@ cursor_row_p (struct glyph_row *row)
    `line-prefix' and `wrap-prefix' properties.  */
 
 static int
-push_display_prop (struct it *it, Lisp_Object prop)
+push_prefix_prop (struct it *it, Lisp_Object prop)
 {
   struct text_pos pos =
     STRINGP (it->string) ? it->current.string_pos : it->current.pos;
@@ -18472,6 +18610,7 @@ push_display_prop (struct it *it, Lisp_Object prop)
        }
 
       it->string = prop;
+      it->string_from_prefix_prop_p = 1;
       it->multibyte_p = STRING_MULTIBYTE (it->string);
       it->current.overlay_string_index = -1;
       IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
@@ -18558,7 +18697,7 @@ handle_line_prefix (struct it *it)
       if (NILP (prefix))
        prefix = Vline_prefix;
     }
-  if (! NILP (prefix) && push_display_prop (it, prefix))
+  if (! NILP (prefix) && push_prefix_prop (it, prefix))
     {
       /* If the prefix is wider than the window, and we try to wrap
         it, it would acquire its own wrap prefix, and so on till the
@@ -18839,7 +18978,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));                     \
@@ -18894,8 +19034,13 @@ display_line (struct it *it)
          /* A row that displays right-to-left text must always have
             its last face extended all the way to the end of line,
             even if this row ends in ZV, because we still write to
-            the screen left to right.  */
-         if (row->reversed_p)
+            the screen left to right.  We also need to extend the
+            last face if the default face is remapped to some
+            different face, otherwise the functions that clear
+            portions of the screen will clear with the default face's
+            background color.  */
+         if (row->reversed_p
+             || lookup_basic_face (it->f, DEFAULT_FACE_ID) != DEFAULT_FACE_ID)
            extend_face_to_end_of_line (it);
          break;
        }
@@ -22688,7 +22833,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p)
     ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id;                \
     struct composition *cmp = composition_table[cmp_id];                   \
     XChar2b *char2b;                                                       \
-    struct glyph_string *first_s IF_LINT (= NULL);                         \
+    struct glyph_string *first_s = NULL;                                   \
     int n;                                                                 \
                                                                            \
     char2b = (XChar2b *) alloca ((sizeof *char2b) * cmp->glyph_len);       \
@@ -23627,7 +23772,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
@@ -23914,7 +24059,7 @@ produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
          sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c);
          str = buf;
        }
-      for (len = 0; str[len] && ASCII_BYTE_P (str[len]); len++)
+      for (len = 0; str[len] && ASCII_BYTE_P (str[len]) && len < 6; len++)
        code[len] = font->driver->encode_char (font, str[len]);
       upper_len = (len + 1) / 2;
       font->driver->text_extents (font, code, upper_len,
@@ -24350,7 +24495,7 @@ x_produce_glyphs (struct it *it)
          /* Initialize the bounding box.  */
          if (pcm)
            {
-             width = pcm->width;
+             width = cmp->glyph_len > 0 ? pcm->width : 0;
              ascent = pcm->ascent;
              descent = pcm->descent;
              lbearing = pcm->lbearing;
@@ -24358,7 +24503,7 @@ x_produce_glyphs (struct it *it)
            }
          else
            {
-             width = font->space_width;
+             width = cmp->glyph_len > 0 ? font->space_width : 0;
              ascent = FONT_BASE (font);
              descent = FONT_DESCENT (font);
              lbearing = 0;
@@ -24576,7 +24721,7 @@ x_produce_glyphs (struct it *it)
       if (it->descent < 0)
        it->descent = 0;
 
-      if (it->glyph_row)
+      if (it->glyph_row && cmp->glyph_len > 0)
        append_composite_glyph (it);
     }
   else if (it->what == IT_COMPOSITION)
@@ -24664,9 +24809,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.  */
@@ -24681,8 +24834,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;
@@ -25192,8 +25345,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;
 
@@ -25281,6 +25443,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)
@@ -25424,8 +25594,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;
     }
@@ -25595,9 +25783,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;
        }
@@ -25696,19 +25893,33 @@ 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);
 }
 
 
 \f
 /* Find the glyph rows START_ROW and END_ROW of window W that display
    characters between buffer positions START_CHARPOS and END_CHARPOS
-   (excluding END_CHARPOS).  This is similar to row_containing_pos,
-   but is more accurate when bidi reordering makes buffer positions
-   change non-linearly with glyph rows.  */
+   (excluding END_CHARPOS).  DISP_STRING is a display string that
+   covers these buffer positions.  This is similar to
+   row_containing_pos, but is more accurate when bidi reordering makes
+   buffer positions change non-linearly with glyph rows.  */
 static void
 rows_from_pos_range (struct window *w,
                     EMACS_INT start_charpos, EMACS_INT end_charpos,
+                    Lisp_Object disp_string,
                     struct glyph_row **start, struct glyph_row **end)
 {
   struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
@@ -25760,8 +25971,11 @@ rows_from_pos_range (struct window *w,
 
          while (g < e)
            {
-             if ((BUFFERP (g->object) || INTEGERP (g->object))
-                 && start_charpos <= g->charpos && g->charpos < end_charpos)
+             if (((BUFFERP (g->object) || INTEGERP (g->object))
+                  && start_charpos <= g->charpos && g->charpos < end_charpos)
+                 /* A glyph that comes from DISP_STRING is by
+                    definition to be highlighted.  */
+                 || EQ (g->object, disp_string))
                *start = row;
              g++;
            }
@@ -25780,14 +25994,15 @@ rows_from_pos_range (struct window *w,
   for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
     {
       struct glyph_row *next = row + 1;
+      EMACS_INT next_start = MATRIX_ROW_START_CHARPOS (next);
 
       if (!next->enabled_p
          || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
          /* The first row >= START whose range of displayed characters
             does NOT intersect the range [START_CHARPOS..END_CHARPOS]
             is the row END + 1.  */
-         || (start_charpos < MATRIX_ROW_START_CHARPOS (next)
-             && end_charpos < MATRIX_ROW_START_CHARPOS (next))
+         || (start_charpos < next_start
+             && end_charpos < next_start)
          || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
               || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
                   && !next->ends_at_zv_p
@@ -25806,12 +26021,29 @@ rows_from_pos_range (struct window *w,
             but none of the characters it displays are in the range, it is
             also END + 1. */
          struct glyph *g = next->glyphs[TEXT_AREA];
+         struct glyph *s = g;
          struct glyph *e = g + next->used[TEXT_AREA];
 
          while (g < e)
            {
-             if ((BUFFERP (g->object) || INTEGERP (g->object))
-                 && start_charpos <= g->charpos && g->charpos < end_charpos)
+             if (((BUFFERP (g->object) || INTEGERP (g->object))
+                  && ((start_charpos <= g->charpos && g->charpos < end_charpos)
+                      /* If the buffer position of the first glyph in
+                         the row is equal to END_CHARPOS, it means
+                         the last character to be highlighted is the
+                         newline of ROW, and we must consider NEXT as
+                         END, not END+1.  */
+                      || (((!next->reversed_p && g == s)
+                           || (next->reversed_p && g == e - 1))
+                          && (g->charpos == end_charpos
+                              /* Special case for when NEXT is an
+                                 empty line at ZV.  */
+                              || (g->charpos == -1
+                                  && !row->ends_at_zv_p
+                                  && next_start == end_charpos)))))
+                 /* A glyph that comes from DISP_STRING is by
+                    definition to be highlighted.  */
+                 || EQ (g->object, disp_string))
                break;
              g++;
            }
@@ -25820,6 +26052,13 @@ rows_from_pos_range (struct window *w,
              *end = row;
              break;
            }
+         /* The first row that ends at ZV must be the last to be
+            highlighted.  */
+         else if (next->ends_at_zv_p)
+           {
+             *end = next;
+             break;
+           }
        }
     }
 }
@@ -25855,7 +26094,7 @@ mouse_face_from_buffer_pos (Lisp_Object window,
   xassert (NILP (after_string) || STRINGP (after_string));
 
   /* Find the rows corresponding to START_CHARPOS and END_CHARPOS.  */
-  rows_from_pos_range (w, start_charpos, end_charpos, &r1, &r2);
+  rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
   if (r1 == NULL)
     r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
   /* If the before-string or display-string contains newlines,
@@ -26133,6 +26372,19 @@ mouse_face_from_buffer_pos (Lisp_Object window,
            }
          x += end->pixel_width;
        }
+      /* If we exited the above loop because we arrived at the last
+        glyph of the row, and its buffer position is still not in
+        range, it means the last character in range is the preceding
+        newline.  Bump the end column and x values to get past the
+        last glyph.  */
+      if (end == glyph
+         && BUFFERP (end->object)
+         && (end->charpos < start_charpos
+             || end->charpos >= end_charpos))
+       {
+         x += end->pixel_width;
+         ++end;
+       }
       hlinfo->mouse_face_end_x = x;
       hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
     }
@@ -28211,7 +28463,11 @@ all the functions in the list are called, with the frame as argument.  */);
 Each function is called with two arguments, the window and its new
 display-start position.  Note that these functions are also called by
 `set-window-buffer'.  Also note that the value of `window-end' is not
-valid when these functions are called.  */);
+valid when these functions are called.
+
+Warning: Do not use this feature to alter the way the window
+is scrolled.  It is not designed for that, and such use probably won't
+work.  */);
   Vwindow_scroll_functions = Qnil;
 
   DEFVAR_LISP ("window-text-change-functions",
@@ -28447,7 +28703,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",
@@ -28562,7 +28818,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)
 {