diff options
author | Paul Eggert <[email protected]> | 2011-12-10 16:56:50 -0800 |
---|---|---|
committer | Paul Eggert <[email protected]> | 2011-12-10 16:56:50 -0800 |
commit | 8f50130c565eaf0ad7c49e4ad044c3291ecdfa71 (patch) | |
tree | c8129448cbbf387fe82667ccac02983592c688f1 /src/dispnew.c | |
parent | 85a83e2e2585a1906dec5168ed96ad521b5849ed (diff) | |
parent | 7b9d523a07395ecea505be88f45c33d73aea7038 (diff) |
Merge from trunk.
Diffstat (limited to 'src/dispnew.c')
-rw-r--r-- | src/dispnew.c | 84 |
1 files changed, 71 insertions, 13 deletions
diff --git a/src/dispnew.c b/src/dispnew.c index 88f7541407..e53e3fdf80 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -431,7 +431,7 @@ margin_glyphs_to_reserve (struct window *w, int total_glyphs, Lisp_Object margin #if XASSERTS /* Return non-zero if ROW's hash value is correct, zero if not. */ -static int +int verify_row_hash (struct glyph_row *row) { return row->hash == row_hash (row); @@ -608,7 +608,6 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y row->glyphs[LAST_AREA] = row->glyphs[LEFT_MARGIN_AREA] + dim.width; } - xassert (!row->enabled_p || verify_row_hash (row)); ++row; } } @@ -3575,12 +3574,11 @@ update_window (struct window *w, int force_p) rif->update_window_begin_hook (w); yb = window_text_bottom_y (w); - - /* If window has a header line, update it before everything else. - Adjust y-positions of other rows by the header line height. */ row = desired_matrix->rows; end = row + desired_matrix->nrows - 1; + /* Take note of the header line, if there is one. We will + update it below, after updating all of the window's lines. */ if (row->mode_line_p) { header_line_row = row; @@ -3625,6 +3623,8 @@ update_window (struct window *w, int force_p) /* Update the rest of the lines. */ for (; row < end && (force_p || !input_pending); ++row) + /* scrolling_window resets the enabled_p flag of the rows it + reuses from current_matrix. */ if (row->enabled_p) { int vpos = MATRIX_ROW_VPOS (row, desired_matrix); @@ -4550,18 +4550,69 @@ scrolling_window (struct window *w, int header_line_p) { rif->clear_window_mouse_face (w); rif->scroll_run_hook (w, r); + } - /* Invalidate runs that copy from where we copied to. */ - for (j = i + 1; j < nruns; ++j) + /* Truncate runs that copy to where we copied to, and + invalidate runs that copy from where we copied to. */ + for (j = nruns - 1; j > i; --j) + { + struct run *p = runs[j]; + int truncated_p = 0; + + if (p->nrows > 0 + && p->desired_y < r->desired_y + r->height + && p->desired_y + p->height > r->desired_y) { - struct run *p = runs[j]; + if (p->desired_y < r->desired_y) + { + p->nrows = r->desired_vpos - p->desired_vpos; + p->height = r->desired_y - p->desired_y; + truncated_p = 1; + } + else + { + int nrows_copied = (r->desired_vpos + r->nrows + - p->desired_vpos); + + if (p->nrows <= nrows_copied) + p->nrows = 0; + else + { + int height_copied = (r->desired_y + r->height + - p->desired_y); + + p->current_vpos += nrows_copied; + p->desired_vpos += nrows_copied; + p->nrows -= nrows_copied; + p->current_y += height_copied; + p->desired_y += height_copied; + p->height -= height_copied; + truncated_p = 1; + } + } + } - if ((p->current_y >= r->desired_y + if (r->current_y != r->desired_y + /* The condition below is equivalent to + ((p->current_y >= r->desired_y && p->current_y < r->desired_y + r->height) - || (p->current_y + p->height >= r->desired_y + || (p->current_y + p->height > r->desired_y && (p->current_y + p->height - < r->desired_y + r->height))) - p->nrows = 0; + <= r->desired_y + r->height))) + because we have 0 < p->height <= r->height. */ + && p->current_y < r->desired_y + r->height + && p->current_y + p->height > r->desired_y) + p->nrows = 0; + + /* Reorder runs by copied pixel lines if truncated. */ + if (truncated_p && p->nrows > 0) + { + int k = nruns - 1; + + while (runs[k]->nrows == 0 || runs[k]->height < p->height) + k--; + memmove (runs + j, runs + j + 1, (k - j) * sizeof (*runs)); + runs[k] = p; } } @@ -4576,7 +4627,14 @@ scrolling_window (struct window *w, int header_line_p) to_overlapped_p = to->overlapped_p; from->redraw_fringe_bitmaps_p = from->fringe_bitmap_periodic_p; assign_row (to, from); - to->enabled_p = 1, from->enabled_p = 0; + /* The above `assign_row' actually does swap, so if we had + an overlap in the copy destination of two runs, then + the second run would assign a previously disabled bogus + row. But thanks to the truncation code in the + preceding for-loop, we no longer have such an overlap, + and thus the assigned row should always be enabled. */ + xassert (to->enabled_p); + from->enabled_p = 0; to->overlapped_p = to_overlapped_p; } } |