📄 screen.c
字号:
col == Columns - 1)
&& (*ptr != NUL
|| (wp->w_p_list && lcs_eol != NUL)
|| (n_extra && (c_extra != NUL || *p_extra != NUL))))
{
c = lcs_ext;
char_attr = hl_attr(HLF_AT);
}
#ifdef MULTI_BYTE
if (is_dbcs)
{
/* if an mult-byte character splits by line edge,
lead or trail byte is substituted by '~' */
if (col == 0 && bCharacter)
{
if (IsTrailByte(line_head, ptr-1))
c = '~';
}
if (
# ifdef RIGHTLEFT
wp->w_p_rl ? (col <= 0) :
# endif
(col >= Columns-1))
{
if (bCharacter && IsLeadByte(*(ptr-1))
&& IsTrailByte(line_head, ptr))
c = '~';
}
bCharacter = 0;
}
#endif
/* Skip characters that are left of the screen for 'nowrap' */
if (n_number > 0 || n_skip <= 0)
{
/*
* Store the character.
*/
*screenp = c;
*(screenp + Columns) = char_attr;
#ifdef RIGHTLEFT
if (wp->w_p_rl)
{
--screenp;
--col;
}
else
#endif
{
++screenp;
++col;
}
--n_number;
}
else
--n_skip;
++vcol;
/* restore attributes after last 'listchars' or 'number' char */
if (n_attr && --n_attr == 0)
char_attr = saved_attr2;
/* When still displaying '$' of change command, stop at cursor */
if (dollar_vcol && wp == curwin && vcol >= (long)wp->w_virtcol)
{
SCREEN_LINE(screen_row, col, FALSE, wp->w_p_rl);
break;
}
}
return (row);
}
/*
* Move one "cooked" screen line to the screen, but only the characters that
* have actually changed. Handle insert/delete character.
* 'endcol' gives the columns where valid characters are.
* 'clear_rest' is TRUE if the rest of the line needs to be cleared.
* 'rlflag' is TRUE in a rightleft window:
* When TRUE and clear_rest, line is cleared in 0 -- endcol.
* When FALSE and clear_rest, line is cleared in endcol -- Columns-1.
*/
static void
screen_line(row, endcol, clear_rest
#ifdef RIGHTLEFT
, rlflag
#endif
)
int row;
int endcol;
int clear_rest;
#ifdef RIGHTLEFT
int rlflag;
#endif
{
char_u *screenp_from;
char_u *screenp_to;
int col = 0;
int force = FALSE; /* force update rest of the line */
screenp_from = current_LinePointer;
screenp_to = LinePointers[row];
#ifdef RIGHTLEFT
if (rlflag)
{
if (clear_rest)
{
while (col <= endcol && *screenp_to == ' '
&& *(screenp_to + Columns) == 0)
{
++screenp_to;
++col;
}
if (col <= endcol)
screen_fill(row, row + 1, col, endcol + 1, ' ', ' ', 0);
}
col = endcol + 1;
screenp_to = LinePointers[row] + col;
screenp_from += col;
}
while (rlflag ? (col < Columns) : (col < endcol))
#else
while (col < endcol)
#endif
{
if (
#if defined(MULTI_BYTE)
/* a multi byte ch. is misprinted when right/left scrolling. */
is_dbcs ||
#endif
force
|| *screenp_from != *screenp_to
|| *(screenp_from + Columns) != *(screenp_to + Columns)
)
{
/*
* Special handling when 'xs' termcap flag set (hpterm):
* Attributes for characters are stored at the position where the
* cursor is when writing the highlighting code. The
* start-highlighting code must be written with the cursor on the
* first highlighted character. The stop-highlighting code must
* be written with the cursor just after the last highlighted
* character.
* Overwriting a character doesn't remove it's highlighting. Need
* to clear the rest of the line, and force redrawing it
* completely.
*/
if ( p_wiv
&& !force
#ifdef USE_GUI
&& !gui.in_use
#endif
&& *(screenp_to + Columns)
&& *(screenp_from + Columns) != *(screenp_to + Columns))
{
/*
* Need to remove highlighting attributes here.
*/
windgoto(row, col);
out_str(T_CE); /* clear rest of this screen line */
screen_start(); /* don't know where cursor is now */
force = TRUE; /* force redraw of rest of the line */
/*
* If the previous character was highlighted, need to stop
* highlighting at this character.
*/
if (col > 0 && *(screenp_to + Columns - 1))
{
screen_attr = *(screenp_to + Columns - 1);
term_windgoto(row, col);
screen_stop_highlight();
}
else
screen_attr = 0; /* highlighting has stopped */
}
*screenp_to = *screenp_from;
#if defined(USE_GUI) || defined(UNIX)
/* The bold trick makes a single row of pixels appear in the next
* character. When a bold character is removed, the next
* character should be redrawn too. This happens for our own GUI
* and for some xterms. */
if (
# ifdef USE_GUI
gui.in_use
# endif
# if defined(USE_GUI) && defined(UNIX)
||
# endif
# ifdef UNIX
vim_is_xterm(T_NAME)
# endif
)
{
int n;
n = *(screenp_to + Columns);
if (col + 1 < Columns && (n > HL_ALL || (n & HL_BOLD)))
*(screenp_to + 1) = 0;
}
#endif
*(screenp_to + Columns) = *(screenp_from + Columns);
screen_char(screenp_to, row, col);
}
else if ( p_wiv
#ifdef USE_GUI
&& !gui.in_use
#endif
&& col > 0)
{
if (*(screenp_to + Columns) == *(screenp_to + Columns - 1))
{
/*
* Don't output stop-highlight when moving the cursor, it will
* stop the highlighting when it should continue.
*/
screen_attr = 0;
}
else if (screen_attr)
{
screen_stop_highlight();
}
}
++screenp_to;
++screenp_from;
++col;
}
if (clear_rest
#ifdef RIGHTLEFT
&& !rlflag
#endif
)
{
/* blank out the rest of the line */
while (col < Columns && *screenp_to == ' ' &&
*(screenp_to + Columns) == 0)
{
++screenp_to;
++col;
}
if (col < Columns)
screen_fill(row, row + 1, col, (int)Columns, ' ', ' ', 0);
}
}
/*
* mark all status lines for redraw; used after first :cd
*/
void
status_redraw_all()
{
WIN *wp;
for (wp = firstwin; wp; wp = wp->w_next)
if (wp->w_status_height)
{
wp->w_redr_status = TRUE;
redraw_later(NOT_VALID);
}
}
/*
* Redraw all status lines that need to be redrawn.
*/
void
redraw_statuslines()
{
WIN *wp;
for (wp = firstwin; wp; wp = wp->w_next)
if (wp->w_redr_status)
win_redr_status(wp);
}
/*
* Redraw the status line of window wp.
*
* If inversion is possible we use it. Else '=' characters are used.
*/
void
win_redr_status(wp)
WIN *wp;
{
int row;
char_u *p;
int len;
int fillchar;
int attr;
if (wp->w_status_height) /* if there is a status line */
{
fillchar = highlight_status(&attr, wp == curwin);
p = wp->w_buffer->b_fname;
if (p == NULL)
STRCPY(NameBuff, "[No File]");
else
{
home_replace(wp->w_buffer, p, NameBuff, MAXPATHL, TRUE);
trans_characters(NameBuff, MAXPATHL);
}
p = NameBuff;
len = STRLEN(p);
if (wp->w_buffer->b_help || buf_changed(wp->w_buffer) ||
wp->w_buffer->b_p_ro)
*(p + len++) = ' ';
if (wp->w_buffer->b_help)
{
STRCPY(p + len, "[help]");
len += 6;
}
if (buf_changed(wp->w_buffer))
{
STRCPY(p + len, "[+]");
len += 3;
}
if (wp->w_buffer->b_p_ro)
{
STRCPY(p + len, "[RO]");
len += 4;
}
if (len > ru_col - 1)
{
p += len - (ru_col - 1);
*p = '<';
len = ru_col - 1;
}
row = wp->w_winpos + wp->w_height;
screen_puts(p, row, 0, attr);
screen_fill(row, row + 1, len, ru_col, fillchar, fillchar, attr);
win_redr_ruler(wp, TRUE);
}
else /* no status line, can only be last window */
redraw_cmdline = TRUE;
wp->w_redr_status = FALSE;
}
/*
* Output a single character directly to the screen and update NextScreen.
*/
void
screen_putchar(c, row, col, attr)
int c;
int row, col;
int attr;
{
char_u buf[2];
buf[0] = c;
buf[1] = NUL;
screen_puts(buf, row, col, attr);
}
/*
* Put string '*text' on the screen at position 'row' and 'col', with
* attributes 'attr', and update NextScreen.
* Note: only outputs within one row, message is truncated at screen boundary!
* Note: if NextScreen, row and/or col is invalid, nothing is done.
*/
void
screen_puts(text, row, col, attr)
char_u *text;
int row;
int col;
int attr;
{
char_u *screenp;
if (NextScreen != NULL && row < Rows) /* safety check */
{
screenp = LinePointers[row] + col;
while (*text && col < Columns)
{
if (*screenp != *text || *(screenp + Columns) != attr ||
exmode_active)
{
*screenp = *text;
*(screenp + Columns) = attr;
screen_char(screenp, row, col);
}
++screenp;
++col;
++text;
}
}
}
#ifdef EXTRA_SEARCH
/*
* Prepare for 'searchhl' highlighting.
*/
static void
start_search_hl()
{
if (p_hls && !no_hlsearch)
{
search_hl_prog = last_pat_prog();
search_hl_attr = hl_attr(HLF_L);
search_hl_ic = reg_ic;
}
}
/*
* Clean up for 'searchhl' highlighting.
*/
static void
end_search_hl()
{
if (search_hl_prog != NULL)
{
vim_free(search_hl_prog);
search_hl_prog = NULL;
}
}
#endif
/*
* Reset cursor position. Use whenever cursor was moved because of outputting
* something directly to the screen (shell commands) or a terminal control
* code.
*/
void
screen_start()
{
screen_cur_row = screen_cur_col = 9999;
}
/*
* Note that the cursor has gone down to the next line, column 0.
* Used for Ex mode.
*/
void
screen_down()
{
screen_cur_col = 0;
if (screen_cur_row < Rows - 1)
++screen_cur_row;
}
static void
screen_start_highlight(attr)
int attr;
{
struct attr_entry *aep = NULL;
screen_attr = attr;
if (full_screen
#ifdef WIN32
&& termcap_active
#endif
)
{
#ifdef USE_GUI
if (gui.in_use)
{
char buf[20];
sprintf(buf, "\033|%dh", attr); /* internal GUI code */
OUT_STR(buf);
}
else
#endif
{
if (attr > HL_ALL) /* special HL attr. */
{
if (*T_CCO != NUL)
aep = syn_cterm_attr2entry(attr);
else
aep = syn_term_attr2entry(attr);
if (aep == NULL) /* did ":syntax clear" */
attr = 0;
else
attr = aep->ae_attr;
}
if ((attr & HL_BOLD) && T_MD != NULL) /* bold */
out_str(T_MD);
if ((attr & HL_STANDOUT) && T_SO != NULL) /* standout */
out_str(T_SO);
if ((attr & HL_UNDERLINE) && T_US != NULL) /* underline */
out_str(T_US);
if ((attr & HL_ITALIC) && T_CZH != NULL) /* italic */
out_str(T_CZH);
if ((attr & HL_INVERSE) && T_MR != NULL) /* inverse (reverse) */
out_str(T_MR);
/*
* Output the color or start string after bold etc., in case the
* bold etc. override the color setting.
*/
if (aep != NULL)
{
if (*T_CCO != NUL)
{
if (aep->ae_u.cterm.fg_color)
term_fg_color(aep->ae_u.cterm.fg_color - 1);
if (aep->ae_u.cterm.bg_color)
term_bg_color(aep->ae_u.cterm.bg_color - 1);
}
else
{
if (aep->ae_u.term.start != NULL)
out_str(aep->ae_u.term.start);
}
}
}
}
}
void
screen_stop_highlight()
{
int do_ME = FALSE; /* output T_ME code */
if (screen_attr
#ifdef WIN32
&& termcap_active
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -