📄 misc1.c
字号:
{
STRNCPY(leader, saved_line, lead_len);
leader[lead_len] = NUL;
/*
* Replace leader with lead_repl, right or left adjusted
*/
if (lead_repl != NULL)
{
for (p = lead_flags; *p && *p != ':'; ++p)
if (*p == COM_RIGHT || *p == COM_LEFT)
break;
if (*p == COM_RIGHT) /* right adjusted leader */
{
/* find last non-white in the leader to line up with */
for (p = leader + lead_len - 1; p > leader &&
vim_iswhite(*p); --p)
;
++p;
if (p < leader + lead_repl_len)
p = leader;
else
p -= lead_repl_len;
mch_memmove(p, lead_repl, (size_t)lead_repl_len);
if (p + lead_repl_len > leader + lead_len)
p[lead_repl_len] = NUL;
/* blank-out any other chars from the old leader. */
while (--p >= leader)
if (!vim_iswhite(*p))
*p = ' ';
}
else /* left adjusted leader */
{
p = skipwhite(leader);
mch_memmove(p, lead_repl, (size_t)lead_repl_len);
/* blank-out any other chars from the old leader. */
for (p += lead_repl_len; p < leader + lead_len; ++p)
if (!vim_iswhite(*p))
*p = ' ';
*p = NUL;
}
/* Recompute the indent, it may have changed. */
if (curbuf->b_p_ai
#ifdef SMARTINDENT
|| curbuf->b_p_si
#endif
)
newindent = get_indent_str(leader);
}
lead_len = STRLEN(leader);
if (extra_space)
{
leader[lead_len++] = ' ';
leader[lead_len] = NUL;
}
newcol = lead_len;
/*
* if a new indent will be set below, remove the indent that
* is in the comment leader
*/
if (newindent
#ifdef SMARTINDENT
|| did_si
#endif
)
{
while (lead_len && vim_iswhite(*leader))
{
--lead_len;
--newcol;
++leader;
}
}
}
#ifdef SMARTINDENT
did_si = can_si = FALSE;
#endif
}
else if (comment_end != NULL)
{
/*
* We have finished a comment, so we don't use the leader.
* If this was a C-comment and 'ai' or 'si' is set do a normal
* indent to align with the line containing the start of the
* comment.
*/
if (comment_end[0] == '*' && comment_end[1] == '/' &&
(curbuf->b_p_ai
#ifdef SMARTINDENT
|| curbuf->b_p_si
#endif
))
{
old_cursor = curwin->w_cursor;
curwin->w_cursor.col = comment_end - saved_line;
if ((pos = findmatch(NULL, NUL)) != NULL)
{
curwin->w_cursor.lnum = pos->lnum;
newindent = get_indent();
}
curwin->w_cursor = old_cursor;
}
}
}
/* (State == INSERT || State == REPLACE), only when dir == FORWARD */
if (p_extra != NULL)
{
*p_extra = saved_char; /* restore char that NUL replaced */
/*
* When 'ai' set or "del_spaces" TRUE, skip to the first non-blank.
*
* When in REPLACE mode, put the deleted blanks on the replace stack,
* preceded by a NUL, so they can be put back when a BS is entered.
*/
if (State == REPLACE)
replace_push(NUL); /* end of extra blanks */
if (curbuf->b_p_ai || del_spaces)
{
while (*p_extra == ' ' || *p_extra == '\t')
{
if (State == REPLACE)
replace_push(*p_extra);
++p_extra;
}
}
if (*p_extra != NUL)
did_ai = FALSE; /* append some text, don't trucate now */
}
if (p_extra == NULL)
p_extra = (char_u *)""; /* append empty line */
/* concatenate leader and p_extra, if there is a leader */
if (lead_len)
{
STRCAT(leader, p_extra);
p_extra = leader;
}
old_cursor = curwin->w_cursor;
if (dir == BACKWARD)
--curwin->w_cursor.lnum;
if (ml_append(curwin->w_cursor.lnum, p_extra, (colnr_t)0, FALSE) == FAIL)
goto theend;
changed_line_abv_curs(); /* update cursor screen position later */
mark_adjust(curwin->w_cursor.lnum + 1, (linenr_t)MAXLNUM, 1L, 0L);
if (newindent
#ifdef SMARTINDENT
|| did_si
#endif
)
{
++curwin->w_cursor.lnum;
#ifdef SMARTINDENT
if (did_si)
{
if (p_sr)
newindent -= newindent % (int)curbuf->b_p_sw;
newindent += (int)curbuf->b_p_sw;
}
#endif
set_indent(newindent, FALSE);
/*
* In REPLACE mode, for each character in the new indent, there must
* be a NUL on the replace stack, for when it is deleted with BS
*/
if (State == REPLACE)
for (n = 0; n < (int)curwin->w_cursor.col; ++n)
replace_push(NUL);
newcol += curwin->w_cursor.col;
#ifdef SMARTINDENT
if (no_si)
did_si = FALSE;
#endif
}
/*
* In REPLACE mode, for each character in the extra leader, there must be
* a NUL on the replace stack, for when it is deleted with BS.
*/
if (State == REPLACE)
while (lead_len-- > 0)
replace_push(NUL);
curwin->w_cursor = old_cursor;
if (dir == FORWARD)
{
if (redraw) /* want to know the old number of screen lines */
{
old_plines = plines(curwin->w_cursor.lnum);
new_plines = old_plines;
}
if (trunc_line || State == INSERT || State == REPLACE)
{
if (trunc_line)
{
/* find start of trailing white space */
for (n = STRLEN(saved_line); n > 0 &&
vim_iswhite(saved_line[n - 1]); --n)
;
saved_line[n] = NUL;
}
else /* truncate current line at cursor */
*(saved_line + curwin->w_cursor.col) = NUL;
ml_replace(curwin->w_cursor.lnum, saved_line, FALSE);
saved_line = NULL;
#ifdef SYNTAX_HL
/* recompute syntax hl. for this line */
syn_changed(curwin->w_cursor.lnum);
#endif
if (redraw)
new_plines = plines(curwin->w_cursor.lnum);
}
/*
* Get the cursor to the start of the line, so that 'curwin->w_wrow'
* gets set to the right physical line number for the stuff that
* follows...
*/
curwin->w_cursor.col = 0;
if (redraw)
{
/*
* If we're doing an open on the last logical line, then go ahead
* and scroll the screen up. Otherwise, just insert blank lines
* at the right place if the number of screen lines changed.
* We use calls to plines() in case the cursor is resting on a
* long line, we want to know the row below the line.
*
* Note: using w_cline_row from before the change!
*/
n = curwin->w_cline_row + new_plines;
if (n + plines(curwin->w_cursor.lnum + 1) - 1 >=
curwin->w_height - p_so)
{
/* If redraw < 0, will later redraw with NOT_VALID, thus not
* scroll but redraw. Scroll the text here instead. */
if (redraw < 0)
win_del_lines(curwin, 0, plines(curwin->w_topline),
TRUE, TRUE);
scrollup(1L);
}
else
win_ins_lines(curwin, n,
plines(curwin->w_cursor.lnum + 1) + new_plines - old_plines,
TRUE, TRUE);
}
/*
* Put the cursor on the new line. Careful: the scrollup() above may
* have moved w_cursor, we must use old_cursor.
*/
curwin->w_cursor.lnum = old_cursor.lnum + 1;
}
else if (redraw)
{
/*
* Insert physical line above current line.
* Note: use w_cline_row from before the change.
*/
win_ins_lines(curwin, curwin->w_cline_row, 1, TRUE, TRUE);
}
curwin->w_cursor.col = newcol;
#ifdef LISPINDENT
/*
* May do lisp indenting.
*/
if (leader == NULL && curbuf->b_p_lisp && curbuf->b_p_ai)
fixthisline(get_lisp_indent);
#endif
#ifdef CINDENT
/*
* May do indenting after opening a new line.
*/
if (leader == NULL && curbuf->b_p_cin &&
in_cinkeys(dir == FORWARD ? KEY_OPEN_FORW :
KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum)))
fixthisline(get_c_indent);
#endif
/*
* w_botline won't change much when inserting a new line.
*/
approximate_botline();
if (redraw > 0)
{
update_topline();
update_screen(VALID_BEF_CURSCHAR);
}
changed();
retval = TRUE; /* success! */
theend:
vim_free(saved_line);
vim_free(allocated);
return retval;
}
/*
* get_leader_len() returns the length of the prefix of the given string
* which introduces a comment. If this string is not a comment then 0 is
* returned.
* When "flags" is non-zero, it is set to point to the flags of the recognized
* comment leader.
*/
int
get_leader_len(line, flags)
char_u *line;
char_u **flags;
{
int i, j;
int got_com = FALSE;
int found_one;
char_u part_buf[COM_MAX_LEN]; /* buffer for one option part */
char_u *string; /* pointer to comment string */
char_u *list;
if (!fo_do_comments) /* don't format comments at all */
return 0;
i = 0;
while (vim_iswhite(line[i])) /* leading white space is ignored */
++i;
/*
* Repeat to match several nested comment strings.
*/
while (line[i])
{
/*
* scan through the 'comments' option for a match
*/
found_one = FALSE;
for (list = curbuf->b_p_com; *list; )
{
/*
* Get one option part into part_buf[]. Advance list to next one.
* put string at start of string.
*/
if (!got_com && flags != NULL) /* remember where flags started */
*flags = list;
(void)copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
string = vim_strchr(part_buf, ':');
if (string == NULL) /* missing ':', ignore this part */
continue;
*string++ = NUL; /* isolate flags from string */
/*
* When already found a nested comment, only accept further
* nested comments.
*/
if (got_com && vim_strchr(part_buf, COM_NEST) == NULL)
continue;
/*
* Line contents and string must match.
*/
for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j)
;
if (string[j] != NUL)
continue;
/*
* When 'b' flag used, there must be white space or an
* end-of-line after the string in the line.
*/
if (vim_strchr(part_buf, COM_BLANK) != NULL &&
!vim_iswhite(line[i + j]) && line[i + j] != NUL)
continue;
/*
* We have found a match, stop searching.
*/
i += j;
got_com = TRUE;
found_one = TRUE;
break;
}
/*
* No match found, stop scanning.
*/
if (!found_one)
break;
/*
* Include any trailing white space.
*/
while (vim_iswhite(line[i]))
++i;
/*
* If this comment doesn't nest, stop here.
*/
if (vim_strchr(part_buf, COM_NEST) == NULL)
break;
}
return (got_com ? i : 0);
}
/*
* plines(p) - return the number of physical screen lines taken by line 'p'
*/
int
plines(p)
linenr_t p;
{
return plines_win(curwin, p);
}
int
plines_win(wp, p)
WIN *wp;
linenr_t p;
{
long col;
char_u *s;
int lines;
if (!wp->w_p_wrap)
return 1;
s = ml_get_buf(wp->w_buffer, p, FALSE);
if (*s == NUL) /* empty line */
return 1;
col = win_linetabsize(wp, s);
/*
* If list mode is on, then the '$' at the end of the line may take up one
* extra column.
*/
if (wp->w_p_list && lcs_eol != NUL)
col += 1;
/*
* If 'number' mode is on, add another 8.
*/
if (wp->w_p_nu)
col += 8;
lines = (col + (Columns - 1)) / Columns;
if (lines <= wp->w_height)
return lines;
return (int)(wp->w_height); /* maximum length */
}
/*
* Like plines_win(), but only reports the number of physical screen lines used
* from the start of the line to the given column number.
*/
int
plines_win_col(wp, p, column)
WIN *wp;
linenr_t p;
long column;
{
register long col;
register char_u *s;
register int lines;
if (!wp->w_p_wrap)
return 1;
s = ml_get_buf(wp->w_buffer, p, FALSE);
col = 0;
while (*s != NUL && --column >= 0)
col += win_lbr_chartabsize(wp, s++, (colnr_t)col, NULL);
/*
* If *s is a TAB, and the TAB is not displayed as ^I, and we're not in
* INSERT mode, then col must be adjusted so that it represents the last
* screen position of the TAB. This only fixes an error when the TAB wraps
* from one screen line to the next (when 'columns' is not a multiple of
* 'ts') -- webb.
*/
if (*s == TAB && (State & NORMAL) && (!wp->w_p_list || lcs_tab1))
col += win_lbr_chartabsize(wp, s, (colnr_t)col, NULL) - 1;
/*
* If 'number' mode is on, add another 8.
*/
if (wp->w_p_nu)
col += 8;
lines = 1 + col / Columns;
if (lines <= wp->w_height)
return lines;
return (int)(wp->w_height); /* maximum length */
}
/*
* Count the physical lines (rows) for the lines "first" to "last" inclusive.
*/
int
plines_m(first, last)
linenr_t first, last;
{
return plines_m_win(curwin, first, last);
}
int
plines_m_win(wp, first, last)
WIN *wp;
linenr_t first, last;
{
int count = 0;
while (first <= last)
count += plines_win(wp, first++);
return (count);
}
/*
* Insert or replace a single character at the cursor position.
* When in REPLACE mode, replace any existing character.
*/
void
ins_char(c)
int c;
{
char_u *p;
char_u *newp;
char_u *oldp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -