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

📄 getchar.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 5 页
字号:
			    map_free(mpp);
			    continue;		/* continue with *mpp */
			}

			/*
			 * May need to put this entry into another hash list.
			 */
			new_hash = MAP_HASH(mp->m_mode, mp->m_keys[0]);
			if (!abbrev && new_hash != hash)
			{
			    *mpp = mp->m_next;
			    mp->m_next = maphash[new_hash];
			    maphash[new_hash] = mp;

			    continue;		/* continue with *mpp */
			}
		    }
		}
		mpp = &(mp->m_next);
	    }
	}
    }

    if (maptype == 1)			    /* delete entry */
    {
	if (!did_it)
	    retval = 2;			    /* no match */
	goto theend;
    }

    if (!haskey || !hasarg)		    /* print entries */
    {
	if (!did_it)
	{
	    if (abbrev)
		MSG("No abbreviation found");
	    else
		MSG("No mapping found");
	}
	goto theend;			    /* listing finished */
    }

    if (did_it)			/* have added the new entry already */
	goto theend;
/*
 * Get here when we have to add a new entry to the maphash[] list or abbrlist.
 */
    mp = (struct mapblock *)alloc((unsigned)sizeof(struct mapblock));
    if (mp == NULL)
    {
	retval = 4;	    /* no mem */
	goto theend;
    }

#ifdef USE_GUI_WIN32
    /* If CTRL-C has been mapped, don't use it for Interrupting */
    if (*keys == Ctrl('C'))
	mapped_ctrl_c = TRUE;
#endif
    mp->m_keys = vim_strsave(keys);
    mp->m_str = vim_strsave(arg);
    if (mp->m_keys == NULL || mp->m_str == NULL)
    {
	vim_free(mp->m_keys);
	vim_free(mp->m_str);
	vim_free(mp);
	retval = 4;	/* no mem */
	goto theend;
    }
    mp->m_keylen = STRLEN(mp->m_keys);
    mp->m_noremap = maptype;
    mp->m_mode = mode;

    /* add the new entry in front of the abbrlist or maphash[] list */
    if (abbrev)
    {
	mp->m_next = first_abbr;
	first_abbr = mp;
    }
    else
    {
	n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
	mp->m_next = maphash[n];
	maphash[n] = mp;
    }

theend:
    vim_free(keys_buf);
    vim_free(arg_buf);
    return retval;
}

/*
 * Delete one entry from the abbrlist or maphash[].
 * "mpp" is a pointer to the m_next field of the PREVIOUS entry!
 */
    static void
map_free(mpp)
    struct mapblock	**mpp;
{
    struct mapblock	*mp;

    mp = *mpp;
    vim_free(mp->m_keys);
    vim_free(mp->m_str);
    *mpp = mp->m_next;
    vim_free(mp);
}

/*
 * Initialize maphash[] for first use.
 */
    static void
validate_maphash()
{
    if (!maphash_valid)
    {
	vim_memset(maphash, 0, sizeof(maphash));
	maphash_valid = TRUE;
    }
}

/*
 * Get the mapping mode from the command name.
 */
    int
get_map_mode(cmdp, forceit)
    char_u	**cmdp;
    int		forceit;
{
    char_u	*p;
    int		modec;
    int		mode;

    p = *cmdp;
    modec = *p++;
    if (modec == 'i')
	mode = INSERT;				/* :imap */
    else if (modec == 'c')
	mode = CMDLINE;				/* :cmap */
    else if (modec == 'n' && *p != 'o')		    /* avoid :noremap */
	mode = NORMAL;				/* :nmap */
    else if (modec == 'v')
	mode = VISUAL;				/* :vmap */
    else if (modec == 'o')
	mode = OP_PENDING;			/* :omap */
    else
    {
	--p;
	if (forceit)
	    mode = INSERT + CMDLINE;		/* :map ! */
	else
	    mode = VISUAL + NORMAL + OP_PENDING;/* :map */
    }

    *cmdp = p;
    return mode;
}

/*
 * Clear all mappings or abbreviations.
 * 'abbr' should be FALSE for mappings, TRUE for abbreviations.
 */
    void
map_clear(cmdp, forceit, abbr)
    char_u  *cmdp;
    int	    forceit;
    int	    abbr;
{
    struct mapblock	*mp, **mpp;
    int	    mode;
    int	    hash;
    int	    new_hash;

    validate_maphash();

    mode = get_map_mode(&cmdp, forceit);

    for (hash = 0; hash < 256; ++hash)
    {
	if (abbr)
	{
	    if (hash)	    /* there is only one abbrlist */
		break;
	    mpp = &first_abbr;
	}
	else
	    mpp = &maphash[hash];
	while (*mpp != NULL)
	{
	    mp = *mpp;
	    if (mp->m_mode & mode)
	    {
		mp->m_mode &= ~mode;
		if (mp->m_mode == 0) /* entry can be deleted */
		{
		    map_free(mpp);
		    continue;
		}
		/*
		 * May need to put this entry into another hash list.
		 */
		new_hash = MAP_HASH(mp->m_mode, mp->m_keys[0]);
		if (!abbr && new_hash != hash)
		{
		    *mpp = mp->m_next;
		    mp->m_next = maphash[new_hash];
		    maphash[new_hash] = mp;
		    continue;		/* continue with *mpp */
		}
	    }
	    mpp = &(mp->m_next);
	}
    }
}

    static void
showmap(mp)
    struct mapblock *mp;
{
    int len = 1;

    if (msg_didout)
	msg_putchar('\n');
    if ((mp->m_mode & (INSERT + CMDLINE)) == INSERT + CMDLINE)
	msg_putchar('!');			/* :map! */
    else if (mp->m_mode & INSERT)
	msg_putchar('i');			/* :imap */
    else if (mp->m_mode & CMDLINE)
	msg_putchar('c');			/* :cmap */
    else if ((mp->m_mode & (NORMAL + VISUAL + OP_PENDING))
					      == NORMAL + VISUAL + OP_PENDING)
	msg_putchar(' ');			/* :map */
    else
    {
	len = 0;
	if (mp->m_mode & NORMAL)
	{
	    msg_putchar('n');		/* :nmap */
	    ++len;
	}
	if (mp->m_mode & OP_PENDING)
	{
	    msg_putchar('o');		/* :omap */
	    ++len;
	}
	if (mp->m_mode & VISUAL)
	{
	    msg_putchar('v');		/* :vmap */
	    ++len;
	}
    }
    while (++len <= 3)
	msg_putchar(' ');

    /* Get length of what we write */
    len = msg_outtrans_special(mp->m_keys, TRUE);
    do
    {
	msg_putchar(' ');		/* padd with blanks */
	++len;
    } while (len < 12);
    if (mp->m_noremap)
	msg_puts_attr((char_u *)"*", hl_attr(HLF_8));
    else
	msg_putchar(' ');
    /* Use FALSE below if we only want things like <Up> to show up as such on
     * the rhs, and not M-x etc, TRUE gets both -- webb
     */
    if (*mp->m_str == NUL)
	msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8));
    else
	msg_outtrans_special(mp->m_str, TRUE);
    out_flush();			/* show one line at a time */
}

/*
 * Check for an abbreviation.
 * Cursor is at ptr[col]. When inserting, mincol is where insert started.
 * "c" is the character typed before check_abbr was called.
 *
 * Historic vi practice: The last character of an abbreviation must be an id
 * character ([a-zA-Z0-9_]). The characters in front of it must be all id
 * characters or all non-id characters. This allows for abbr. "#i" to
 * "#include".
 *
 * Vim addition: Allow for abbreviations that end in a non-keyword character.
 * Then there must be white space before the abbr.
 *
 * return TRUE if there is an abbreviation, FALSE if not
 */
    int
check_abbr(c, ptr, col, mincol)
    int	    c;
    char_u  *ptr;
    int	    col;
    int	    mincol;
{
    int		    len;
    int		    j;
    char_u	    tb[4];
    struct mapblock *mp;
    int		    is_id = TRUE;
    int		    vim_abbr;

    if (no_abbr_cnt)	    /* abbrev. are not recursive */
	return FALSE;

    /*
     * Check for word before the cursor: If it ends in a keyword char all
     * chars before it must be al keyword chars or non-keyword chars, but not
     * white space. If it ends in a non-keyword char we accept any characters
     * before it except white space.
     */
    if (col == 0)				/* cannot be an abbr. */
	return FALSE;

    if (!vim_iswordc(ptr[col - 1]))
	vim_abbr = TRUE;			/* Vim added abbr. */
    else
    {
	vim_abbr = FALSE;			/* vi compatible abbr. */
	if (col > 1)
	    is_id = vim_iswordc(ptr[col - 2]);
    }
    for (len = col - 1; len > 0 && !vim_isspace(ptr[len - 1]) &&
		       (vim_abbr || is_id == vim_iswordc(ptr[len - 1])); --len)
	;

    if (len < mincol)
	len = mincol;
    if (len < col)		/* there is a word in front of the cursor */
    {
	ptr += len;
	len = col - len;
	for (mp = first_abbr; mp; mp = mp->m_next)
	{
	    /* find entries with right mode and keys */
	    if (       (mp->m_mode & State)
		    && mp->m_keylen == len
		    && !STRNCMP(mp->m_keys, ptr, (size_t)len))
		break;
	}
	if (mp)
	{
	    /*
	     * Found a match:
	     * Insert the rest of the abbreviation in typebuf[].
	     * This goes from end to start.
	     *
	     * Characters 0x000 - 0x100: normal chars, may need CTRL-V,
	     * except K_SPECIAL: Becomes K_SPECIAL KS_SPECIAL K_FILLER
	     * Characters where IS_SPECIAL() == TRUE: key codes, need
	     * K_SPECIAL. Other characters (with ABBR_OFF): don't use CTRL-V.
	     *
	     * Character CTRL(']') is treated specially - it completes the
	     * abbreviation, but is not inserted into the input stream.
	     */
	    j = 0;
					    /* special key code, split up */
	    if (c != Ctrl(']'))
	    {
		if (IS_SPECIAL(c) || c == K_SPECIAL)
		{
		    tb[j++] = K_SPECIAL;
		    tb[j++] = K_SECOND(c);
		    c = K_THIRD(c);
		}
		else if (c < 0x100 && (c < ' ' || c > '~'))
		    tb[j++] = Ctrl('V');    /* special char needs CTRL-V */
		tb[j++] = c;
		tb[j] = NUL;
					    /* insert the last typed char */
		(void)ins_typebuf(tb, TRUE, 0, TRUE);
	    }
					    /* insert the to string */
	    (void)ins_typebuf(mp->m_str, mp->m_noremap ? -1 : 0, 0, TRUE);
					    /* no abbrev. for these chars */
	    no_abbr_cnt += STRLEN(mp->m_str) + j + 1;

	    tb[0] = Ctrl('H');
	    tb[1] = NUL;
	    while (len--)		    /* delete the from string */
		(void)ins_typebuf(tb, TRUE, 0, TRUE);
	    return TRUE;
	}
    }
    return FALSE;
}

/*
 * Write map commands for the current mappings to an .exrc file.
 * Return FAIL on error, OK otherwise.
 */
    int
makemap(fd)
    FILE *fd;
{
    struct mapblock *mp;
    char_u	    c1, c2;
    char_u	    *p;
    char	    *cmd;
    int		    abbr;
    int		    hash;
    int		    did_cpo = FALSE;
    int		    i;

    validate_maphash();

    /*
     * Do the loop twice: Once for mappings, once for abbreviations.
     * Then loop over all map hash lists.
     */
    for (abbr = 0; abbr < 2; ++abbr)
	for (hash = 0; hash < 256; ++hash)
	{
	    if (abbr)
	    {
		if (hash)	    /* there is only one abbr list */
		    break;
		mp = first_abbr;
	    }
	    else
		mp = maphash[hash];
	    for ( ; mp; mp = mp->m_next)
	    {
		c1 = NUL;
		c2 = NUL;
		if (abbr)
		    cmd = "abbr";
		else
		    cmd = "map";
		switch (mp->m_mode)
		{
		    case NORMAL + VISUAL + OP_PENDING:
			break;
		    case NORMAL:
			c1 = 'n';
			break;
		    case VISUAL:
			c1 = 'v';
			break;
		    case OP_PENDING:
			c1 = 'o';
			break;
		    case NORMAL + VISUAL:
			c1 = 'n';
			c2 = 'v';
			break;
		    case VISUAL + OP_PENDING:
			c1 = 'v';
			c2 = 'o';
			break;
		    case NORMAL + OP_PENDING:
			c1 = 'n';
			c2 = 'o';
			break;
		    case CMDLINE + INSERT:
			if (!abbr)
			    cmd = "map!";
			break;
		    case CMDLINE:
			c1 = 'c';
			break;
		    case INSERT:
			c1 = 'i';
			break;
		    default:
			EMSG("makemap: Illegal mode");
			return FAIL;
		}
		do	/* may do this twice if c2 is set */
		{
		    /* When outputting <> form, need to make sure that 'cpo'
		     * is empty. */
		    if (!did_cpo)
		    {
			if (*mp->m_str == NUL)		/* will use <Nop> */
			    did_cpo = TRUE;
			else
			    for (i = 0; i < 2; ++i)
				for (p = (i ? mp->m_str : mp->m_keys); *p; ++p)
				    if (*p == K_SPECIAL || *p == NL)
					did_cpo = TRUE;
			if (did_cpo)
			{
			    if (fprintf(fd,
#ifdef USE_CRNL
					"let cpo_save=&cpo\r\nset cpo=\r\n"
#else
					"let cpo_save=&cpo\nset cpo=\n"
#endif
				       ) < 0)
				return FAIL;
			}
		    }
		    if (c1 && putc(c1, fd) < 0)
			return FAIL;
		    if (mp->m_noremap && fprintf(fd, "nore") < 0)
			return FAIL;
		    if (fprintf(fd, cmd) < 0)
			return FAIL;

		    if (       putc(' ', fd) < 0
			    || putescstr(fd, mp->m_keys, FALSE) == FAIL
			    || putc(' ', fd) < 0
			    || putescstr(fd, mp->m_str, FALSE) == FAIL
#ifdef USE_CRNL
			    || putc('\r', fd) < 0
#endif
			    || putc('\n', fd) < 0)
			return FAIL;
		    c1 = c2;
		    c2 = NUL;
		}
		while (c1);
	    }
	}

    if (did_cpo)
	if (fprintf(fd,
#ifdef USE_CRNL
		    "let &cpo=cpo_save\r\nunlet cpo_save\r\n"
#else
		    "let &cpo=cpo_save\nunlet cpo_save\n"
#endif
		    ) < 0)

⌨️ 快捷键说明

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