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

📄 misc1.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
    int		    oldlen;
    int		    extra;
    colnr_t	    col = curwin->w_cursor.col;
    linenr_t	    lnum = curwin->w_cursor.lnum;

    oldp = ml_get(lnum);
    oldlen = STRLEN(oldp) + 1;

    if (State != REPLACE || *(oldp + col) == NUL)
	extra = 1;
    else
	extra = 0;

    /*
     * A character has to be put on the replace stack if there is a
     * character that is replaced, so it can be put back when BS is used.
     */
    if (State == REPLACE)
    {
	replace_push(NUL);
	if (!extra)
	    replace_push(*(oldp + col));
    }
    newp = alloc_check((unsigned)(oldlen + extra));
    if (newp == NULL)
	return;
    mch_memmove(newp, oldp, (size_t)col);
    p = newp + col;
    mch_memmove(p + extra, oldp + col, (size_t)(oldlen - col));
#ifdef MULTI_BYTE
    /*
     * We define that "[]" is a multi-byte character.  For example. If
     * replace(R) is done over "a[]" with "[]".  finnaly, "[]]" is
     * constructed. but the following line replaces "[]]" with "[] ".
     */
    if (is_dbcs && State == REPLACE && IsLeadByte(*p) && p[1] != NUL)
	p[1] = ' ';
#endif
    *p = c;
    ml_replace(lnum, newp, FALSE);

    /*
     * If we're in insert or replace mode and 'showmatch' is set, then check for
     * right parens and braces. If there isn't a match, then beep. If there
     * is a match AND it's on the screen, then flash to it briefly. If it
     * isn't on the screen, don't do anything.
     */
#ifdef RIGHTLEFT
    if (p_sm && (State & INSERT) &&
	((!(curwin->w_p_rl ^ p_ri) && (c == ')' || c == '}' || c == ']')) ||
	 ((curwin->w_p_rl ^ p_ri) && (c == '(' || c == '{' || c == '['))))
#else
    if (p_sm && (State & INSERT) && (c == ')' || c == '}' || c == ']'))
#endif
	showmatch();

#ifdef RIGHTLEFT
    if (!p_ri || State == REPLACE)	/* normal insert: cursor right */
#endif
	++curwin->w_cursor.col;
    changed();
    /*
     * TODO: should try to update w_row here, to avoid recomputing it later.
     */
    changed_cline_bef_curs();
    approximate_botline();	/* w_botline might have changed */
}

/*
 * Insert a string at the cursor position.
 * Note: Nothing special for replace mode.
 */
    void
ins_str(s)
    char_u  *s;
{
    char_u	*oldp, *newp;
    int		newlen = STRLEN(s);
    int		oldlen;
    colnr_t	col = curwin->w_cursor.col;
    linenr_t	lnum = curwin->w_cursor.lnum;

    oldp = ml_get(lnum);
    oldlen = STRLEN(oldp);

    newp = alloc_check((unsigned)(oldlen + newlen + 1));
    if (newp == NULL)
	return;
    mch_memmove(newp, oldp, (size_t)col);
    mch_memmove(newp + col, s, (size_t)newlen);
    mch_memmove(newp + col + newlen, oldp + col, (size_t)(oldlen - col + 1));
    ml_replace(lnum, newp, FALSE);
    curwin->w_cursor.col += newlen;
    changed();
    changed_cline_bef_curs();
    approximate_botline();	/* w_botline might have changed */
}

/*
 * Delete one character under the cursor.
 * If 'fixpos' is TRUE, don't let the cursor on the NUL after the line.
 *
 * return FAIL for failure, OK otherwise
 */
    int
del_char(fixpos)
    int		fixpos;
{
#ifdef MULTI_BYTE
    if (is_dbcs)
    {
	/* delete two-bytes, when the character is an multi-byte character */
	if (AdjustCursorForMultiByteCharacter())
	    return del_chars(2L, fixpos); /* do BACKSPACE key */
	else
	{
	    char_u *p; /* do DELETE key */

	    p = ml_get_cursor();
	    if (p == NULL || p[0] == NUL)
		return FALSE;
	    if (p[1] != NUL && IsLeadByte(p[0]))
		return del_chars(2L, fixpos);
	    else
		return del_chars(1L, fixpos);
	}
    }
    else
#endif
	return del_chars(1L, fixpos);
}

/*
 * Delete 'count' characters under the cursor.
 * If 'fixpos' is TRUE, don't leave the cursor on the NUL after the line.
 *
 * return FAIL for failure, OK otherwise
 */
    int
del_chars(count, fixpos)
    long	count;
    int		fixpos;
{
    char_u	*oldp, *newp;
    colnr_t	oldlen;
    linenr_t	lnum = curwin->w_cursor.lnum;
    colnr_t	col = curwin->w_cursor.col;
    int		was_alloced;
    long	movelen;

    oldp = ml_get(lnum);
    oldlen = STRLEN(oldp);

    /*
     * Can't do anything when the cursor is on the NUL after the line.
     */
    if (col >= oldlen)
	return FAIL;

    /*
     * When count is too big, reduce it.
     */
    movelen = (long)oldlen - (long)col - count + 1; /* includes trailing NUL */
    if (movelen <= 1)
    {
	/*
	 * If we just took off the last character of a non-blank line, and
	 * fixpos is TRUE, we don't want to end up positioned at the NUL.
	 */
	if (col > 0 && fixpos)
	    --curwin->w_cursor.col;
	count = oldlen - col;
	movelen = 1;
    }

    /*
     * If the old line has been allocated the deletion can be done in the
     * existing line. Otherwise a new line has to be allocated
     */
    was_alloced = ml_line_alloced();	    /* check if oldp was allocated */
    if (was_alloced)
	newp = oldp;			    /* use same allocated memory */
    else
    {					    /* need to allocated a new line */
	newp = alloc((unsigned)(oldlen + 1 - count));
	if (newp == NULL)
	    return FAIL;
	mch_memmove(newp, oldp, (size_t)col);
    }
    mch_memmove(newp + col, oldp + col + count, (size_t)movelen);
    if (!was_alloced)
	ml_replace(lnum, newp, FALSE);

    changed();

    /*
     * When the new character under the cursor is a TAB, the cursor will move
     * on the screen, so we can't use changed_cline_aft_curs() here.
     */
    changed_cline_bef_curs();
    approximate_botline();	/* w_botline might have changed */
    return OK;
}

/*
 * Delete from cursor to end of line.
 *
 * return FAIL for failure, OK otherwise
 */
    int
truncate_line(fixpos)
    int		fixpos;	    /* if TRUE fix the cursor position when done */
{
    char_u	*newp;
    linenr_t	lnum = curwin->w_cursor.lnum;
    colnr_t	col = curwin->w_cursor.col;

    if (col == 0)
	newp = vim_strsave((char_u *)"");
    else
	newp = vim_strnsave(ml_get(lnum), col);

    if (newp == NULL)
	return FAIL;

    ml_replace(lnum, newp, FALSE);

    /*
     * If "fixpos" is TRUE we don't want to end up positioned at the NUL.
     */
    if (fixpos && curwin->w_cursor.col > 0)
	--curwin->w_cursor.col;

    changed();
    changed_cline_bef_curs();
    approximate_botline();	/* w_botline might have changed */
    return OK;
}

    void
del_lines(nlines, dowindow, undo)
    long	nlines;		/* number of lines to delete */
    int		dowindow;	/* if true, update the window */
    int		undo;		/* if true, prepare for undo */
{
    int		num_plines = 0;
    int		offset = 0;

    if (nlines <= 0)
	return;
    /*
     * There's no point in keeping the window updated if redrawing is disabled
     * or we're deleting more than a window's worth of lines.
     */
    if (!redrawing() || !botline_approximated())
	dowindow = FALSE;
    else
    {
	validate_cursor();
	if (nlines > (curwin->w_height - curwin->w_wrow) && dowindow)
	{
	    dowindow = FALSE;
	    /* flaky way to clear rest of window */
	    win_del_lines(curwin, curwin->w_wrow, curwin->w_height, TRUE, TRUE);
	}
    }

    /*
     * Assume that w_botline won't change much.  If it does, there is a small
     * risc of an extra redraw or scroll-up.
     */
    approximate_botline();

    /* save the deleted lines for undo */
    if (undo && u_savedel(curwin->w_cursor.lnum, nlines) == FAIL)
	return;

    /* adjust marks for deleted lines and lines that follow */
    mark_adjust(curwin->w_cursor.lnum, curwin->w_cursor.lnum + nlines - 1,
						  (linenr_t)MAXLNUM, -nlines);

    while (nlines-- > 0)
    {
	if (curbuf->b_ml.ml_flags & ML_EMPTY)	    /* nothing to delete */
	    break;

	/*
	 * Set up to delete the correct number of physical lines on the
	 * window
	 */
	if (dowindow)
	    num_plines += plines(curwin->w_cursor.lnum);

	ml_delete(curwin->w_cursor.lnum, TRUE);

	changed();

	/* If we delete the last line in the file, stop */
	if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
	{
	    curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
	    offset = 1;
	    break;
	}
    }
    curwin->w_cursor.col = 0;
    /*
     * The cursor will stay in the same line number, but the contents will be
     * different, so need to update it's screen posision later.
     */
    changed_cline_bef_curs();

    /*
     * Delete the correct number of physical lines on the window
     */
    if (dowindow && num_plines > 0)
    {
	validate_cline_row();
	win_del_lines(curwin, curwin->w_cline_row + offset, num_plines,
								  TRUE, TRUE);
    }
}

    int
gchar(pos)
    FPOS *pos;
{
    char_u	*ptr = ml_get_pos(pos);

#ifdef MULTI_BYTE
    if (ptr[0] && (is_unicode || (is_dbcs && IsLeadByte(*ptr))))
	return ptr[0] + (ptr[1] << 8);
#endif
    return (int)*ptr;
}

    int
gchar_cursor()
{
    char_u	*ptr = ml_get_cursor();

#ifdef MULTI_BYTE
    if (ptr[0] && (is_unicode || (is_dbcs && IsLeadByte(*ptr))))
	return ptr[0] + (ptr[1] << 8);
#endif
    return (int)*ptr;
}

