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

📄 getchar.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
				 * character -- webb
				 */
				col = vcol = curwin->w_wcol = 0;
				ptr = ml_get_curline();
				while (col < curwin->w_cursor.col)
				{
				    if (!vim_iswhite(ptr[col]))
					curwin->w_wcol = vcol;
				    vcol += lbr_chartabsize(ptr + col,
							       (colnr_t)vcol);
				    ++col;
				}
				if (curwin->w_p_nu)
				    curwin->w_wcol += 8;
			    }
			    else
				--curwin->w_wcol;
			}
			else if (curwin->w_p_wrap && curwin->w_wrow)
			{
				--curwin->w_wrow;
				curwin->w_wcol = Columns - 1;
			}
		    }
		    setcursor();
		    out_flush();
#ifdef SHOWCMD
		    new_wcol = curwin->w_wcol;
		    new_wrow = curwin->w_wrow;
#endif
		    curwin->w_wcol = old_wcol;
		    curwin->w_wrow = old_wrow;
		}
		if (c < 0)
		    continue;	/* end of input script reached */
		typelen += c;

		/* buffer full, don't map */
		if (typelen >= typemaplen + MAXMAPLEN)
		{
		    timedout = TRUE;
		    continue;
		}
/*
 * get a character: 4. from the user
 */
#ifdef SHOWCMD
		/*
		 * If we have a partial match (and are going to wait for more
		 * input from the user), show the partially matched characters
		 * to the user with showcmd -- webb.
		 */
		i = 0;
		if (typelen > 0 && (State & (NORMAL | INSERT)) &&
						    advance && !exmode_active)
		{
		    /* need to use the col and row from above here */
		    old_wcol = curwin->w_wcol;
		    old_wrow = curwin->w_wrow;
		    curwin->w_wcol = new_wcol;
		    curwin->w_wrow = new_wrow;
		    push_showcmd();
		    if (typelen > SHOWCMD_COLS)
			i = typelen - SHOWCMD_COLS;
		    while (i < typelen)
			(void)add_to_showcmd(typebuf[typeoff + i++]);
		    curwin->w_wcol = old_wcol;
		    curwin->w_wrow = old_wrow;
		}
#endif

		c = inchar(typebuf + typeoff + typelen,
			typebuflen - typeoff - typelen - 1,
			!advance
			    ? 0
			    : ((typelen == 0 || !(p_timeout || (p_ttimeout &&
					keylen == K_NEEDMORET)))
				    ? -1L
				    : ((keylen == K_NEEDMORET && p_ttm >= 0)
					    ? p_ttm
					    : p_tm)));

#ifdef SHOWCMD
		if (i)
		    pop_showcmd();
#endif

		if (c < 0)
		    continue;		/* end of input script reached */
		if (c == NUL)		/* no character available */
		{
		    if (!advance)
			break;
		    if (typelen)		/* timed out */
		    {
			timedout = TRUE;
			continue;
		    }
		}
		else
		{	    /* allow mapping for just typed characters */
		    while (typebuf[typeoff + typelen] != NUL)
			noremapbuf[typeoff + typelen++] = FALSE;
		}
	    }	    /* for (;;) */
	}	/* if (!character from stuffbuf) */

			/* if advance is FALSE don't loop on NULs */
    } while (c < 0 || (advance && c == NUL));

    /*
     * The "INSERT" message is taken care of here:
     *	 if we return an ESC to exit insert mode, the message is deleted
     *	 if we don't return an ESC but deleted the message before, redisplay it
     */
    if (advance && p_smd && (State & INSERT))
    {
	if (c == ESC && !mode_deleted && !no_mapping)
	{
	    if (typelen && !KeyTyped)
		redraw_cmdline = TRUE;	    /* delete mode later */
	    else
		unshowmode(FALSE);
	}
	else if (c != ESC && mode_deleted)
	{
	    if (typelen && !KeyTyped)
		redraw_cmdline = TRUE;	    /* show mode later */
	    else
		showmode();
	}
    }
#ifdef USE_GUI
    /* may unshow different cursor shape */
    if (gui.in_use && shape_changed)
	gui_update_cursor(TRUE, FALSE);
#endif

    vgetc_busy = FALSE;

    return c;
}

/*
 * inchar() - get one character from
 *	1. a scriptfile
 *	2. the keyboard
 *
 *  As much characters as we can get (upto 'maxlen') are put in buf and
 *  NUL terminated (buffer length must be 'maxlen' + 1).
 *  Minimum for 'maxlen' is 3!!!!
 *
 *  If we got an interrupt all input is read until none is available.
 *
 *  If wait_time == 0  there is no waiting for the char.
 *  If wait_time == n  we wait for n msec for a character to arrive.
 *  If wait_time == -1 we wait forever for a character to arrive.
 *
 *  Return the number of obtained characters.
 *  Return -1 when end of input script reached.
 */

    int
inchar(buf, maxlen, wait_time)
    char_u  *buf;
    int	    maxlen;
    long    wait_time;		    /* milli seconds */
{
    int		len = 0;	    /* init for GCC */
    int		retesc = FALSE;	    /* return ESC with gotint */
    int		c;
    int		i;

    if (wait_time == -1L || wait_time > 100L)  /* flush output before waiting */
    {
	cursor_on();
	out_flush();
    }

    /*
     * Don't reset these when at the hit-return prompt, otherwise a endless
     * recursive loop may result (write error in swapfile, hit-return, timeout
     * on char wait, flush swapfile, write error....).
     */
    if (State != HITRETURN)
    {
	did_outofmem_msg = FALSE;   /* display out of memory message (again) */
	did_swapwrite_msg = FALSE;  /* display swap file write error again */
    }
    undo_off = FALSE;		    /* restart undo now */

    /*
     * first try script file
     *	If interrupted: Stop reading script files.
     */
    c = -1;
    while (scriptin[curscript] != NULL && c < 0)
    {
	if (got_int || (c = getc(scriptin[curscript])) < 0) /* reached EOF */
	{
	    closescript();
	    /*
	     * When reading script file is interrupted, return an ESC to get
	     * back to normal mode.
	     * Otherwise return -1, because typebuf[] has changed.
	     */
	    if (got_int)
		retesc = TRUE;
	    else
		return -1;
	}
	else
	{
	    buf[0] = c;
	    len = 1;
	}
    }

    if (c < 0)		/* did not get a character from script */
    {
	/*
	 * If we got an interrupt, skip all previously typed characters and
	 * return TRUE if quit reading script file.
	 */
	if (got_int)
	{
	    while (ui_inchar(buf, maxlen, 0L))
		;
	    return retesc;
	}

	/*
	 * Always flush the output characters when getting input characters
	 * from the user.
	 */
	out_flush();

	/*
	 * fill up to a third of the buffer, because each character may be
	 * tripled below
	 */
	len = ui_inchar(buf, maxlen / 3, wait_time);
    }

    /*
     * Two characters are special: NUL and K_SPECIAL.
     * Replace	     NUL by K_SPECIAL KS_ZERO	 K_FILLER
     * Replace K_SPECIAL by K_SPECIAL KS_SPECIAL K_FILLER
     * Don't replace K_SPECIAL when reading a script file.
     */
    for (i = len; --i >= 0; ++buf)
    {
#ifdef USE_GUI
	/* Any character can come after a CSI, don't escape it. */
	if (buf[0] == CSI && i >= 2)
	{
	    buf += 2;
	    i   -= 2;
	    continue;
	}
#endif
	if (buf[0] == NUL || (buf[0] == K_SPECIAL && c < 0))
	{
	    mch_memmove(buf + 3, buf + 1, (size_t)i);
	    buf[2] = K_THIRD(buf[0]);
	    buf[1] = K_SECOND(buf[0]);
	    buf[0] = K_SPECIAL;
	    buf += 2;
	    len += 2;
	}
    }
    *buf = NUL;				    /* add trailing NUL */
    return len;
}

/*
 * map[!]		    : show all key mappings
 * map[!] {lhs}		    : show key mapping for {lhs}
 * map[!] {lhs} {rhs}	    : set key mapping for {lhs} to {rhs}
 * noremap[!] {lhs} {rhs}   : same, but no remapping for {rhs}
 * unmap[!] {lhs}	    : remove key mapping for {lhs}
 * abbr			    : show all abbreviations
 * abbr {lhs}		    : show abbreviations for {lhs}
 * abbr {lhs} {rhs}	    : set abbreviation for {lhs} to {rhs}
 * noreabbr {lhs} {rhs}	    : same, but no remapping for {rhs}
 * unabbr {lhs}		    : remove abbreviation for {lhs}
 *
 * maptype == 1 for unmap command, 2 for noremap command.
 *
 * keys is pointer to any arguments. Note: keys cannot be a read-only string,
 * it will be modified.
 *
 * for :map   mode is NORMAL + VISUAL + OP_PENDING
 * for :map!  mode is INSERT + CMDLINE
 * for :cmap  mode is CMDLINE
 * for :imap  mode is INSERT
 * for :nmap  mode is NORMAL
 * for :vmap  mode is VISUAL
 * for :omap  mode is OP_PENDING
 *
 * for :abbr  mode is INSERT + CMDLINE
 * for :iabbr mode is INSERT
 * for :cabbr mode is CMDLINE
 *
 * Return 0 for success
 *	  1 for invalid arguments
 *	  2 for no match
 *	  3 for ambiguety
 *	  4 for out of mem
 */
    int
do_map(maptype, keys, mode, abbrev)
    int	    maptype;
    char_u  *keys;
    int	    mode;
    int	    abbrev;		/* not a mapping but an abbreviation */
{
    struct mapblock	*mp, **mpp;
    char_u		*arg;
    char_u		*p;
    int			n;
    int			len = 0;	/* init for GCC */
    char_u		*newstr;
    int			hasarg;
    int			haskey;
    int			did_it = FALSE;
    int			round;
    char_u		*keys_buf = NULL;
    char_u		*arg_buf = NULL;
    int			retval = 0;
    int			do_backslash;
    int			hash;
    int			new_hash;

    validate_maphash();
/*
 * find end of keys and skip CTRL-Vs (and backslashes) in it
 * Accept backslash like CTRL-V when 'cpoptions' does not contain 'B'.
 * with :unmap white space is included in the keys, no argument possible
 */
    p = keys;
    do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
    while (*p && (maptype == 1 || !vim_iswhite(*p)))
    {
	if ((p[0] == Ctrl('V') || (do_backslash && p[0] == '\\')) &&
								  p[1] != NUL)
	    ++p;		/* skip CTRL-V or backslash */
	++p;
    }
    if (*p != NUL)
	*p++ = NUL;
    p = skipwhite(p);
    arg = p;
    hasarg = (*arg != NUL);
    haskey = (*keys != NUL);

	/* check for :unmap without argument */
    if (maptype == 1 && !haskey)
    {
	retval = 1;
	goto theend;
    }

    /*
     * If mapping has been given as ^V<C_UP> say, then replace the term codes
     * with the appropriate two bytes. If it is a shifted special key, unshift
     * it too, giving another two bytes.
     * replace_termcodes() may move the result to allocated memory, which
     * needs to be freed later (*keys_buf and *arg_buf).
     * replace_termcodes() also removes CTRL-Vs and sometimes backslashes.
     */
    if (haskey)
	keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE);
    if (hasarg)
    {
	if (STRICMP(arg, "<nop>") == 0)	    /* "<Nop>" means nothing */
	    arg = (char_u *)"";
	else
	    arg = replace_termcodes(arg, &arg_buf, FALSE, TRUE);
    }

#ifdef FKMAP
    /*
     * when in right-to-left mode and alternate keymap option set,
     * reverse the character flow in the arg in Farsi.
     */
    if (p_altkeymap && curwin->w_p_rl)
	lrswap(arg);
#endif

    /*
     * check arguments and translate function keys
     */
    if (haskey)
    {
	len = STRLEN(keys);
	if (len > MAXMAPLEN)		/* maximum length of MAXMAPLEN chars */
	{
	    retval = 1;
	    goto theend;
	}

	if (abbrev && maptype != 1)
	{
	    /*
	     * If an abbreviation ends in a keyword character, the
	     * rest must be all keyword-char or all non-keyword-char.
	     * Otherwise we won't be able to find the start of it in a
	     * vi-compatible way.
	     * An abbrevation cannot contain white space.
	     */
	    if (vim_iswordc(keys[len - 1]))	/* ends in keyword char */
		for (n = 0; n < len - 2; ++n)
		    if (vim_iswordc(keys[n]) != vim_iswordc(keys[len - 2]))
		    {
			retval = 1;
			goto theend;
		    }
	    for (n = 0; n < len; ++n)
		if (vim_iswhite(keys[n]))
		{
		    retval = 1;
		    goto theend;
		}
	}
    }

    if (haskey && hasarg && abbrev)	/* if we will add an abbreviation */
	no_abbr = FALSE;		/* reset flag that indicates there are
							    no abbreviations */

    if (!haskey || (maptype != 1 && !hasarg))
	msg_start();

    /*
     * Find an entry in the maphash[] list that matches.
     * For :unmap we may loop two times: once to try to unmap an entry with a
     * matching 'from' part, a second time, if the first fails, to unmap an
     * entry with a matching 'to' part. This was done to allow ":ab foo bar"
     * to be unmapped by typing ":unab foo", where "foo" will be replaced by
     * "bar" because of the abbreviation.
     */
    for (round = 0; (round == 0 || maptype == 1) && round <= 1 &&
						 !did_it && !got_int; ++round)
    {
	/* need to loop over all hash lists */
	for (hash = 0; hash < 256 && !got_int; ++hash)
	{
	    if (abbrev)
	    {
		if (hash)	/* there is only one abbreviation list */
		    break;
		mpp = &first_abbr;
	    }
	    else
		mpp = &(maphash[hash]);
	    for (mp = *mpp; mp != NULL && !got_int; mp = *mpp)
	    {

		if (!(mp->m_mode & mode))   /* skip entries with wrong mode */
		{
		    mpp = &(mp->m_next);
		    continue;
		}
		if (!haskey)		    /* show all entries */
		{
		    showmap(mp);
		    did_it = TRUE;
		}
		else			    /* do we have a match? */
		{
		    if (round)	    /* second round: Try unmap "rhs" string */
		    {
			n = STRLEN(mp->m_str);
			p = mp->m_str;
		    }
		    else
		    {
			n = mp->m_keylen;
			p = mp->m_keys;
		    }
		    if (!STRNCMP(p, keys, (size_t)(n < len ? n : len)))
		    {
			if (maptype == 1)	/* delete entry */
			{
			    if (n != len)	/* not a full match */
			    {
				mpp = &(mp->m_next);
				continue;
			    }
			    /*
			     * We reset the indicated mode bits. If nothing is
			     * left the entry is deleted below.
			     */
			    mp->m_mode &= ~mode;
			    did_it = TRUE;	/* remember we did something */
			}
			else if (!hasarg)	/* show matching entry */
			{
			    showmap(mp);
			    did_it = TRUE;
			}
			else if (n != len)	/* new entry is ambigious */
			{
			    if (abbrev)		/* for abbrev's that's ok */
			    {
				mpp = &(mp->m_next);
				continue;
			    }
			    retval = 3;
			    goto theend;
			}
			else			/* new rhs for existing entry */
			{
			    mp->m_mode &= ~mode;	/* remove mode bits */
			    if (mp->m_mode == 0 && !did_it) /* reuse entry */
			    {
				newstr = vim_strsave(arg);
				if (newstr == NULL)
				{
				    retval = 4;		/* no mem */
				    goto theend;
				}
				vim_free(mp->m_str);
				mp->m_str = newstr;
				mp->m_noremap = maptype;
				mp->m_mode = mode;
				did_it = TRUE;
			    }
			}
			if (mp->m_mode == 0)	/* entry can be deleted */
			{

⌨️ 快捷键说明

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