⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 edit.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
		    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 + -