/*
 * Write a character at the current cursor position.
 * It is directly written into the block.
 */
    void
pchar_cursor(c)
    int c;
{
    *(ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE) +
						    curwin->w_cursor.col) = c;
}

/*
 * Put *pos at end of current buffer
 */
    void
goto_endofbuf(pos)
    FPOS    *pos;
{
    char_u  *p;

    pos->lnum = curbuf->b_ml.ml_line_count;
    pos->col = 0;
    p = ml_get(pos->lnum);
    while (*p++)
	++pos->col;
}

/*
 * When extra == 0: Return TRUE if the cursor is before or on the first
 *		    non-blank in the line.
 * When extra == 1: Return TRUE if the cursor is before the first non-blank in
 *		    the line.
 */
    int
inindent(extra)
    int	    extra;
{
    char_u	*ptr;
    colnr_t	col;

    for (col = 0, ptr = ml_get_curline(); vim_iswhite(*ptr); ++col)
	++ptr;
    if (col >= curwin->w_cursor.col + extra)
	return TRUE;
    else
	return FALSE;
}

/*
 * Skip to next part of an option argument: Skip space and comma.
 */
    char_u *
skip_to_option_part(p)
    char_u  *p;
{
    if (*p == ',')
	++p;
    while (*p == ' ')
	++p;
    return p;
}

    char *
plural(n)
    long n;
{
    static char buf[2] = "s";

    if (n == 1)
	return &(buf[1]);
    return &(buf[0]);
}

/*
 * changed() is called when something in the current buffer is changed
 */
    void
changed()
{
    int	    save_msg_scroll = msg_scroll;

    if (!curbuf->b_changed)
    {
	change_warning(0);
	if (curbuf->b_may_swap)	    /* still need to create a swap file */
	{
	    ml_open_file(curbuf);

	    /* The ml_open_file() can cause an ATTENTION message.
	     * Wait two seconds, to make sure the user reads this unexpected
	     * message.  Since we could be anywhere, call wait_return() now,
	     * and don't let the emsg() set msg_scroll. */
	    if (need_wait_return)
	    {
		out_flush();
		ui_delay(2000L, TRUE);
		wait_return(TRUE);
		msg_scroll = save_msg_scroll;
	    }
	}
	curbuf->b_changed = TRUE;
	check_status(curbuf);
    }
    modified = TRUE;		    /* used for redrawing */
    tag_modified = TRUE;	    /* used for tag searching check */
}

/*
 * unchanged() is called when the changed flag must be reset for buffer 'buf'
 */
    void
unchanged(buf, ff)
    BUF	    *buf;
    int	    ff;	    /* also reset 'fileformat' */
{
    if (buf->b_changed || (ff && buf->b_start_ffc != *buf->b_p_ff))
    {
	buf->b_changed = 0;
	if (ff)
	    buf->b_start_ffc = *buf->b_p_ff;	/* keep this fileformat */
	check_status(buf);
    }
}

/*
 * check_status: called when the status bars for the buffer 'buf'
 *		 need to be updated
 */
    void
check_status(buf)
    BUF	    *buf;
{
    WIN	    *wp;
    int	    i;

    i = 0;
    for (wp = firstwin; wp != NULL; wp = wp->w_next)
	if (wp->w_buffer == buf && wp->w_status_height)
	{
	    wp->w_redr_status = TRUE;
	    ++i;
	}
    if (i)
	redraw_later(NOT_VALID);
}

/*
 * If the file is readonly, give a warning message with the first change.
 * Don't do this for autocommands.
 * Don't use emsg(), because it flushes the macro buffer.
 * If we have undone all changes b_changed will be FALSE, but b_did_warn
 * will be TRUE.
 */
    void
change_warning(col)
    int	    col;		/* column for message; non-zero when in insert
				   mode and 'showmode' is on */
{
    if (curbuf->b_did_warn == FALSE
	    && curbuf_changed() == 0
	    && !p_im
#ifdef AUTOCMD
	    && !autocmd_busy
#endif
	    && curbuf->b_p_ro)
    {
	/*
	 * Do what msg() does, but with a column offset if the warning should
	 * be after the mode message.
	 */
	msg_start();
	if (msg_row == Rows - 1)
	    msg_col = col;
	MSG_PUTS_ATTR("Warning: Changing a readonly file", hl_attr(HLF_W));
	msg_clr_eos();
	(void)msg_end();
	ui_delay(1000L, TRUE);	/* give him some time to think about it */
	curbuf->b_did_warn = TRUE;
	redraw_cmdline = FALSE;	/* don't redraw and erase the message */
	if (msg_row < Rows - 1)
	    showmode();
    }
}

/*
 * Ask for a reply from the user, a 'y' or a 'n'.
 * No other characters are accepted, the message is repeated until a valid
 * reply is entered or CTRL-C is hit.
 * If direct is TRUE, don't use vgetc() but ui_inchar(), don't get characters
 * from any buffers but directly from the user.
 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -