Mercurial > emacs
changeset 25186:d6c941334567
(redraw_overlapping_rows): Use flag overlapping_p.
(direct_output_for_insert): Ditto.
(direct_output_for_insert): Don't use this method if
row is overlapped by others.
(update_text_area): Write full line if current line is overlapped.
(redraw_overlapped_rows): New.
(update_window): Call it.
(redraw_overlapping_rows): New.
(update_window): Call it.
(scrolling_window): Make sure overlapped_p flag in current rows is
unchanged.
(row_equal_p): Take rows overlapped_p flag into account.
(adjust_glyphs): Block input while adjusting matrices.
(direct_output_for_insert): Don't use this
optimization for rows that overlap others.
(update_window_line): Return non-zero if display has changed.
(update_text_area): Ditto.
(update_window): Record if display has been changed.
(blank_row): Compute glyph row's physical height.
(row_equal_p): Take physical row heights into account.
(direct_output_for_insert): Ditto.
(update_text_area): Ditto.
author | Gerd Moellmann <gerd@gnu.org> |
---|---|
date | Fri, 06 Aug 1999 13:59:32 +0000 |
parents | d3614d7b7583 |
children | 39feb68ed3c7 |
files | src/dispnew.c |
diffstat | 1 files changed, 176 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/src/dispnew.c Fri Aug 06 13:59:29 1999 +0000 +++ b/src/dispnew.c Fri Aug 06 13:59:32 1999 +0000 @@ -109,6 +109,8 @@ /* Function prototypes. */ +static void redraw_overlapping_rows P_ ((struct window *, int)); +static void redraw_overlapped_rows P_ ((struct window *, int)); static int count_blanks P_ ((struct glyph *, int)); static int count_match P_ ((struct glyph *, struct glyph *, struct glyph *, struct glyph *)); @@ -146,9 +148,9 @@ static void clear_window_matrices P_ ((struct window *, int)); static void fill_up_glyph_row_area_with_spaces P_ ((struct glyph_row *, int)); static int scrolling_window P_ ((struct window *, int)); -static void update_window_line P_ ((struct window *, int)); +static int update_window_line P_ ((struct window *, int)); static void update_marginal_area P_ ((struct window *, int, int)); -static void update_text_area P_ ((struct window *, int)); +static int update_text_area P_ ((struct window *, int)); static void make_current P_ ((struct glyph_matrix *, struct glyph_matrix *, int)); static void mirror_make_current P_ ((struct window *, int)); @@ -999,8 +1001,8 @@ clear_glyph_row (row); row->y = y; - row->ascent = 0; - row->height = CANON_Y_UNIT (XFRAME (WINDOW_FRAME (w))); + row->ascent = row->phys_ascent = 0; + row->height = row->phys_height = CANON_Y_UNIT (XFRAME (w->frame)); if (row->y < min_y) row->visible_height = row->height - (min_y - row->y); @@ -1361,12 +1363,15 @@ || a->overlay_arrow_p != b->overlay_arrow_p || a->continued_p != b->continued_p || a->indicate_empty_line_p != b->indicate_empty_line_p + || a->overlapped_p != b->overlapped_p || (MATRIX_ROW_CONTINUATION_LINE_P (a) != MATRIX_ROW_CONTINUATION_LINE_P (b)) /* Different partially visible characters on left margin. */ || a->x != b->x /* Different height. */ || a->ascent != b->ascent + || a->phys_ascent != b->phys_ascent + || a->phys_height != b->phys_height || a->visible_height != b->visible_height) return 0; } @@ -1863,6 +1868,10 @@ adjust_glyphs (f) struct frame *f; { + /* Block input so that expose events and other events that access + glyph matrices are not processed while we are changing them. */ + BLOCK_INPUT; + if (f) adjust_frame_glyphs (f); else @@ -1872,6 +1881,8 @@ FOR_EACH_FRAME (tail, lisp_frame) adjust_frame_glyphs (XFRAME (lisp_frame)); } + + UNBLOCK_INPUT; } @@ -3025,9 +3036,15 @@ || g == '\r' /* Give up if unable to display the cursor in the window. */ || w->cursor.vpos < 0 - /* Can't do it in a continued line because continuation lines - will change. */ - || MATRIX_ROW (w->current_matrix, w->cursor.vpos)->continued_p + || (glyph_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos), + /* Can't do it in a continued line because continuation + lines would change. */ + (glyph_row->continued_p + /* Can't use this method if the line overlaps others or is + overlapped by others because these other lines would + have to be redisplayed. */ + || glyph_row->overlapping_p + || glyph_row->overlapped_p)) /* Can't do it for partial width windows on terminal frames because we can't clear to eol in such a window. */ || (!window_redisplay_p && !WINDOW_FULL_WIDTH_P (w))) @@ -3088,6 +3105,8 @@ the original row, or if it is not a character glyph. */ if (glyph_row->ascent != it.ascent || glyph_row->height != it.ascent + it.descent + || glyph_row->phys_ascent != it.phys_ascent + || glyph_row->phys_height != it.phys_ascent + it.phys_descent || it.what != IT_CHARACTER) return 0; @@ -3450,6 +3469,104 @@ } +/* Redraw lines from the current matrix of window W that are + overlapped by other rows. YB is bottom-most y-position in W. */ + +static void +redraw_overlapped_rows (w, yb) + struct window *w; + int yb; +{ + int i, bottom_y; + struct glyph_row *row; + + /* If rows overlapping others have been changed, the rows being + overlapped have to be redrawn. This won't draw lines that have + already been drawn in update_window_line because overlapped_p in + desired rows is 0, so after row assignment overlapped_p in + current rows is 0. */ + for (i = 0; i < w->current_matrix->nrows; ++i) + { + row = w->current_matrix->rows + i; + + if (!row->enabled_p) + break; + else if (row->mode_line_p) + continue; + + if (row->overlapped_p) + { + enum glyph_row_area area; + + for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) + { + updated_row = row; + updated_area = area; + rif->cursor_to (i, 0, row->y, area == TEXT_AREA ? row->x : 0); + if (row->used[area]) + rif->write_glyphs (row->glyphs[area], row->used[area]); + rif->clear_end_of_line (-1); + } + + row->overlapped_p = 0; + } + + bottom_y = MATRIX_ROW_BOTTOM_Y (row); + if (bottom_y >= yb) + break; + } +} + + +/* Redraw lines from the current matrix of window W that overlap + others. YB is bottom-most y-position in W. */ + +static void +redraw_overlapping_rows (w, yb) + struct window *w; + int yb; +{ + int i, bottom_y; + struct glyph_row *row; + + for (i = 0; i < w->current_matrix->nrows; ++i) + { + row = w->current_matrix->rows + i; + + if (!row->enabled_p) + break; + else if (row->mode_line_p) + continue; + + bottom_y = MATRIX_ROW_BOTTOM_Y (row); + + if (row->overlapping_p && i > 0 && bottom_y < yb) + { + if (row->used[LEFT_MARGIN_AREA]) + rif->fix_overlapping_area (w, row, LEFT_MARGIN_AREA); + + if (row->used[TEXT_AREA]) + rif->fix_overlapping_area (w, row, TEXT_AREA); + + if (row->used[RIGHT_MARGIN_AREA]) + rif->fix_overlapping_area (w, row, RIGHT_MARGIN_AREA); + + /* Record in neighbor rows that ROW overwrites part of their + display. */ + if (row->phys_ascent > row->ascent && i > 0) + MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p = 1; + if ((row->phys_height - row->phys_ascent + > row->height - row->ascent) + && bottom_y < yb) + MATRIX_ROW (w->current_matrix, i + 1)->overlapped_p = 1; + } + + if (bottom_y >= yb) + break; + } +} + + /* Update display of window W. FORCE_P non-zero means that we should not stop when detecting pending input. */ @@ -3482,7 +3599,7 @@ struct glyph_row *row, *end; struct glyph_row *mode_line_row; struct glyph_row *top_line_row = NULL; - int yb; + int yb, changed_p = 0; rif->update_window_begin_hook (w); yb = window_text_bottom_y (w); @@ -3501,6 +3618,7 @@ mode_line_row->y = yb; update_window_line (w, MATRIX_ROW_VPOS (mode_line_row, desired_matrix)); + changed_p = 1; } /* Find first enabled row. Optimizations in redisplay_internal @@ -3521,6 +3639,7 @@ } else if (rc > 0) force_p = 1; + changed_p = 1; } /* Update the top mode line after scrolling because a new top @@ -3530,6 +3649,7 @@ { top_line_row->y = 0; update_window_line (w, 0); + changed_p = 1; } /* Update the rest of the lines. */ @@ -3550,7 +3670,7 @@ if (!force_p && vpos % preempt_count == 0) detect_input_pending (); - update_window_line (w, vpos); + changed_p |= update_window_line (w, vpos); /* Mark all rows below the last visible one in the current matrix as invalid. This is necessary because of @@ -3571,6 +3691,16 @@ set_cursor: + /* Fix the appearance of overlapping(overlapped rows. */ + if (rif->fix_overlapping_area + && !w->pseudo_window_p + && changed_p + && !paused_p) + { + redraw_overlapped_rows (w, yb); + redraw_overlapping_rows (w, yb); + } + if (!paused_p && !w->pseudo_window_p) { /* Make cursor visible at cursor position of W. */ @@ -3588,14 +3718,16 @@ /* Remember the redisplay method used to display the matrix. */ strcpy (w->current_matrix->method, w->desired_matrix->method); #endif - + /* End of update of window W. */ rif->update_window_end_hook (w, 1); + } else paused_p = 1; clear_glyph_matrix (desired_matrix); + return paused_p; } @@ -3624,15 +3756,17 @@ } -/* Update the display of the text area of row VPOS in window W. */ - -static void +/* Update the display of the text area of row VPOS in window W. + Value is non-zero if display has changed. */ + +static int update_text_area (w, vpos) struct window *w; int vpos; { struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos); struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); + int changed_p = 0; /* Let functions in xterm.c know what area subsequent X positions will be relative to. */ @@ -3643,7 +3777,10 @@ if (!current_row->enabled_p || desired_row->y != current_row->y || desired_row->ascent != current_row->ascent + || desired_row->phys_ascent != current_row->phys_ascent + || desired_row->phys_height != current_row->phys_height || desired_row->visible_height != current_row->visible_height + || current_row->overlapped_p || current_row->x != desired_row->x) { rif->cursor_to (vpos, 0, desired_row->y, desired_row->x); @@ -3654,6 +3791,7 @@ /* Clear to end of window. */ rif->clear_end_of_line (-1); + changed_p = 1; } else { @@ -3736,6 +3874,7 @@ rif->cursor_to (vpos, start_hpos, desired_row->y, start_x); rif->write_glyphs (start, i - start_hpos); + changed_p = 1; } } @@ -3744,6 +3883,7 @@ { rif->cursor_to (vpos, i, desired_row->y, x); rif->write_glyphs (desired_glyph, desired_row->used[TEXT_AREA] - i); + changed_p = 1; } /* Maybe clear to end of line. */ @@ -3762,6 +3902,7 @@ rif->cursor_to (vpos, i, desired_row->y, desired_row->x + desired_row->pixel_width); rif->clear_end_of_line (-1); + changed_p = 1; } else if (desired_row->pixel_width < current_row->pixel_width) { @@ -3787,20 +3928,25 @@ else x = current_row->x + current_row->pixel_width; rif->clear_end_of_line (x); + changed_p = 1; } } + + return changed_p; } -/* Update row VPOS in window W. */ - -static void +/* Update row VPOS in window W. Value is non-zero if display has been + changed. */ + +static int update_window_line (w, vpos) struct window *w; int vpos; { struct glyph_row *current_row = MATRIX_ROW (w->current_matrix, vpos); struct glyph_row *desired_row = MATRIX_ROW (w->desired_matrix, vpos); + int changed_p = 0; xassert (desired_row->enabled_p); @@ -3811,15 +3957,21 @@ /* Update display of the left margin area, if there is one. */ if (!desired_row->full_width_p && !NILP (w->left_margin_width)) - update_marginal_area (w, LEFT_MARGIN_AREA, vpos); + { + update_marginal_area (w, LEFT_MARGIN_AREA, vpos); + changed_p = 1; + } /* Update the display of the text area. */ - update_text_area (w, vpos); + changed_p |= update_text_area (w, vpos); /* Update display of the right margin area, if there is one. */ if (!desired_row->full_width_p && !NILP (w->right_margin_width)) - update_marginal_area (w, RIGHT_MARGIN_AREA, vpos); + { + changed_p = 1; + update_marginal_area (w, RIGHT_MARGIN_AREA, vpos); + } /* Draw truncation marks etc. */ if (!current_row->enabled_p @@ -3839,6 +3991,7 @@ /* Update current_row from desired_row. */ make_current (w->desired_matrix, w->current_matrix, vpos); updated_row = NULL; + return changed_p; } @@ -4207,10 +4360,14 @@ for (j = 0; j < r->nrows; ++j) { struct glyph_row *from, *to; + int to_overlapped_p; + to = MATRIX_ROW (current_matrix, r->desired_vpos + j); + to_overlapped_p = to->overlapped_p; from = MATRIX_ROW (desired_matrix, r->desired_vpos + j); assign_row (to, from); to->enabled_p = 1, from->enabled_p = 0; + to->overlapped_p = to_overlapped_p; } }