diff options
Diffstat (limited to 'src/xdisp.c')
-rw-r--r-- | src/xdisp.c | 646 |
1 files changed, 453 insertions, 193 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index aeaf8b34652..140d71129f3 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2508,7 +2508,7 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int r.x = s->clip_head->x; } if (s->clip_tail) - if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width) + if (r.x + (int) r.width > s->clip_tail->x + s->clip_tail->background_width) { if (s->clip_tail->x + s->clip_tail->background_width >= r.x) r.width = s->clip_tail->x + s->clip_tail->background_width - r.x; @@ -2588,7 +2588,7 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent); if (height < r.height) { - max_y = r.y + r.height; + max_y = r.y + (int) r.height; r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height)); r.height = min (max_y - r.y, height); } @@ -2629,7 +2629,7 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int if (s->for_overlaps & OVERLAPS_PRED) { rs[i] = r; - if (r.y + r.height > row_y) + if (r.y + (int) r.height > row_y) { if (r.y < row_y) rs[i].height = row_y - r.y; @@ -2643,10 +2643,10 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int rs[i] = r; if (r.y < row_y + s->row->visible_height) { - if (r.y + r.height > row_y + s->row->visible_height) + if (r.y + (int) r.height > row_y + s->row->visible_height) { rs[i].y = row_y + s->row->visible_height; - rs[i].height = r.y + r.height - rs[i].y; + rs[i].height = r.y + (int) r.height - rs[i].y; } else rs[i].height = 0; @@ -2831,7 +2831,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) text_glyph: gr = 0; gy = 0; for (; r <= end_row && r->enabled_p; ++r) - if (r->y + r->height > y) + if (r->y + (int) r->height > y) { gr = r; gy = r->y; break; @@ -2931,7 +2931,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) row_glyph: gr = 0, gy = 0; for (; r <= end_row && r->enabled_p; ++r) - if (r->y + r->height > y) + if (r->y + (int) r->height > y) { gr = r; gy = r->y; break; @@ -3072,10 +3072,24 @@ dsafe__call (bool inhibit_quit, Lisp_Object (f) (ptrdiff_t, Lisp_Object *), return val; } +static Lisp_Object +funcall_with_backtraces (ptrdiff_t nargs, Lisp_Object *args) +{ + /* If an error is signaled during a Lisp hook in redisplay, write a + backtrace into the buffer *Redisplay-trace*. */ + push_handler_bind (list_of_error, Qdebug_early__muted, 0); + Lisp_Object res = Ffuncall (nargs, args); + pop_handler (); + return res; +} + #define SAFE_CALLMANY(inhibit_quit, f, array) \ - dsafe__call ((inhibit_quit), f, ARRAYELTS (array), array) -#define dsafe_calln(inhibit_quit, ...) \ - SAFE_CALLMANY ((inhibit_quit), Ffuncall, ((Lisp_Object []) {__VA_ARGS__})) + dsafe__call (inhibit_quit, f, ARRAYELTS (array), array) +#define dsafe_calln(inhibit_quit, ...) \ + SAFE_CALLMANY (inhibit_quit, \ + backtrace_on_redisplay_error \ + ? funcall_with_backtraces : Ffuncall, \ + ((Lisp_Object []) {__VA_ARGS__})) static Lisp_Object dsafe_call1 (Lisp_Object f, Lisp_Object arg) @@ -3807,7 +3821,7 @@ start_display (struct it *it, struct window *w, struct text_pos pos) it->current_y = first_y; it->vpos = 0; - it->current_x = it->hpos = 0; + it->current_x = it->hpos = it->wrap_prefix_width = 0; } } } @@ -4331,10 +4345,7 @@ compute_stop_pos (struct it *it) } } - if (it->cmp_it.id < 0 - && (STRINGP (it->string) - || ((!it->bidi_p || it->bidi_it.scan_dir >= 0) - && it->cmp_it.stop_pos <= IT_CHARPOS (*it)))) + if (it->cmp_it.id < 0) { ptrdiff_t stoppos = it->end_charpos; @@ -4342,8 +4353,10 @@ compute_stop_pos (struct it *it) an automatic composition, limit the search of composable characters to that position. */ if (it->bidi_p && it->bidi_it.scan_dir < 0) - stoppos = -1; - else if (cmp_limit_pos > 0) + stoppos = bidi_level_start (it->bidi_it.resolved_level) - 1; + else if (!STRINGP (it->string) + && it->cmp_it.stop_pos <= IT_CHARPOS (*it) + && cmp_limit_pos > 0) stoppos = cmp_limit_pos; /* Force composition_compute_stop_pos avoid the costly search for static compositions, since those were already found by @@ -5048,31 +5061,169 @@ handle_invisible_prop (struct it *it) { enum prop_handled handled = HANDLED_NORMALLY; int invis; - Lisp_Object prop; + ptrdiff_t curpos, endpos; + Lisp_Object prop, pos, overlay; + /* Get the value of the invisible text property at the current + position. Value will be nil if there is no such property. */ if (STRINGP (it->string)) { - Lisp_Object end_charpos, limit; + curpos = IT_STRING_CHARPOS (*it); + endpos = SCHARS (it->string); + pos = make_fixnum (curpos); + prop = Fget_text_property (pos, Qinvisible, it->string); + } + else /* buffer */ + { + curpos = IT_CHARPOS (*it); + endpos = ZV; + pos = make_fixnum (curpos); + prop = get_char_property_and_overlay (pos, Qinvisible, it->window, + &overlay); + } - /* Get the value of the invisible text property at the - current position. Value will be nil if there is no such - property. */ - end_charpos = make_fixnum (IT_STRING_CHARPOS (*it)); - prop = Fget_text_property (end_charpos, Qinvisible, it->string); - invis = TEXT_PROP_MEANS_INVISIBLE (prop); + /* Do we have anything to do here? */ + invis = TEXT_PROP_MEANS_INVISIBLE (prop); + if (invis == 0 || curpos >= it->end_charpos) + return handled; - if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos) + /* If not bidi, or the bidi iteration is at base paragraph level, we + can use a faster method; otherwise we need to check invisibility + of every character while bidi-iterating out of invisible text. */ + bool slow = it->bidi_p && !BIDI_AT_BASE_LEVEL (it->bidi_it); + /* Record whether we have to display an ellipsis for the + invisible text. */ + bool display_ellipsis_p = (invis == 2); + + handled = HANDLED_RECOMPUTE_PROPS; + + if (slow) + { + if (it->bidi_it.first_elt && it->bidi_it.charpos < endpos) + bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true); + + if (STRINGP (it->string)) { - /* Record whether we have to display an ellipsis for the - invisible text. */ - bool display_ellipsis_p = (invis == 2); - ptrdiff_t len, endpos; + bool done = false; + /* Bidi-iterate out of the invisible part of the string. */ + do + { + bidi_move_to_visually_next (&it->bidi_it); + if (it->bidi_it.charpos < 0 || it->bidi_it.charpos >= endpos) + done = true; + else + { + pos = make_fixnum (it->bidi_it.charpos); + prop = Fget_text_property (pos, Qinvisible, it->string); + invis = TEXT_PROP_MEANS_INVISIBLE (prop); + /* If there are adjacent invisible texts, don't lose + the second one's ellipsis. */ + if (invis == 2) + display_ellipsis_p = true; + } + } + while (!done && invis != 0); - handled = HANDLED_RECOMPUTE_PROPS; + if (display_ellipsis_p) + it->ellipsis_p = true; + IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; + IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; + if (IT_STRING_BYTEPOS (*it) >= endpos) + { + /* The rest of the string is invisible. If this is an + overlay string, proceed with the next overlay string + or whatever comes and return a character from there. */ + if (it->current.overlay_string_index >= 0 + && !display_ellipsis_p) + { + next_overlay_string (it); + /* Don't check for overlay strings when we just + finished processing them. */ + handled = HANDLED_OVERLAY_STRING_CONSUMED; + } + } + } + else + { + bool done = false; + /* Bidi-iterate out of the invisible text. */ + do + { + bidi_move_to_visually_next (&it->bidi_it); + if (it->bidi_it.charpos < BEGV || it->bidi_it.charpos >= endpos) + done = true; + else + { + pos = make_fixnum (it->bidi_it.charpos); + prop = Fget_char_property (pos, Qinvisible, it->window); + invis = TEXT_PROP_MEANS_INVISIBLE (prop); + /* If there are adjacent invisible texts, don't lose + the second one's ellipsis. */ + if (invis == 2) + display_ellipsis_p = true; + } + } + while (!done && invis != 0); + + IT_CHARPOS (*it) = it->bidi_it.charpos; + IT_BYTEPOS (*it) = it->bidi_it.bytepos; + if (display_ellipsis_p) + { + /* Make sure that the glyphs of the ellipsis will get + correct `charpos' values. See below for detailed + explanation why this is needed. */ + it->position.charpos = IT_CHARPOS (*it) - 1; + it->position.bytepos = CHAR_TO_BYTE (it->position.charpos); + } + /* If there are before-strings at the start of invisible + text, and the text is invisible because of a text + property, arrange to show before-strings because 20.x did + it that way. (If the text is invisible because of an + overlay property instead of a text property, this is + already handled in the overlay code.) */ + if (NILP (overlay) + && get_overlay_strings (it, it->stop_charpos)) + { + handled = HANDLED_RECOMPUTE_PROPS; + if (it->sp > 0) + { + it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p; + /* The call to get_overlay_strings above recomputes + it->stop_charpos, but it only considers changes + in properties and overlays beyond iterator's + current position. This causes us to miss changes + that happen exactly where the invisible property + ended. So we play it safe here and force the + iterator to check for potential stop positions + immediately after the invisible text. Note that + if get_overlay_strings returns true, it + normally also pushed the iterator stack, so we + need to update the stop position in the slot + below the current one. */ + it->stack[it->sp - 1].stop_charpos + = CHARPOS (it->stack[it->sp - 1].current.pos); + } + } + else if (display_ellipsis_p) + { + it->ellipsis_p = true; + /* Let the ellipsis display before + considering any properties of the following char. + Fixes jasonr@gnu.org 01 Oct 07 bug. */ + handled = HANDLED_RETURN; + } + } + } + else if (STRINGP (it->string)) + { + Lisp_Object end_charpos = pos, limit; + + if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos) + { + ptrdiff_t len = endpos; /* Get the position at which the next visible text can be found in IT->string, if any. */ - endpos = len = SCHARS (it->string); XSETINT (limit, len); do { @@ -5123,7 +5274,7 @@ handle_invisible_prop (struct it *it) IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; - if (IT_CHARPOS (*it) >= endpos) + if (IT_STRING_CHARPOS (*it) >= endpos) it->prev_stop = endpos; } else @@ -5153,27 +5304,14 @@ handle_invisible_prop (struct it *it) } } } - else + else /* we are iterating over buffer text at base paragraph level */ { - ptrdiff_t newpos, next_stop, start_charpos, tem; - Lisp_Object pos, overlay; - - /* First of all, is there invisible text at this position? */ - tem = start_charpos = IT_CHARPOS (*it); - pos = make_fixnum (tem); - prop = get_char_property_and_overlay (pos, Qinvisible, it->window, - &overlay); - invis = TEXT_PROP_MEANS_INVISIBLE (prop); + ptrdiff_t newpos, next_stop, tem = curpos; + Lisp_Object pos; /* If we are on invisible text, skip over it. */ - if (invis != 0 && start_charpos < it->end_charpos) + if (invis != 0 && curpos < it->end_charpos) { - /* Record whether we have to display an ellipsis for the - invisible text. */ - bool display_ellipsis_p = invis == 2; - - handled = HANDLED_RECOMPUTE_PROPS; - /* Loop skipping over invisible text. The loop is left at ZV or with IT on the first char being visible again. */ do @@ -5473,9 +5611,6 @@ display_min_width (struct it *it, ptrdiff_t bufpos, if (!NILP (it->min_width_property) && !EQ (width_spec, it->min_width_property)) { - if (!it->glyph_row) - return; - /* When called from display_string (i.e., the mode line), we're being called with a string as the object, and we may be called with many sub-strings belonging to the same @@ -5518,7 +5653,13 @@ display_min_width (struct it *it, ptrdiff_t bufpos, it->object = list3 (Qspace, QCwidth, w); produce_stretch_glyph (it); if (it->area == TEXT_AREA) - it->current_x += it->pixel_width; + { + it->current_x += it->pixel_width; + + if (it->continuation_lines_width + && it->string_from_prefix_prop_p) + it->wrap_prefix_width = it->current_x; + } it->min_width_property = Qnil; } } @@ -6761,7 +6902,7 @@ load_overlay_strings (struct it *it, ptrdiff_t charpos) \ entries[n].string = (STRING); \ entries[n].overlay = (OVERLAY); \ - priority = Foverlay_get ((OVERLAY), Qpriority); \ + priority = Foverlay_get (OVERLAY, Qpriority); \ entries[n].priority = FIXNUMP (priority) ? XFIXNUM (priority) : 0; \ entries[n].after_string_p = (AFTER_P); \ ++n; \ @@ -8571,9 +8712,8 @@ set_iterator_to_next (struct it *it, bool reseat_p) ptrdiff_t stop = it->end_charpos; if (it->bidi_it.scan_dir < 0) - /* Now we are scanning backward and don't know - where to stop. */ - stop = -1; + /* Now we are scanning backward; figure out where to stop. */ + stop = bidi_level_start (it->bidi_it.resolved_level) - 1; composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it), IT_BYTEPOS (*it), stop, Qnil, true); } @@ -8604,7 +8744,7 @@ set_iterator_to_next (struct it *it, bool reseat_p) re-compute the stop position for composition. */ ptrdiff_t stop = it->end_charpos; if (it->bidi_it.scan_dir < 0) - stop = -1; + stop = bidi_level_start (it->bidi_it.resolved_level) - 1; composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it), IT_BYTEPOS (*it), stop, Qnil, true); @@ -9049,7 +9189,9 @@ get_visually_first_element (struct it *it) bytepos = IT_BYTEPOS (*it); } if (it->bidi_it.scan_dir < 0) - stop = -1; + stop = STRINGP (it->string) + ? -1 + : bidi_level_start (it->bidi_it.resolved_level) - 1; composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop, it->string, true); } @@ -9553,9 +9695,10 @@ next_element_from_buffer (struct it *it) && PT < it->end_charpos) ? PT : it->end_charpos; } else - stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos; - if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it), - stop) + stop = it->bidi_it.scan_dir < 0 + ? bidi_level_start (it->bidi_it.resolved_level) - 1 + : it->end_charpos; + if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it), stop) && next_element_from_composition (it)) { return true; @@ -9719,6 +9862,13 @@ move_it_in_display_line_to (struct it *it, ptrdiff_t prev_pos = IT_CHARPOS (*it); bool saw_smaller_pos = prev_pos < to_charpos; bool line_number_pending = false; + int this_line_subject_to_line_prefix = 0; + +#ifdef GLYPH_DEBUG + /* atx_flag, atpos_flag and wrap_flag are assigned but never used; + these hold information useful while debugging. */ + int atx_flag, atpos_flag, wrap_flag; +#endif /* GLYPH_DEBUG */ /* Don't produce glyphs in produce_glyphs. */ saved_glyph_row = it->glyph_row; @@ -9784,6 +9934,11 @@ move_it_in_display_line_to (struct it *it, /* If there's a line-/wrap-prefix, handle it, if we didn't already. */ if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p) handle_line_prefix (it); + + /* Save whether this line has received a wrap prefix, as this + affects whether Emacs attempts to move glyphs into + continuation lines. */ + this_line_subject_to_line_prefix = it->string_from_prefix_prop_p; } if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos)) @@ -9827,10 +9982,15 @@ move_it_in_display_line_to (struct it *it, break; } else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0) - /* If wrap_it is valid, the current position might be in a - word that is wrapped. So, save the iterator in - atpos_it and continue to see if wrapping happens. */ - SAVE_IT (atpos_it, *it, atpos_data); + { + /* If wrap_it is valid, the current position might be in + a word that is wrapped. So, save the iterator in + atpos_it and continue to see if wrapping happens. */ + SAVE_IT (atpos_it, *it, atpos_data); +#ifdef GLYPH_DEBUG + atpos_flag = this_line_subject_to_line_prefix; +#endif /* GLYPH_DEBUG */ + } } /* Stop when ZV reached. @@ -9892,6 +10052,9 @@ move_it_in_display_line_to (struct it *it, } /* Otherwise, we can wrap here. */ SAVE_IT (wrap_it, *it, wrap_data); +#ifdef GLYPH_DEBUG + wrap_flag = this_line_subject_to_line_prefix; +#endif /* GLYPH_DEBUG */ } /* Update may_wrap for the next iteration. */ may_wrap = next_may_wrap; @@ -9970,6 +10133,9 @@ move_it_in_display_line_to (struct it *it, { SAVE_IT (atpos_it, *it, atpos_data); IT_RESET_X_ASCENT_DESCENT (&atpos_it); +#ifdef GLYPH_DEBUG + atpos_flag = this_line_subject_to_line_prefix; +#endif /* GLYPH_DEBUG */ } } else @@ -9984,6 +10150,9 @@ move_it_in_display_line_to (struct it *it, { SAVE_IT (atx_it, *it, atx_data); IT_RESET_X_ASCENT_DESCENT (&atx_it); +#ifdef GLYPH_DEBUG + atx_flag = this_line_subject_to_line_prefix; +#endif /* GLYPH_DEBUG */ } } } @@ -9998,12 +10167,27 @@ move_it_in_display_line_to (struct it *it, && FRAME_WINDOW_P (it->f) && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L) ? WINDOW_LEFT_FRINGE_WIDTH (it->w) - : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))) + : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))) + /* There is no line prefix, next to which the + iterator _must_ produce a minimum of one actual + glyph. */ + && (!this_line_subject_to_line_prefix + /* Or this is the second glyph to be produced + beyond the confines of the line. */ + || (i != 0 + && (x > it->last_visible_x + || (x == it->last_visible_x + && FRAME_WINDOW_P (it->f) + && ((it->bidi_p + && it->bidi_it.paragraph_dir == R2L) + ? WINDOW_LEFT_FRINGE_WIDTH (it->w) + : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))))) { bool moved_forward = false; if (/* IT->hpos == 0 means the very first glyph - doesn't fit on the line, e.g. a wide image. */ + doesn't fit on the line, e.g. a wide + image. */ it->hpos == 0 || (new_x == it->last_visible_x && FRAME_WINDOW_P (it->f))) @@ -10064,6 +10248,9 @@ move_it_in_display_line_to (struct it *it, SAVE_IT (atpos_it, *it, atpos_data); atpos_it.current_x = x_before_this_char; atpos_it.hpos = hpos_before_this_char; +#ifdef GLYPH_DEBUG + atpos_flag = this_line_subject_to_line_prefix; +#endif /* GLYPH_DEBUG */ } } @@ -10161,6 +10348,9 @@ move_it_in_display_line_to (struct it *it, if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0) { SAVE_IT (atpos_it, *it, atpos_data); +#ifdef GLYPH_DEBUG + atpos_flag = this_line_subject_to_line_prefix; +#endif /* GLYPH_DEBUG */ IT_RESET_X_ASCENT_DESCENT (&atpos_it); } } @@ -10259,24 +10449,24 @@ move_it_in_display_line_to (struct it *it, if (it->method == GET_FROM_BUFFER) prev_pos = IT_CHARPOS (*it); - /* Detect overly-wide wrap-prefixes made of (space ...) display - properties. When such a wrap prefix reaches past the right - margin of the window, we need to avoid the call to - set_iterator_to_next below, so that it->line_wrap is left at - its TRUNCATE value wisely set by handle_line_prefix. - Otherwise, set_iterator_to_next will pop the iterator stack, - restore it->line_wrap, and we might miss the opportunity to - exit the loop and return. */ - bool overwide_wrap_prefix = - CONSP (it->object) && EQ (XCAR (it->object), Qspace) - && it->sp > 0 && it->method == GET_FROM_STRETCH - && it->current_x >= it->last_visible_x - && it->continuation_lines_width > 0 - && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE; - /* The current display element has been consumed. Advance - to the next. */ - if (!overwide_wrap_prefix) - set_iterator_to_next (it, true); + /* The current display element has been consumed. Advance to + the next. */ + set_iterator_to_next (it, true); + + /* If IT has just finished producing glyphs for the wrap prefix + and is proceeding to the next method, there might not be + sufficient space remaining in this line to accommodate its + glyphs, and one real glyph must be produced to prevent an + infinite loop. Next, clear this flag if such a glyph has + already been produced. */ + + if (this_line_subject_to_line_prefix == 1 + && !it->string_from_prefix_prop_p) + this_line_subject_to_line_prefix = 2; + else if (this_line_subject_to_line_prefix == 2 + && !it->string_from_prefix_prop_p) + this_line_subject_to_line_prefix = 0; + if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos)) SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it)); if (IT_CHARPOS (*it) < to_charpos) @@ -10360,11 +10550,26 @@ move_it_in_display_line_to (struct it *it, && wrap_it.sp >= 0 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x) || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x))) - RESTORE_IT (it, &wrap_it, wrap_data); + { +#ifdef GLYPH_DEBUG + this_line_subject_to_line_prefix = wrap_flag; +#endif /* GLYPH_DEBUG */ + RESTORE_IT (it, &wrap_it, wrap_data); + } else if (atpos_it.sp >= 0) - RESTORE_IT (it, &atpos_it, atpos_data); + { +#ifdef GLYPH_DEBUG + this_line_subject_to_line_prefix = atpos_flag; +#endif /* GLYPH_DEBUG */ + RESTORE_IT (it, &atpos_it, atpos_data); + } else if (atx_it.sp >= 0) - RESTORE_IT (it, &atx_it, atx_data); + { +#ifdef GLYPH_DEBUG + this_line_subject_to_line_prefix = atx_flag; +#endif /* GLYPH_DEBUG */ + RESTORE_IT (it, &atx_it, atx_data); + } done: @@ -10438,13 +10643,9 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos int line_height, line_start_x = 0, reached = 0; int max_current_x = 0; void *backup_data = NULL; - ptrdiff_t orig_charpos = -1; - enum it_method orig_method = NUM_IT_METHODS; for (;;) { - orig_charpos = IT_CHARPOS (*it); - orig_method = it->method; if (op & MOVE_TO_VPOS) { /* If no TO_CHARPOS and no TO_X specified, stop at the @@ -10716,21 +10917,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos } } else - { - /* Make sure we do advance, otherwise we might infloop. - This could happen when the first display element is - wider than the window, or if we have a wrap-prefix - that doesn't leave enough space after it to display - even a single character. We only do this for moving - through buffer text, as with display/overlay strings - we'd need to also compare it->object's, and this is - unlikely to happen in that case anyway. */ - if (IT_CHARPOS (*it) == orig_charpos - && it->method == orig_method - && orig_method == GET_FROM_BUFFER) - set_iterator_to_next (it, false); - it->continuation_lines_width += it->current_x; - } + it->continuation_lines_width += it->current_x; break; default: @@ -10739,6 +10926,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos /* Reset/increment for the next run. */ it->current_x = line_start_x; + it->wrap_prefix_width = 0; line_start_x = 0; it->hpos = 0; it->line_number_produced_p = false; @@ -10769,6 +10957,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos { it->continuation_lines_width += it->current_x; it->current_x = it->hpos = it->max_ascent = it->max_descent = 0; + it->wrap_prefix_width = 0; it->current_y += it->max_ascent + it->max_descent; ++it->vpos; last_height = it->max_ascent + it->max_descent; @@ -10828,6 +11017,7 @@ move_it_vertically_backward (struct it *it, int dy) reseat_1 (it, it->current.pos, true); /* We are now surely at a line start. */ + it->wrap_prefix_width = 0; it->current_x = it->hpos = 0; /* FIXME: this is incorrect when bidi reordering is in effect. */ it->continuation_lines_width = 0; @@ -11106,7 +11296,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) dvpos--; } - it->current_x = it->hpos = 0; + it->current_x = it->hpos = it->wrap_prefix_width = 0; /* Above call may have moved too far if continuation lines are involved. Scan forward and see if it did. */ @@ -11115,7 +11305,7 @@ move_it_by_lines (struct it *it, ptrdiff_t dvpos) move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS); it->vpos -= it2.vpos; it->current_y -= it2.current_y; - it->current_x = it->hpos = 0; + it->current_x = it->hpos = it->wrap_prefix_width = 0; /* If we moved too far back, move IT some lines forward. */ if (it2.vpos > -dvpos) @@ -11394,7 +11584,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, IT.current_x will be incorrectly set to zero at some arbitrary non-zero X coordinate. */ move_it_by_lines (&it, 0); - it.current_x = it.hpos = 0; + it.current_x = it.hpos = it.wrap_prefix_width = 0; if (IT_CHARPOS (it) != start) { void *it1data = NULL; @@ -11447,7 +11637,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, /* If FROM is on a newline, pretend that we start at the beginning of the next line, because the newline takes no place on display. */ if (FETCH_BYTE (start) == '\n') - it.current_x = 0; + it.current_x = 0, it.wrap_prefix_width = 0; if (!NILP (x_limit)) { it.last_visible_x = max_x; @@ -14359,7 +14549,7 @@ display_tab_bar_line (struct it *it, int height) row->truncated_on_left_p = false; row->truncated_on_right_p = false; - it->current_x = it->hpos = 0; + it->current_x = it->hpos = it->wrap_prefix_width = 0; it->current_y += row->height; ++it->vpos; ++it->glyph_row; @@ -15383,7 +15573,7 @@ display_tool_bar_line (struct it *it, int height) row->truncated_on_left_p = false; row->truncated_on_right_p = false; - it->current_x = it->hpos = 0; + it->current_x = it->hpos = it->wrap_prefix_width = 0; it->current_y += row->height; ++it->vpos; ++it->glyph_row; @@ -17083,6 +17273,7 @@ redisplay_internal (void) NULL, DEFAULT_FACE_ID); it.current_x = this_line_start_x; it.current_y = this_line_y; + it.wrap_prefix_width = 0; it.vpos = this_line_vpos; if (current_buffer->long_line_optimizations_p @@ -18668,6 +18859,14 @@ enum `scroll-conservatively' and the Emacs manual. */ #define SCROLL_LIMIT 100 +/* The freshness of the w->base_line_number cache is only ensured at every + redisplay cycle, so the cache can be used only if there's been + no relevant changes to the buffer since the last redisplay. */ +#define BASE_LINE_NUMBER_VALID_P(w) \ + (eassert (current_buffer == XBUFFER ((w)->contents)), \ + !current_buffer->clip_changed \ + && BEG_UNCHANGED >= (w)->base_line_pos) + static int try_scrolling (Lisp_Object window, bool just_this_one_p, intmax_t arg_scroll_conservatively, intmax_t scroll_step, @@ -18968,9 +19167,10 @@ try_scrolling (Lisp_Object window, bool just_this_one_p, else { /* Maybe forget recorded base line for line number display. */ - if (!just_this_one_p - || current_buffer->clip_changed - || BEG_UNCHANGED < CHARPOS (startp)) + /* FIXME: Why do we need this? `try_scrolling` can only be called from + `redisplay_window` which should have flushed this cache already when + eeded. */ + if (!BASE_LINE_NUMBER_VALID_P (w)) w->base_line_number = 0; /* If cursor ends up on a partially visible line, @@ -19740,9 +19940,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) /* Record it now because it's overwritten. */ bool current_matrix_up_to_date_p = false; bool used_current_matrix_p = false; - /* This is less strict than current_matrix_up_to_date_p. - It indicates that the buffer contents and narrowing are unchanged. */ - bool buffer_unchanged_p = false; bool temp_scroll_step = false; specpdl_ref count = SPECPDL_INDEX (); int rc; @@ -19848,11 +20045,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) specbind (Qinhibit_point_motion_hooks, Qt); - buffer_unchanged_p - = (w->window_end_valid - && !current_buffer->clip_changed - && !window_outdated (w)); - /* When windows_or_buffers_changed is non-zero, we can't rely on the window end being valid, so set it to zero there. */ if (windows_or_buffers_changed) @@ -19992,6 +20184,10 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) } } + if (!BASE_LINE_NUMBER_VALID_P (w)) + /* Forget any recorded base line for line number display. */ + w->base_line_number = 0; + force_start: /* Handle case where place to start displaying has been specified, @@ -20012,10 +20208,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) w->preserve_vscroll_p = false; w->window_end_valid = false; - /* Forget any recorded base line for line number display. */ - if (!buffer_unchanged_p) - w->base_line_number = 0; - /* Redisplay the mode line. Select the buffer properly for that. Also, run the hook window-scroll-functions because we have scrolled. */ @@ -20344,12 +20536,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) if (w->cursor.vpos >= 0) { - if (!just_this_one_p - || current_buffer->clip_changed - || BEG_UNCHANGED < CHARPOS (startp)) - /* Forget any recorded base line for line number display. */ - w->base_line_number = 0; - if (!cursor_row_fully_visible_p (w, true, false, false)) { clear_glyph_matrix (w->desired_matrix); @@ -20420,10 +20606,6 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) debug_method_add (w, "recenter"); #endif - /* Forget any previously recorded base line for line number display. */ - if (!buffer_unchanged_p) - w->base_line_number = 0; - /* Determine the window start relative to point. */ init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); it.current_y = it.last_visible_y; @@ -20529,7 +20711,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p) it.current_y = 0; } - it.current_x = it.hpos = 0; + it.current_x = it.wrap_prefix_width = it.hpos = 0; /* Set the window start position here explicitly, to avoid an infinite loop in case the functions in window-scroll-functions @@ -22497,7 +22679,7 @@ try_window_id (struct window *w) /* We may start in a continuation line. If so, we have to get the right continuation_lines_width and current_x. */ it.continuation_lines_width = last_row->continuation_lines_width; - it.hpos = it.current_x = 0; + it.hpos = it.current_x = it.wrap_prefix_width = 0; /* Display the rest of the lines at the window end. */ it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos); @@ -23102,6 +23284,7 @@ insert_left_trunc_glyphs (struct it *it) /* Get the truncation glyphs. */ truncate_it = *it; truncate_it.current_x = 0; + truncate_it.wrap_prefix_width = 0; truncate_it.face_id = DEFAULT_FACE_ID; truncate_it.glyph_row = &scratch_glyph_row; truncate_it.area = TEXT_AREA; @@ -23864,6 +24047,10 @@ extend_face_to_end_of_line (struct it *it) for (it->current_x = 0; g < e; g++) it->current_x += g->pixel_width; + if (it->continuation_lines_width + && it->string_from_prefix_prop_p) + it->wrap_prefix_width = it->current_x; + it->area = LEFT_MARGIN_AREA; it->face_id = default_face->id; while (it->glyph_row->used[LEFT_MARGIN_AREA] @@ -24585,6 +24772,13 @@ maybe_produce_line_number (struct it *it) if (!last_line) { /* If possible, reuse data cached by line-number-mode. */ + /* NOTE: We use `base_line_number` without checking + BASE_LINE_NUMBER_VALID_P because we assume that `redisplay_window` + has already flushed this cache for us when needed. + NOTE2: Checking BASE_LINE_NUMBER_VALID_P here would be + overly pessimistic because it might say that the cache + was invalid before entering `redisplay_window` yet the + value has just been refreshed. */ if (it->w->base_line_number > 0 && it->w->base_line_pos > 0 && it->w->base_line_pos <= IT_CHARPOS (*it) @@ -24634,7 +24828,7 @@ maybe_produce_line_number (struct it *it) /* Produce the glyphs for the line number. */ struct it tem_it; char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1]; - bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false; + bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE; ptrdiff_t lnum_offset = -1; /* to produce 1-based line numbers */ int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID); int current_lnum_face_id @@ -24864,7 +25058,7 @@ should_produce_line_number (struct it *it) because get-char-property always returns nil for ZV, except if the property is in 'default-text-properties'. */ if (NILP (val) && IT_CHARPOS (*it) >= ZV) - val = disable_line_numbers_overlay_at_eob (); + return !disable_line_numbers_overlay_at_eob (); return NILP (val) ? true : false; } @@ -24929,6 +25123,7 @@ display_line (struct it *it, int cursor_vpos) int first_visible_x = it->first_visible_x; int last_visible_x = it->last_visible_x; int x_incr = 0; + int this_line_subject_to_line_prefix = 0; /* We always start displaying at hpos zero even if hscrolled. */ eassert (it->hpos == 0 && it->current_x == 0); @@ -25005,7 +25200,10 @@ display_line (struct it *it, int cursor_vpos) if (it->current_x < it->first_visible_x && (move_result == MOVE_NEWLINE_OR_CR || move_result == MOVE_POS_MATCH_OR_ZV)) - it->current_x = it->first_visible_x; + { + it->current_x = it->first_visible_x; + it->wrap_prefix_width = 0; + } /* In case move_it_in_display_line_to above "produced" the line number. */ @@ -25034,6 +25232,7 @@ display_line (struct it *it, int cursor_vpos) /* We only do this when not calling move_it_in_display_line_to above, because that function calls itself handle_line_prefix. */ handle_line_prefix (it); + this_line_subject_to_line_prefix = it->string_from_prefix_prop_p; } else { @@ -25200,12 +25399,15 @@ display_line (struct it *it, int cursor_vpos) process the prefix now. */ if (it->area == TEXT_AREA && pending_handle_line_prefix) { - /* Line numbers should precede the line-prefix or wrap-prefix. */ + /* Line numbers should precede the line-prefix or + wrap-prefix. */ if (line_number_needed) maybe_produce_line_number (it); pending_handle_line_prefix = false; handle_line_prefix (it); + this_line_subject_to_line_prefix + = it->string_from_prefix_prop_p; } continue; } @@ -25226,7 +25428,16 @@ display_line (struct it *it, int cursor_vpos) if (/* Not a newline. */ nglyphs > 0 /* Glyphs produced fit entirely in the line. */ - && it->current_x < it->last_visible_x) + && (it->current_x < it->last_visible_x + /* Or a line or wrap prefix is in effect, and not + truncating the glyph produced immediately after it + would cause an infinite cycle. */ + || (it->line_wrap != TRUNCATE + /* This code is not valid if multiple glyphs were + produced, as some of these glyphs might remain + within this line. */ + && nglyphs == 1 + && this_line_subject_to_line_prefix))) { it->hpos += nglyphs; row->ascent = max (row->ascent, it->max_ascent); @@ -25277,7 +25488,20 @@ display_line (struct it *it, int cursor_vpos) && FRAME_WINDOW_P (it->f) && (row->reversed_p ? WINDOW_LEFT_FRINGE_WIDTH (it->w) - : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))) + : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))) + /* There is no line prefix, next to which the + iterator _must_ produce a minimum of one actual + glyph. */ + && (!this_line_subject_to_line_prefix + /* Or this is the second glyph to be produced + beyond the confines of the line. */ + || (i != 0 + && (x > it->last_visible_x + || (x == it->last_visible_x + && FRAME_WINDOW_P (it->f) + && (row->reversed_p + ? WINDOW_LEFT_FRINGE_WIDTH (it->w) + : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))))) { /* End of a continued line. */ @@ -25574,24 +25798,23 @@ display_line (struct it *it, int cursor_vpos) break; } - /* Detect overly-wide wrap-prefixes made of (space ...) display - properties. When such a wrap prefix reaches past the right - margin of the window, we need to avoid the call to - set_iterator_to_next below, so that it->line_wrap is left at - its TRUNCATE value wisely set by handle_line_prefix. - Otherwise, set_iterator_to_next will pop the iterator stack, - restore it->line_wrap, and redisplay might infloop. */ - bool overwide_wrap_prefix = - CONSP (it->object) && EQ (XCAR (it->object), Qspace) - && it->sp > 0 && it->method == GET_FROM_STRETCH - && it->current_x >= it->last_visible_x - && it->continuation_lines_width > 0 - && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE; - /* Proceed with next display element. Note that this skips over lines invisible because of selective display. */ - if (!overwide_wrap_prefix) - set_iterator_to_next (it, true); + set_iterator_to_next (it, true); + + /* If IT has just finished producing glyphs for the wrap prefix + and is proceeding to the next method, there might not be + sufficient space remaining in this line to accommodate its + glyphs, and one real glyph must be produced to prevent an + infinite loop. Next, clear this flag if such a glyph has + already been produced. */ + + if (this_line_subject_to_line_prefix == 1 + && !it->string_from_prefix_prop_p) + this_line_subject_to_line_prefix = 2; + else if (this_line_subject_to_line_prefix == 2 + && !it->string_from_prefix_prop_p) + this_line_subject_to_line_prefix = 0; /* If we truncate lines, we are done when the last displayed glyphs reach past the right margin of the window. */ @@ -25837,7 +26060,7 @@ display_line (struct it *it, int cursor_vpos) HPOS) = (0 0). Vertical positions are incremented. As a convenience for the caller, IT->glyph_row is set to the next row to be used. */ - it->current_x = it->hpos = 0; + it->wrap_prefix_width = it->current_x = it->hpos = 0; it->current_y += row->height; /* Restore the first and last visible X if we adjusted them for current-line hscrolling. */ @@ -26316,7 +26539,7 @@ Value is the new character position of point. */) { struct text_pos pt; struct it it; - int pt_x, target_x, pixel_width, pt_vpos; + int pt_x, pt_wrap_prefix_x, target_x, pixel_width, pt_vpos; bool at_eol_p; bool overshoot_expected = false; bool target_is_eol_p = false; @@ -26348,6 +26571,7 @@ Value is the new character position of point. */) reseat: reseat_at_previous_visible_line_start (&it); it.current_x = it.hpos = it.current_y = it.vpos = 0; + it.wrap_prefix_width = 0; if (IT_CHARPOS (it) != PT) { move_it_to (&it, overshoot_expected ? PT - 1 : PT, @@ -26366,6 +26590,7 @@ Value is the new character position of point. */) move_it_in_display_line (&it, PT, -1, MOVE_TO_POS); } pt_x = it.current_x; + pt_wrap_prefix_x = it.wrap_prefix_width; pt_vpos = it.vpos; if (dir > 0 || overshoot_expected) { @@ -26380,10 +26605,11 @@ Value is the new character position of point. */) it.glyph_row = NULL; PRODUCE_GLYPHS (&it); /* compute it.pixel_width */ it.glyph_row = row; - /* PRODUCE_GLYPHS advances it.current_x, so we must restore - it, lest it will become out of sync with it's buffer + /* PRODUCE_GLYPHS advances it.current_x, so it must be + restored, lest it become out of sync with its buffer position. */ it.current_x = pt_x; + it.wrap_prefix_width = pt_wrap_prefix_x; } else at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it); @@ -26428,6 +26654,7 @@ Value is the new character position of point. */) it.last_visible_x = DISP_INFINITY; reseat_at_previous_visible_line_start (&it); it.current_x = it.current_y = it.hpos = 0; + it.wrap_prefix_width = 0; if (pt_vpos != 0) move_it_by_lines (&it, pt_vpos); } @@ -27944,6 +28171,11 @@ are the selected window and the WINDOW's buffer). */) init_iterator (&it, w, -1, -1, NULL, face_id); + /* Make sure `base_line_number` is fresh in case we encounter a `%l`. */ + if (current_buffer == XBUFFER ((w)->contents) + && !BASE_LINE_NUMBER_VALID_P (w)) + w->base_line_number = 0; + if (no_props) { mode_line_target = MODE_LINE_NOPROP; @@ -28396,30 +28628,29 @@ decode_mode_spec (struct window *w, register int c, int field_width, when the buffer's restriction was changed, but the window wasn't yet redisplayed after that. If that happens, we need to determine a new base line. */ - if (!(BUF_BEGV_BYTE (b) <= startpos_byte + if (current_buffer != XBUFFER (w->contents) + || !(BUF_BEGV_BYTE (b) <= startpos_byte && startpos_byte <= BUF_ZV_BYTE (b))) { startpos = BUF_BEGV (b); startpos_byte = BUF_BEGV_BYTE (b); - w->base_line_pos = 0; - w->base_line_number = 0; } /* If we decided that this buffer isn't suitable for line numbers, - don't forget that too fast. */ + don't forget that too fast. + FIXME: What if `current_buffer != w->contents`? */ if (w->base_line_pos == -1) goto no_value; /* If the buffer is very big, don't waste time. */ if (FIXNUMP (Vline_number_display_limit) && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit)) - { - w->base_line_pos = 0; - w->base_line_number = 0; - goto no_value; - } + goto no_value; - if (w->base_line_number > 0 + /* Callers of `display_mode_element` are in charge of flushing + any stale `base_line_number` cache. */ + if (current_buffer == XBUFFER ((w)->contents) + && w->base_line_number > 0 && w->base_line_pos > 0 && w->base_line_pos <= startpos) { @@ -28445,7 +28676,9 @@ decode_mode_spec (struct window *w, register int c, int field_width, or too far away, or if we did not have one. "Too close" means it's plausible a scroll-down would go back past it. */ - if (startpos == BUF_BEGV (b)) + if (current_buffer != XBUFFER (w->contents)) + ; /* The base line is for another buffer, don't touch it! */ + else if (startpos == BUF_BEGV (b)) { w->base_line_number = topline; w->base_line_pos = BUF_BEGV (b); @@ -28482,6 +28715,12 @@ decode_mode_spec (struct window *w, register int c, int field_width, goto no_value; } + /* NOTE: if `clip_changed` is set or if `BEG_UNCHANGED` is + before `position`, this new cached value may get flushed + soon needlessly, because we can't reset `BEG_UNCHANGED` or + `clip_changed` from here (since they reflect the changes + since the last redisplay so they can only be reset from + `mark_window_display_accurate_1`). :-( */ w->base_line_number = topline - nlines; w->base_line_pos = BYTE_TO_CHAR (position); } @@ -29509,9 +29748,9 @@ dump_glyph_string (struct glyph_string *s) # define ALLOCATE_HDC(hdc, f) \ Lisp_Object prev_quit = Vinhibit_quit; \ Vinhibit_quit = Qt; \ - HDC hdc = get_frame_dc ((f)) + HDC hdc = get_frame_dc (f) # define RELEASE_HDC(hdc, f) \ - release_frame_dc ((f), (hdc)); \ + release_frame_dc (f, hdc); \ Vinhibit_quit = prev_quit #else # define ALLOCATE_HDC(hdc, f) @@ -30942,7 +31181,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, #ifdef HAVE_RSVG /* Update SVG image glyphs with mouse face features. FIXME: it - should be possible to have this behaviour with transparent + should be possible to have this behavior with transparent background PNG. */ if (hl == DRAW_MOUSE_FACE) { @@ -32575,7 +32814,19 @@ gui_produce_glyphs (struct it *it) if (font->space_width > 0) { int tab_width = it->tab_width * font->space_width; - int x = it->current_x + it->continuation_lines_width; + /* wrap-prefix strings are prepended to continuation + lines, so the width of tab characters inside should + be computed from the start of this screen line rather + than as a product of the total width of the physical + line being wrapped. */ + int x = it->current_x + (it->string_from_prefix_prop_p + /* Subtract the width of the + prefix from it->current_x if + it exists. */ + ? 0 : (it->continuation_lines_width + ? (it->continuation_lines_width + - it->wrap_prefix_width) + : 0)); int x0 = x; /* Adjust for line numbers, if needed. */ if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p) @@ -33046,7 +33297,13 @@ gui_produce_glyphs (struct it *it) because this isn't true for images with `:ascent 100'. */ eassert (it->ascent >= 0 && it->descent >= 0); if (it->area == TEXT_AREA) - it->current_x += it->pixel_width; + { + it->current_x += it->pixel_width; + + if (it->continuation_lines_width + && it->string_from_prefix_prop_p) + it->wrap_prefix_width = it->current_x; + } if (extra_line_spacing > 0) { @@ -36205,7 +36462,7 @@ expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r, /* Use a signed int intermediate value to avoid catastrophic failures due to comparison between signed and unsigned, when x is negative (can happen for wide images that are hscrolled). */ - int r_end = r->x + r->width; + int r_end = r->x + (int) r->width; while (last < end && x < r_end) { x += last->pixel_width; @@ -36504,7 +36761,7 @@ expose_window (struct window *w, const Emacs_Rectangle *fr) /* Use a signed int intermediate value to avoid catastrophic failures due to comparison between signed and unsigned, when y0 or y1 is negative (can happen for tall images). */ - int r_bottom = r.y + r.height; + int r_bottom = r.y + (int) r.height; /* We must temporarily switch to the window's buffer, in case the fringe face has been remapped in that buffer's @@ -36551,7 +36808,7 @@ expose_window (struct window *w, const Emacs_Rectangle *fr) /* We must redraw a row overlapping the exposed area. */ if (y0 < r.y ? y0 + row->phys_height > r.y - : y0 + row->ascent - row->phys_ascent < r.y +r.height) + : y0 + row->ascent - row->phys_ascent < r.y + (int) r.height) { if (first_overlapping_row == NULL) first_overlapping_row = row; @@ -36730,7 +36987,7 @@ gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2, const Emacs_Rectangle *upper, *lower; bool intersection_p = false; - /* Rearrange so that R1 is the left-most rectangle. */ + /* Rearrange so that left is the left-most rectangle. */ if (r1->x < r2->x) left = r1, right = r2; else @@ -36738,13 +36995,14 @@ gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2, /* X0 of the intersection is right.x0, if this is inside R1, otherwise there is no intersection. */ - if (right->x <= left->x + left->width) + if (right->x <= left->x + (int) left->width) { result->x = right->x; /* The right end of the intersection is the minimum of the right ends of left and right. */ - result->width = (min (left->x + left->width, right->x + right->width) + result->width = (min (left->x + (int) left->width, + right->x + (int) right->width) - result->x); /* Same game for Y. */ @@ -36755,14 +37013,14 @@ gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2, /* The upper end of the intersection is lower.y0, if this is inside of upper. Otherwise, there is no intersection. */ - if (lower->y <= upper->y + upper->height) + if (lower->y <= upper->y + (int) upper->height) { result->y = lower->y; /* The lower end of the intersection is the minimum of the lower ends of upper and lower. */ - result->height = (min (lower->y + lower->height, - upper->y + upper->height) + result->height = (min (lower->y + (int) lower->height, + upper->y + (int) upper->height) - result->y); intersection_p = true; } @@ -37753,6 +38011,8 @@ cursor shapes. */); DEFSYM (Qthin_space, "thin-space"); DEFSYM (Qzero_width, "zero-width"); + DEFSYM (Qdebug_early__muted, "debug-early--muted"); + DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function, doc: /* Function run just before redisplay. It is called with one argument, which is the set of windows that are to |