📄 screen.c
字号:
idx = 0;
}
}
else if (lastwin == firstwin)
{
screenclear(); /* far off: clearing the screen is faster */
must_start_top = TRUE;
must_end_bot = TRUE;
}
}
else if (lastwin == firstwin)
{
screenclear(); /* far off: clearing the screen is faster */
must_start_top = TRUE;
must_end_bot = TRUE;
}
}
else /* may scroll up */
{
j = -1;
/* try to find wp->w_topline in wp->w_lsize_lnum[] */
for (i = 0; i < wp->w_lsize_valid; i++)
{
if (wp->w_lsize_lnum[i] == wp->w_topline)
{
j = i;
break;
}
row += wp->w_lsize[i];
}
if (j == -1) /* wp->w_topline is not in wp->w_lsize_lnum */
{
row = 0; /* start at the first row */
if (lastwin == firstwin)
{
screenclear(); /* far off: clearing the screen is faster */
must_start_top = TRUE;
must_end_bot = TRUE;
}
}
else
{
/*
* Try to delete the correct number of lines.
* wp->w_topline is at wp->w_lsize_lnum[i].
*/
if (row)
{
check_for_delay(FALSE);
if (win_del_lines(wp, 0, row, FALSE, wp == firstwin) == OK)
must_end_bot = TRUE;
}
if ((row == 0 || must_end_bot) && wp->w_lsize_valid)
{
/*
* Skip the lines (below the deleted lines) that are still
* valid and don't need redrawing. Copy their info
* upwards, to compensate for the deleted lines. Leave
* row and lnum on the first line that needs redrawing.
*/
srow = row;
row = 0;
for (;;)
{
if ((type == VALID_TO_CURSCHAR &&
lnum == wp->w_cursor.lnum) ||
(type == VALID_BEF_CURSCHAR &&
lnum == wp->w_cursor.lnum - 1))
{
wp->w_lsize_valid = idx;
break;
}
wp->w_lsize[idx] = wp->w_lsize[j];
wp->w_lsize_lnum[idx] = lnum;
if (row + srow + (int)wp->w_lsize[j] > wp->w_height)
{
wp->w_lsize_valid = idx + 1;
break;
}
++lnum;
row += wp->w_lsize[idx++];
if ((int)++j >= wp->w_lsize_valid)
{
wp->w_lsize_valid = idx;
break;
}
}
}
else
row = 0; /* update all lines */
}
}
if (endrow == wp->w_height && idx == 0) /* no scrolling */
wp->w_lsize_valid = 0;
}
done = didline = FALSE;
if (VIsual_active) /* check if we are updating the inverted part */
{
linenr_t from, to;
/*
* Find the line numbers that need to be updated: The lines between
* the old cursor position and the current cursor position. Also
* check if the Visual position changed.
*/
if (curwin->w_cursor.lnum < wp->w_old_cursor_lnum)
{
from = curwin->w_cursor.lnum;
to = wp->w_old_cursor_lnum;
}
else
{
from = wp->w_old_cursor_lnum;
to = curwin->w_cursor.lnum;
}
if (VIsual.lnum != wp->w_old_visual_lnum)
{
if (wp->w_old_visual_lnum < from)
from = wp->w_old_visual_lnum;
if (wp->w_old_visual_lnum > to)
to = wp->w_old_visual_lnum;
if (VIsual.lnum < from)
from = VIsual.lnum;
if (VIsual.lnum > to)
to = VIsual.lnum;
}
/*
* If in block mode and changed column or curwin->w_curswant: update
* all lines.
* First compute the actual start and end column.
*/
if (VIsual_mode == Ctrl('V'))
{
colnr_t from1, from2, to1, to2;
if (lt(VIsual, curwin->w_cursor))
{
getvcol(wp, &VIsual, &from1, NULL, &to1);
getvcol(wp, &curwin->w_cursor, &from2, NULL, &to2);
}
else
{
getvcol(wp, &curwin->w_cursor, &from1, NULL, &to1);
getvcol(wp, &VIsual, &from2, NULL, &to2);
}
if (from2 < from1)
from1 = from2;
if (to2 > to1)
{
if (*p_sel == 'e' && from2 - 1 >= to1)
to1 = from2 - 1;
else
to1 = to2;
}
++to1;
if (curwin->w_curswant == MAXCOL)
to1 = MAXCOL;
if (from1 != wp->w_old_cursor_fcol || to1 != wp->w_old_cursor_lcol)
{
if (from > VIsual.lnum)
from = VIsual.lnum;
if (to < VIsual.lnum)
to = VIsual.lnum;
}
wp->w_old_cursor_fcol = from1;
wp->w_old_cursor_lcol = to1;
}
/*
* There is no need to update lines above the top of the window.
* If "must_start_top" is set, always start at w_topline.
*/
if (from < wp->w_topline || must_start_top)
from = wp->w_topline;
/*
* If we know the value of w_botline, use it to restrict the update to
* the lines that are visible in the window.
*/
if (wp->w_valid & VALID_BOTLINE)
{
if (from >= wp->w_botline)
from = wp->w_botline - 1;
if (to >= wp->w_botline)
to = wp->w_botline - 1;
}
/*
* Find the minimal part to be updated.
*
* If "lnum" is past "from" already, start at w_topline (can
* happen when scrolling).
*/
if (lnum > from)
{
lnum = wp->w_topline;
idx = 0;
row = 0;
}
while (lnum < from && idx < wp->w_lsize_valid) /* find start */
{
row += wp->w_lsize[idx++];
++lnum;
}
if (!must_end_bot && !must_start_top)
{
srow = row;
for (j = idx; j < wp->w_lsize_valid; ++j) /* find end */
{
if (wp->w_lsize_lnum[j] == to + 1)
{
endrow = srow;
break;
}
srow += wp->w_lsize[j];
}
}
else
{
/* Redraw until the end, otherwise we could miss something when
* doing CTRL-U. */
endrow = wp->w_height;
}
wp->w_old_cursor_lnum = curwin->w_cursor.lnum;
wp->w_old_visual_lnum = VIsual.lnum;
wp->w_old_curswant = curwin->w_curswant;
}
else
{
wp->w_old_cursor_lnum = 0;
wp->w_old_visual_lnum = 0;
}
/*
* Update the screen rows from "row" to "endrow".
* Start at line "lnum" which is at wp->w_lsize_lnum[idx].
*/
for (;;)
{
if (row == endrow)
{
didline = TRUE;
break;
}
if (lnum > wp->w_buffer->b_ml.ml_line_count)
{
done = TRUE; /* hit the end of the file */
break;
}
srow = row;
row = win_line(wp, lnum, srow, endrow);
if (row > endrow) /* past end of screen */
{
/* we may need the size of that too long line later on */
wp->w_lsize[idx] = plines_win(wp, lnum);
wp->w_lsize_lnum[idx++] = lnum;
break;
}
wp->w_lsize[idx] = row - srow;
wp->w_lsize_lnum[idx++] = lnum;
if (++lnum > wp->w_buffer->b_ml.ml_line_count)
{
done = TRUE;
break;
}
}
if (idx > wp->w_lsize_valid)
wp->w_lsize_valid = idx;
/* Do we have to do off the top of the screen processing ? */
if (endrow != wp->w_height)
{
row = 0;
for (idx = 0; idx < wp->w_lsize_valid && row < wp->w_height; idx++)
row += wp->w_lsize[idx];
if (row < wp->w_height)
{
done = TRUE;
}
else if (row > wp->w_height) /* Need to blank out the last line */
{
lnum = wp->w_lsize_lnum[idx - 1];
srow = row - wp->w_lsize[idx - 1];
didline = FALSE;
}
else
{
lnum = wp->w_lsize_lnum[idx - 1] + 1;
didline = TRUE;
}
}
wp->w_empty_rows = 0;
/*
* If we didn't hit the end of the file, and we didn't finish the last
* line we were working on, then the line didn't fit.
*/
if (!done && !didline)
{
if (lnum == wp->w_topline)
{
#if 0
/*
* Single line that does not fit!
* Fill last line with '@' characters.
*/
screen_fill(wp->w_winpos + wp->w_height - 1,
wp->w_winpos + wp->w_height, 0, (int)Columns, '@', '@',
hl_attr(HLF_AT));
#endif
wp->w_botline = lnum + 1;
}
else
{
/*
* Clear the rest of the screen and mark the unused lines.
*/
#ifdef RIGHTLEFT
if (wp->w_p_rl)
{
screen_fill(wp->w_winpos + srow,
wp->w_winpos + wp->w_height, 0, (int)Columns - 1,
' ', ' ', hl_attr(HLF_AT));
screen_fill(wp->w_winpos + srow,
wp->w_winpos + wp->w_height, (int)Columns - 1,
(int)Columns, '@', ' ', hl_attr(HLF_AT));
}
else
#endif
screen_fill(wp->w_winpos + srow,
wp->w_winpos + wp->w_height, 0, (int)Columns, '@', ' ',
hl_attr(HLF_AT));
wp->w_botline = lnum;
wp->w_empty_rows = wp->w_height - srow;
}
}
else
{
/* make sure the rest of the screen is blank */
/* put '~'s on rows that aren't part of the file. */
#ifdef RIGHTLEFT
if (wp->w_p_rl)
{
screen_fill(wp->w_winpos + row,
wp->w_winpos + wp->w_height, 0, (int)Columns - 1,
' ', ' ', hl_attr(HLF_AT));
screen_fill(wp->w_winpos + row,
wp->w_winpos + wp->w_height, (int)Columns - 1,
(int)Columns, '~', ' ', hl_attr(HLF_AT));
}
else
#endif
screen_fill(wp->w_winpos + row,
wp->w_winpos + wp->w_height, 0, (int)Columns, '~', ' ',
hl_attr(HLF_AT));
wp->w_empty_rows = wp->w_height - row;
if (done) /* we hit the end of the file */
wp->w_botline = wp->w_buffer->b_ml.ml_line_count + 1;
else
wp->w_botline = lnum;
}
/*
* There is a trick with w_botline. If we invalidate it on each change
* that might modify it, this will cause a lot of expensive calls to
* plines() in update_topline() each time. Therefore the value of
* w_botline is often approximated, and this value is used to compute the
* value of w_topline. If the value of w_botline was wrong, check that
* the value of w_topline is correct (cursor is on the visible part of the
* text). If it's not, we need to redraw again. Mostly this just means
* scrolling up a few lines, so it doesn't look too bad. Only do this for
* the current window (where changes are relevant).
*/
wp->w_valid |= VALID_BOTLINE;
if (wp == curwin && wp->w_botline != old_botline && !recursive)
{
recursive = TRUE;
update_topline(); /* may invalidate w_botline again */
if (must_redraw)
{
win_update(wp);
must_redraw = 0;
}
recursive = FALSE;
}
/* When insering lines at top, these have been redrawn now. Still need to
* redraw other lines with changes */
if (wp->w_redr_type && !recursive)
{
recursive = TRUE;
win_update(wp);
recursive = FALSE;
}
}
/*
* Display line "lnum" of window 'wp' on the screen.
* Start at row "startrow", stop when "endrow" is reached.
* wp->w_virtcol needs to be valid.
*
* Return the number of last row the line occupies.
*/
static int
win_line(wp, lnum, startrow, endrow)
WIN *wp;
linenr_t lnum;
int startrow;
int endrow;
{
char_u *screenp;
int c = 0; /* init for GCC */
int col; /* visual column on screen */
long vcol; /* visual column for tabs */
long v;
#ifdef SYNTAX_HL
int rcol; /* real column in the line */
#endif
int row; /* row in the window, excl w_winpos */
int screen_row; /* row on the screen, incl w_winpos */
char_u *ptr;
#ifdef SYNTAX_HL
char_u *line;
#endif
char_u extra[16]; /* "%ld" must fit in here */
int n_extra = 0; /* number of extra chars */
char_u *p_extra = NULL; /* string of extra chars */
int c_extra = NUL; /* extra chars, all the same */
char_u *showbreak = NULL;
int n_attr = 0; /* chars with current attr */
int n_skip = 0; /* nr of chars to skip for 'nowrap' */
int n_number = 0; /* chars for 'number' */
int fromcol, tocol; /* start/end of inverting */
int noinvcur = FALSE; /* don't invert the cursor */
FPOS *top, *bot;
int area_highlighting; /* Visual or incsearch highlighting in
this line */
int attr; /* attributes for area highlighting */
int area_attr = 0; /* attributes desired by highlighting */
int search_attr = 0; /* attributes sesired by 'searchhl' */
#ifdef SYNTAX_HL
int syntax_attr = 0; /* attributes desired by syntax */
int has_syntax = FALSE; /* this buffer has syntax highl. */
#endif
int extra_check; /* has syntax or linebreak */
int char_attr; /* attributes for next character */
int saved_attr1 = 0; /* char_attr saved for showbreak */
int saved_attr2 = 0; /* char_attr saved for listtabstring */
int extra_attr = 0;
#ifdef EXTRA_SEARCH
char_u *matchp;
char_u *search_hl_start = NULL;
char_u *search_hl_end = NULL;
#endif
#ifdef MULTI_BYTE
int bCharacter = 0;
char_u *line_head;
#endif
char_u *trail = NULL; /* start of trailing spaces */
if (startrow > endrow) /* past the end already! */
return startrow;
row = startrow;
screen_row = row + wp->w_winpos;
attr = hl_attr(HLF_V);
/*
* To speed up the loop below, set extra_check when there is linebreak,
* trailing white spcae and/or syntax processing to be done.
*/
extra_check = wp->w_p_lbr;
#ifdef SYNTAX_HL
if (syntax_present(wp->w_buffer))
{
syntax_start(wp, lnum);
has_syntax = TRUE;
extra_check = TRUE;
}
#endif
col = 0;
vcol = 0;
fromcol = -10;
tocol = MAXCOL;
area_highlighting = FALSE;
char_attr = 0;
/*
* handle visual active in this window
*/
if (VIsual_active && wp->w_buffer == curwin->w_buffer)
{
/* Visual is after curwin->w_cursor */
if (ltoreq(curwin->w_cursor, VIsual))
{
top = &curwin->w_cursor;
bot = &VIsual;
}
else /* Visual is before curwin->w_cursor */
{
top = &VIsual;
bot = &curwin->w_cursor;
}
if (VIsual_mode == Ctrl('V')) /* block mode */
{
if (lnum >= top->lnum && lnum <= bot->lnum)
{
fromcol = wp->w_old_cursor_fcol;
tocol = wp->w_old_cursor_lcol;
}
}
else /* non-block mode */
{
if (lnum > top->lnum && lnum <= bot->lnum)
fromcol = 0;
else if (lnum == top->lnum)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -