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

📄 getchar.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:

/*
 * copy the rest of the redo buffer into the stuff buffer (could be done faster)
 * if old_redo is TRUE, use old_redobuff instead of redobuff
 */
    static void
copy_redo(old_redo)
    int	    old_redo;
{
    int	    c;

    while ((c = read_redo(FALSE, old_redo)) != NUL)
	stuffcharReadbuff(c);
}

/*
 * Stuff the redo buffer into the stuffbuff.
 * Insert the redo count into the command.
 * If 'old_redo' is TRUE, the last but one command is repeated
 * instead of the last command (inserting text). This is used for
 * CTRL-O <.> in insert mode
 *
 * return FAIL for failure, OK otherwise
 */
    int
start_redo(count, old_redo)
    long    count;
    int	    old_redo;
{
    int	    c;

    /* init the pointers; return if nothing to redo */
    if (read_redo(TRUE, old_redo) == FAIL)
	return FAIL;

    c = read_redo(FALSE, old_redo);

    /* copy the buffer name, if present */
    if (c == '"')
    {
	add_buff(&stuffbuff, (char_u *)"\"");
	c = read_redo(FALSE, old_redo);

	/* if a numbered buffer is used, increment the number */
	if (c >= '1' && c < '9')
	    ++c;
	add_char_buff(&stuffbuff, c);
	c = read_redo(FALSE, old_redo);
    }

    if (c == 'v')   /* redo Visual */
    {
	VIsual = curwin->w_cursor;
	VIsual_active = TRUE;
	VIsual_reselect = TRUE;
	redo_VIsual_busy = TRUE;
	c = read_redo(FALSE, old_redo);
    }

    /* try to enter the count (in place of a previous count) */
    if (count)
    {
	while (isdigit(c))	/* skip "old" count */
	    c = read_redo(FALSE, old_redo);
	add_num_buff(&stuffbuff, count);
    }

    /* copy from the redo buffer into the stuff buffer */
    add_char_buff(&stuffbuff, c);
    copy_redo(old_redo);
    return OK;
}

/*
 * Repeat the last insert (R, o, O, a, A, i or I command) by stuffing
 * the redo buffer into the stuffbuff.
 * return FAIL for failure, OK otherwise
 */
    int
start_redo_ins()
{
    int	    c;

    if (read_redo(TRUE, FALSE) == FAIL)
	return FAIL;
    start_stuff();

/* skip the count and the command character */
    while ((c = read_redo(FALSE, FALSE)) != NUL)
    {
	if (vim_strchr((char_u *)"AaIiRrOo", c) != NULL)
	{
	    if (c == 'O' || c == 'o')
		stuffReadbuff(NL_STR);
	    break;
	}
    }

/* copy the typed text from the redo buffer into the stuff buffer */
    copy_redo(FALSE);
    block_redo = TRUE;
    return OK;
}

    void
set_redo_ins()
{
    block_redo = TRUE;
}

    void
stop_redo_ins()
{
    block_redo = FALSE;
}

/*
 * Initialize typebuf to point to typebuf_init.
 * Alloc() cannot be used here: In out-of-memory situations it would
 * be impossible to type anything.
 */
    static void
init_typebuf()
{
    if (typebuf == NULL)
    {
	typebuf = typebuf_init;
	noremapbuf = noremapbuf_init;
	typebuflen = TYPELEN_INIT;
	typelen = 0;
	typeoff = 0;
    }
}

/*
 * insert a string in position 'offset' in the typeahead buffer (for "@r"
 * and ":normal" command, vgetorpeek() and check_termcode())
 *
 * If noremap is 0, new string can be mapped again.
 * If noremap is -1, new string cannot be mapped again.
 * If noremap is >0, that many characters of the new string cannot be mapped.
 *
 * If nottyped is TRUE, the string does not return KeyTyped (don't use when
 * offset is non-zero!).
 *
 * return FAIL for failure, OK otherwise
 */
    int
ins_typebuf(str, noremap, offset, nottyped)
    char_u  *str;
    int	    noremap;
    int	    offset;
    int	    nottyped;
{
    char_u  *s1, *s2;
    int	    newlen;
    int	    addlen;
    int	    i;
    int	    newoff;

    init_typebuf();

    addlen = STRLEN(str);
    /*
     * Easy case: there is room in front of typebuf[typeoff]
     */
    if (offset == 0 && addlen <= typeoff)
    {
	typeoff -= addlen;
	mch_memmove(typebuf + typeoff, str, (size_t)addlen);
    }
    /*
     * Need to allocate new buffer.
     * In typebuf there must always be room for 3 * MAXMAPLEN + 4 characters.
     * We add some extra room to avoid having to allocate too often.
     */
    else
    {
	newoff = MAXMAPLEN + 4;
	newlen = typelen + addlen + newoff + 4 * (MAXMAPLEN + 4);
	if (newlen < 0)		    /* string is getting too long */
	{
	    emsg(e_toocompl);	    /* also calls flush_buffers */
	    setcursor();
	    return FAIL;
	}
	s1 = alloc(newlen);
	if (s1 == NULL)		    /* out of memory */
	    return FAIL;
	s2 = alloc(newlen);
	if (s2 == NULL)		    /* out of memory */
	{
	    vim_free(s1);
	    return FAIL;
	}
	typebuflen = newlen;

	/* copy the old chars, before the insertion point */
	mch_memmove(s1 + newoff, typebuf + typeoff, (size_t)offset);
	/* copy the new chars */
	mch_memmove(s1 + newoff + offset, str, (size_t)addlen);
	/* copy the old chars, after the insertion point, including the	NUL at
	 * the end */
	mch_memmove(s1 + newoff + offset + addlen, typebuf + typeoff + offset,
					      (size_t)(typelen - offset + 1));
	if (typebuf != typebuf_init)
	    vim_free(typebuf);
	typebuf = s1;

	mch_memmove(s2 + newoff, noremapbuf + typeoff, (size_t)offset);
	mch_memmove(s2 + newoff + offset + addlen,
		   noremapbuf + typeoff + offset, (size_t)(typelen - offset));
	if (noremapbuf != noremapbuf_init)
	    vim_free(noremapbuf);
	noremapbuf = s2;

	typeoff = newoff;
    }
    typelen += addlen;

    /*
     * Adjust noremapbuf[] for the new characters:
     * If noremap  < 0: all the new characters are flagged not remappable
     * If noremap == 0: all the new characters are flagged mappable
     * If noremap  > 0: 'noremap' characters are flagged not remappable, the
     *			rest mappable
     */
    if (noremap < 0)	    /* length not specified */
	noremap = addlen;
    for (i = 0; i < addlen; ++i)
	noremapbuf[typeoff + i + offset] = (noremap-- > 0);

		    /* this is only correct for offset == 0! */
    if (nottyped)			/* the inserted string is not typed */
	typemaplen += addlen;
    if (no_abbr_cnt && offset == 0)	/* and not used for abbreviations */
	no_abbr_cnt += addlen;

    return OK;
}

/*
 * Return TRUE if there are no characters in the typeahead buffer that have
 * not been typed (result from a mapping or come from ":normal").
 */
    int
typebuf_typed()
{
    return typemaplen == 0;
}

/*
 * Return the number of characters that are mapped (or not typed).
 */
    int
typebuf_maplen()
{
    return typemaplen;
}

/*
 * remove "len" characters from typebuf[typeoff + offset]
 */
    void
del_typebuf(len, offset)
    int	len;
    int	offset;
{
    int	    i;

    typelen -= len;
    /*
     * Easy case: Just increase typeoff.
     */
    if (offset == 0 && typebuflen - (typeoff + len) >= 3 * MAXMAPLEN + 3)
	typeoff += len;
    /*
     * Have to move the characters in typebuf[] and noremapbuf[]
     */
    else
    {
	i = typeoff + offset;
	/*
	 * Leave some extra room at the end to avoid reallocation.
	 */
	if (typeoff > MAXMAPLEN)
	{
	    mch_memmove(typebuf + MAXMAPLEN, typebuf + typeoff, (size_t)offset);
	    mch_memmove(noremapbuf + MAXMAPLEN, noremapbuf + typeoff,
							      (size_t)offset);
	    typeoff = MAXMAPLEN;
	}
	/* adjust typebuf (include the NUL at the end) */
	mch_memmove(typebuf + typeoff + offset, typebuf + i + len,
					      (size_t)(typelen - offset + 1));
	/* adjust noremapbuf[] */
	mch_memmove(noremapbuf + typeoff + offset, noremapbuf + i + len,
						  (size_t)(typelen - offset));
    }

    if (typemaplen > offset)		/* adjust typemaplen */
    {
	if (typemaplen < offset + len)
	    typemaplen = offset;
	else
	    typemaplen -= len;
    }
    if (no_abbr_cnt > offset)		/* adjust no_abbr_cnt */
    {
	if (no_abbr_cnt < offset + len)
	    no_abbr_cnt = offset;
	else
	    no_abbr_cnt -= len;
    }
}

/*
 * Write typed characters to script file.
 * If recording is on put the character in the recordbuffer.
 */
    static void
gotchars(s, len)
    char_u  *s;
    int	    len;
{
    int	    c;
    char_u  buf[2];

    /* remember how many chars were last recorded */
    if (Recording)
	last_recorded_len += len;

    buf[1] = NUL;
    while (len--)
    {
	c = *s++;
	updatescript(c);

	if (Recording)
	{
	    buf[0] = c;
	    add_buff(&recordbuff, buf);
	}
    }
    may_sync_undo();
}

/*
 * Sync undo.  Called when typed characters are obtained from the typeahead
 * buffer, or when a menu is used.
 * Do not sync:
 * - In Insert mode, unless cursor key has been used.
 * - While reading a script file.
 * - When no_u_sync is non-zero.
 */
    static void
may_sync_undo()
{
    if ((!(State & (INSERT + CMDLINE)) || arrow_used) &&
				    scriptin[curscript] == NULL && !no_u_sync)
	u_sync();
}

/*
 * When doing ":so! file", the current typeahead needs to be saved, and
 * restored when "file" has been read completely.
 */
static char_u	*(sv_typebuf[NSCRIPT]);
static char_u	*(sv_noremapbuf[NSCRIPT]);
static int	sv_typebuflen[NSCRIPT];
static int	sv_typeoff[NSCRIPT];
static int	sv_typelen[NSCRIPT];
static int	sv_typemaplen[NSCRIPT];
static int	sv_no_abbr_cnt[NSCRIPT];

    int
save_typebuf()
{
    init_typebuf();
    sv_typebuf[curscript] = typebuf;
    sv_noremapbuf[curscript] = noremapbuf;
    sv_typebuflen[curscript] = typebuflen;
    sv_typeoff[curscript] = typeoff;
    sv_typelen[curscript] = typelen;
    sv_typemaplen[curscript] = typemaplen;
    sv_no_abbr_cnt[curscript] = no_abbr_cnt;
    typebuf = alloc(TYPELEN_INIT);
    noremapbuf = alloc(TYPELEN_INIT);
    typebuflen = TYPELEN_INIT;
    typeoff = 0;
    typelen = 0;
    typemaplen = 0;
    no_abbr_cnt = 0;

    /* If out of memory: restore typebuf and close file. */
    if (typebuf == NULL || noremapbuf == NULL)
    {
	closescript();
	return FAIL;
    }

    return OK;
}

/*
 * open new script file for ":so!" command
 * return OK on success, FAIL on error
 */
    int
openscript(name)
    char_u *name;
{
    int oldcurscript;

    if (curscript + 1 == NSCRIPT)
    {
	emsg(e_nesting);
	return FAIL;
    }

    if (scriptin[curscript] != NULL)    /* already reading script */
	++curscript;
				/* use NameBuff for expanded name */
    expand_env(name, NameBuff, MAXPATHL);
    if ((scriptin[curscript] = fopen((char *)NameBuff, READBIN)) == NULL)
    {
	emsg2(e_notopen, name);
	if (curscript)
	    --curscript;
	return FAIL;
    }
    if (save_typebuf() == FAIL)
	return FAIL;

    /*
     * With command ":g/pat/so! file" we have to execute the
     * commands from the file now.
     */
    if (global_busy)
    {
	OPARG	oa;

	clear_oparg(&oa);
	State = NORMAL;
	oldcurscript = curscript;
	do
	{
	    adjust_cursor();    /* put cursor on an existing line */
	    normal_cmd(&oa, FALSE);
	    vpeekc();	    /* check for end of file */
	}
	while (scriptin[oldcurscript] != NULL);
	State = CMDLINE;
    }

    return OK;
}

/*
 * Close the currently active input script.
 */
    static void
closescript()
{
    vim_free(typebuf);
    vim_free(noremapbuf);
    typebuf = sv_typebuf[curscript];
    noremapbuf = sv_noremapbuf[curscript];
    typebuflen = sv_typebuflen[curscript];
    typelen = sv_typelen[curscript];
    typeoff = sv_typeoff[curscript];
    typemaplen = sv_typemaplen[curscript];
    no_abbr_cnt = sv_no_abbr_cnt[curscript];

    fclose(scriptin[curscript]);
    scriptin[curscript] = NULL;
    if (curscript)
	--curscript;
}

/*
 * updatescipt() is called when a character can be written into the script file
 * or when we have waited some time for a character (c == 0)
 *
 * All the changed memfiles are synced if c == 0 or when the number of typed
 * characters reaches 'updatecount' and 'updatecount' is non-zero.
 */
    void
updatescript(c)
    int c;
{
    static int	    count = 0;

    if (c && scriptout)
	putc(c, scriptout);
    if (c == 0 || (p_uc > 0 && ++count >= p_uc))
    {
	ml_sync_all(c == 0, TRUE);
	count = 0;
    }
}

#define K_NEEDMORET -1		/* keylen value for incomplete key-code */
#define M_NEEDMORET -2		/* keylen value for incomplete mapping */

static int old_char = -1;	/* ungotten character */

    int
vgetc()
{
    int	    c, c2;

    mod_mask = 0x0;
    last_recorded_len = 0;
    for (;;)			/* this is done twice if there are modifiers */
    {
	if (mod_mask)		/* no mapping after modifier has been read */
	{
	    ++no_mapping;
	    ++allow_keys;
	}
	c = vgetorpeek(TRUE);
	if (mod_mask)
	{
	    --no_mapping;
	    --allow_keys;
	}

	/* Get two extra bytes for special keys */
	if (c == K_SPECIAL)
	{
	    ++no_mapping;

⌨️ 快捷键说明

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