📄 edit.c
字号:
tw_save = curbuf->b_p_tw;
curbuf->b_p_tw = -1;
insert_special(c, TRUE, TRUE);
curbuf->b_p_tw = tw_save;
need_redraw = TRUE;
#ifdef RIGHTLEFT
revins_chars++;
revins_legal++;
#endif
c = Ctrl('V'); /* pretend CTRL-V is last character */
}
}
break;
default:
#ifdef UNIX
if (c == intr_char) /* special interrupt char */
goto do_intr;
#endif
normalchar:
#ifdef SMARTINDENT
/*
* Try to perform smart-indenting.
*/
ins_try_si(c);
#endif
if (c == ' ')
{
inserted_space = TRUE;
#ifdef CINDENT
if (inindent(0))
can_cindent = FALSE;
#endif
if (Insstart_blank_vcol == MAXCOL
&& curwin->w_cursor.lnum == Insstart.lnum)
Insstart_blank_vcol = get_nolist_virtcol();
}
if (vim_iswordc(c) || !echeck_abbr(c))
{
insert_special(c, FALSE, FALSE);
need_redraw = TRUE;
#ifdef RIGHTLEFT
revins_legal++;
revins_chars++;
#endif
}
break;
} /* end of switch (c) */
#ifdef CINDENT
if (curbuf->b_p_cin && can_cindent
# ifdef INSERT_EXPAND
&& !ctrl_x_mode
# endif
)
{
force_cindent:
/*
* Indent now if a key was typed that is in 'cinkeys'.
*/
if (in_cinkeys(c, ' ', line_is_white))
{
stop_arrow();
/* re-indent the current line */
fixthisline(get_c_indent);
/* draw the changes on the screen later */
need_redraw = TRUE;
}
}
#endif /* CINDENT */
} /* for (;;) */
/* NOTREACHED */
}
/*
* Put a character directly onto the screen. It's not stored in a buffer.
* Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
*/
static void
edit_putchar(c, highlight)
int c;
int highlight;
{
int attr;
if (NextScreen != NULL)
{
update_topline(); /* just in case w_topline isn't valid */
validate_cursor();
if (highlight)
attr = hl_attr(HLF_8);
else
attr = 0;
screen_putchar(c, curwin->w_winpos + curwin->w_wrow,
#ifdef RIGHTLEFT
curwin->w_p_rl ? (int)Columns - 1 - curwin->w_wcol :
#endif
curwin->w_wcol, attr);
}
}
/*
* Called when p_dollar is set: display a '$' at the end of the changed text
* Only works when cursor is in the line that changes.
*/
void
display_dollar(col)
colnr_t col;
{
colnr_t save_col;
if (!redrawing())
return;
cursor_off();
save_col = curwin->w_cursor.col;
curwin->w_cursor.col = col;
curs_columns(FALSE); /* recompute w_wrow and w_wcol */
if (curwin->w_wcol < Columns)
{
edit_putchar('$', FALSE);
dollar_vcol = curwin->w_virtcol;
}
curwin->w_cursor.col = save_col;
}
/*
* Call this function before moving the cursor from the normal insert position
* in insert mode.
*/
static void
undisplay_dollar()
{
if (dollar_vcol)
{
dollar_vcol = 0;
update_screenline();
}
}
/*
* Insert an indent (for <Tab> or CTRL-T) or delete an indent (for CTRL-D).
* Keep the cursor on the same character.
* type == INDENT_INC increase indent (for CTRL-T or <Tab>)
* type == INDENT_DEC decrease indent (for CTRL-D)
* type == INDENT_SET set indent to "amount"
* if round is TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec).
*/
static void
change_indent(type, amount, round, replaced)
int type;
int amount;
int round;
int replaced; /* replaced character, put on replace stack */
{
int vcol;
int last_vcol;
int insstart_less; /* reduction for Insstart.col */
int new_cursor_col;
int i;
char_u *ptr;
int save_p_list;
int start_col;
colnr_t vc;
/* for the following tricks we don't want list mode */
save_p_list = curwin->w_p_list;
curwin->w_p_list = FALSE;
getvcol(curwin, &curwin->w_cursor, NULL, &vc, NULL);
vcol = vc;
/*
* For Replace mode we need to fix the replace stack later, which is only
* possible when the cursor is in the indent. Remember the number of
* characters before the cursor if it's possible.
*/
start_col = curwin->w_cursor.col;
/* determine offset from first non-blank */
new_cursor_col = curwin->w_cursor.col;
beginline(BL_WHITE);
new_cursor_col -= curwin->w_cursor.col;
insstart_less = curwin->w_cursor.col;
/*
* If the cursor is in the indent, compute how many screen columns the
* cursor is to the left of the first non-blank.
*/
if (new_cursor_col < 0)
vcol = get_indent() - vcol;
if (new_cursor_col > 0) /* can't fix replace stack */
start_col = -1;
/*
* Set the new indent. The cursor will be put on the first non-blank.
*/
if (type == INDENT_SET)
set_indent(amount, TRUE);
else
shift_line(type == INDENT_DEC, round, 1);
insstart_less -= curwin->w_cursor.col;
/*
* Try to put cursor on same character.
* If the cursor is at or after the first non-blank in the line,
* compute the cursor column relative to the column of the first
* non-blank character.
* If we are not in insert mode, leave the cursor on the first non-blank.
* If the cursor is before the first non-blank, position it relative
* to the first non-blank, counted in screen columns.
*/
if (new_cursor_col >= 0)
new_cursor_col += curwin->w_cursor.col;
else if (!(State & INSERT))
new_cursor_col = curwin->w_cursor.col;
else
{
/*
* Compute the screen column where the cursor should be.
*/
vcol = get_indent() - vcol;
curwin->w_virtcol = (vcol < 0) ? 0 : vcol;
/*
* Advance the cursor until we reach the right screen column.
*/
vcol = last_vcol = 0;
new_cursor_col = -1;
ptr = ml_get_curline();
while (vcol <= (int)curwin->w_virtcol)
{
last_vcol = vcol;
++new_cursor_col;
vcol += lbr_chartabsize(ptr + new_cursor_col, (colnr_t)vcol);
}
vcol = last_vcol;
/*
* May need to insert spaces to be able to position the cursor on
* the right screen column.
*/
if (vcol != (int)curwin->w_virtcol)
{
curwin->w_cursor.col = new_cursor_col;
i = (int)curwin->w_virtcol - vcol;
ptr = alloc(i + 1);
if (ptr != NULL)
{
new_cursor_col += i;
ptr[i] = NUL;
while (--i >= 0)
ptr[i] = ' ';
ins_str(ptr);
vim_free(ptr);
}
}
/*
* When changing the indent while the cursor is in it, reset
* Insstart_col to 0.
*/
insstart_less = Insstart.col;
}
curwin->w_p_list = save_p_list;
if (new_cursor_col <= 0)
curwin->w_cursor.col = 0;
else
curwin->w_cursor.col = new_cursor_col;
curwin->w_set_curswant = TRUE;
changed_cline_bef_curs();
/*
* May have to adjust the start of the insert.
*/
if ((State & INSERT) && curwin->w_cursor.lnum == Insstart.lnum &&
Insstart.col != 0)
{
if ((int)Insstart.col <= insstart_less)
Insstart.col = 0;
else
Insstart.col -= insstart_less;
}
/*
* May have to fix the replace stack, if it's possible.
* If the number of characters before the cursor decreased, need to pop a
* few characters from the replace stack.
* If the number of characters before the cursor increased, need to push a
* few NULs onto the replace stack.
*/
if (State == REPLACE && start_col >= 0)
{
while (start_col > (int)curwin->w_cursor.col)
{
replace_join(0); /* remove a NUL from the replace stack */
--start_col;
}
while (start_col < (int)curwin->w_cursor.col || replaced)
{
replace_push(NUL);
if (replaced)
{
replace_push(replaced);
replaced = NUL;
}
++start_col;
}
}
}
#ifdef INSERT_EXPAND
/*
* Is the character 'c' a valid key to keep us in the current ctrl-x mode?
* -- webb
*/
int
vim_is_ctrl_x_key(c)
int c;
{
switch (ctrl_x_mode)
{
case 0: /* Not in any ctrl-x mode */
break;
case CTRL_X_NOT_DEFINED_YET:
if ( c == Ctrl('X') || c == Ctrl('Y') || c == Ctrl('E')
|| c == Ctrl('L') || c == Ctrl('F') || c == Ctrl(']')
|| c == Ctrl('I') || c == Ctrl('D') || c == Ctrl('P')
|| c == Ctrl('N'))
return TRUE;
break;
case CTRL_X_SCROLL:
if (c == Ctrl('Y') || c == Ctrl('E'))
return TRUE;
break;
case CTRL_X_WHOLE_LINE:
if (c == Ctrl('L') || c == Ctrl('P') || c == Ctrl('N'))
return TRUE;
break;
case CTRL_X_FILES:
if (c == Ctrl('F') || c == Ctrl('P') || c == Ctrl('N'))
return TRUE;
break;
case CTRL_X_DICTIONARY:
if (c == Ctrl('K') || c == Ctrl('P') || c == Ctrl('N'))
return TRUE;
break;
case CTRL_X_TAGS:
if (c == Ctrl(']') || c == Ctrl('P') || c == Ctrl('N'))
return TRUE;
break;
#ifdef FIND_IN_PATH
case CTRL_X_PATH_PATTERNS:
if (c == Ctrl('P') || c == Ctrl('N'))
return TRUE;
break;
case CTRL_X_PATH_DEFINES:
if (c == Ctrl('D') || c == Ctrl('P') || c == Ctrl('N'))
return TRUE;
break;
#endif
default:
emsg(e_internal);
break;
}
return FALSE;
}
/*
* This is like add_completion(), but if ic and inf are set, then the
* case of the originally typed text is used, and the case of the completed
* text is infered, ie this tries to work out what case you probably wanted
* the rest of the word to be in -- webb
*/
int
add_completion_and_infercase(str, len, fname, dir, reuse)
char_u *str;
int len;
char_u *fname;
int dir;
int reuse;
{
int has_lower = FALSE;
int was_letter = FALSE;
int idx;
if (p_ic && curbuf->b_p_inf && len < IOSIZE)
{
/* Infer case of completed part -- webb */
/* Use IObuff, str would change text in buffer! */
STRNCPY(IObuff, str, len);
IObuff[len] = NUL;
/* Rule 1: Were any chars converted to lower? */
for (idx = 0; idx < completion_length; ++idx)
{
if (islower(original_text[idx]))
{
has_lower = TRUE;
if (isupper(IObuff[idx]))
{
/* Rule 1 is satisfied */
for (idx = completion_length; idx < len; ++idx)
IObuff[idx] = TO_LOWER(IObuff[idx]);
break;
}
}
}
/*
* Rule 2: No lower case, 2nd consecutive letter converted to
* upper case.
*/
if (!has_lower)
{
for (idx = 0; idx < completion_length; ++idx)
{
if (was_letter && isupper(original_text[idx]) &&
islower(IObuff[idx]))
{
/* Rule 2 is satisfied */
for (idx = completion_length; idx < len; ++idx)
IObuff[idx] = TO_UPPER(IObuff[idx]);
break;
}
was_letter = isalpha(original_text[idx]);
}
}
/* Copy the original case of the part we typed */
STRNCPY(IObuff, original_text, completion_length);
return add_completion(IObuff, len, fname, dir, reuse);
}
return add_completion(str, len, fname, dir, reuse);
}
/*
* Add a match to the list of matches.
* If the given string is already in the list of completions, then return
* FAIL, otherwise add it to the list and return OK. If there is an error,
* maybe because alloc returns NULL, then RET_ERROR is returned -- webb.
*/
static int
add_completion(str, len, fname, dir, reuse)
char_u *str;
int len;
char_u *fname;
int dir;
int reuse;
{
struct Completion *match;
ui_breakcheck();
if (got_int)
return RET_ERROR;
if (len < 0)
len = STRLEN(str);
/*
* If the same match is already present, don't add it.
*/
if (first_match != NULL)
{
match = first_match;
do
{
if ( !(match->original & ORIGINAL_TEXT)
&& STRNCMP(match->str, str, (size_t)len) == 0
&& match->str[len] == NUL)
return FAIL;
match = match->next;
} while (match != NULL && match != first_match);
}
/*
* Allocate a new match structure.
* Copy the values to the new match structure.
*/
match = (struct Completion *)alloc((unsigned)sizeof(struct Completion));
if (match == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -