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

📄 charset.c

📁 VIM文本编辑器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* vi:set ts=8 sts=4 sw=4:
 *
 * VIM - Vi IMproved	by Bram Moolenaar
 *
 * Do ":help uganda"  in Vim to read copying and usage conditions.
 * Do ":help credits" in Vim to see a list of people who contributed.
 */

#include "vim.h"

/*
 * chartab[] is used
 * - to quickly recognize ID characters
 * - to quickly recognize file name characters
 * - to quickly recognize printable characters
 * - to store the size of a character on the screen: Printable is 1 position,
 *   2 otherwise
 */
static int    chartab_initialized = FALSE;

/*
 * init_chartab(): Fill chartab[] with flags for ID and file name characters
 * and the size of characters on the screen (1 or 2 positions).
 * Also fills b_chartab[] with flags for keyword characters for current
 * buffer.
 *
 * Return FAIL if 'iskeyword', 'isident', 'isfname' or 'isprint' option has an
 * error, OK otherwise.
 */
    int
init_chartab()
{
    int	    c;
    int	    c2;
    char_u  *p;
    int	    i;
    int	    tilde;
    int	    do_isalpha;

    /*
     * Set the default size for printable characters:
     * From <Space> to '~' is 1 (printable), others are 2 (not printable).
     * This also inits all 'isident' and 'isfname' flags to FALSE.
     */
    c = 0;
    while (c < ' ')
	chartab[c++] = 2;
    while (c <= '~')
	chartab[c++] = 1 + CHAR_IP;
#ifdef FKMAP
    if (p_altkeymap)
    {
	while (c < YE)
	    chartab[c++] = 1 + CHAR_IP;
    }
#endif
    while (c < 256)
	chartab[c++] = 2;

    /*
     * Init word char flags all to FALSE
     */
    if (curbuf != NULL)
	for (c = 0; c < 256; ++c)
	    curbuf->b_chartab[c] = FALSE;

#ifdef LISPINDENT
    /*
     * In lisp mode the '-' character is included in keywords.
     */
    if (curbuf->b_p_lisp)
	curbuf->b_chartab['-'] = TRUE;
#endif

    /* Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint'
     * options Each option is a list of characters, character numbers or
     * ranges, separated by commas, e.g.: "200-210,x,#-178,-"
     */
    for (i = 0; i < 4; ++i)
    {
	if (i == 0)
	    p = p_isi;		    /* first round: 'isident' */
	else if (i == 1)
	    p = p_isp;		    /* second round: 'isprint' */
	else if (i == 2)
	    p = p_isf;		    /* third round: 'isfname' */
	else	/* i == 3 */
	    p = curbuf->b_p_isk;    /* fourth round: 'iskeyword' */

	while (*p)
	{
	    tilde = FALSE;
	    do_isalpha = FALSE;
	    if (*p == '^' && p[1] != NUL)
	    {
		tilde = TRUE;
		++p;
	    }
	    if (isdigit(*p))
		c = getdigits(&p);
	    else
		c = *p++;
	    c2 = -1;
	    if (*p == '-' && p[1] != NUL)
	    {
		++p;
		if (isdigit(*p))
		    c2 = getdigits(&p);
		else
		    c2 = *p++;
	    }
	    if (c <= 0 || (c2 < c && c2 != -1) || c2 >= 256 ||
						    !(*p == NUL || *p == ','))
		return FAIL;

	    if (c2 == -1)	/* not a range */
	    {
		/*
		 * A single '@' (not "@-@"):
		 * Decide on letters being ID/printable/keyword chars with
		 * standard function isalpha(). This takes care of locale.
		 */
		if (c == '@')
		{
		    do_isalpha = TRUE;
		    c = 1;
		    c2 = 255;
		}
		else
		    c2 = c;
	    }
	    while (c <= c2)
	    {
		if (!do_isalpha || isalpha(c)
#ifdef FKMAP
			|| (p_altkeymap && (F_isalpha(c) || F_isdigit(c)))
#endif
			    )
		{
		    if (i == 0)			/* (re)set ID flag */
		    {
			if (tilde)
			    chartab[c] &= ~CHAR_ID;
			else
			    chartab[c] |= CHAR_ID;
		    }
		    else if (i == 1)		/* set printable to 1 or 2 */
		    {
			if (c < ' ' || c > '~'
#ifdef FKMAP
				|| (p_altkeymap
					    && (F_isalpha(c) || F_isdigit(c)))
#endif
				)
			{
			    if (tilde)
			    {
				chartab[c] = (chartab[c] & ~CHAR_MASK) + 2;
				chartab[c] &= ~CHAR_IP;
			    }
			    else
			    {
				chartab[c] = (chartab[c] & ~CHAR_MASK) + 1;
				chartab[c] |= CHAR_IP;
			    }
			}
		    }
		    else if (i == 2)		/* (re)set fname flag */
		    {
			if (tilde)
			    chartab[c] &= ~CHAR_IF;
			else
			    chartab[c] |= CHAR_IF;
		    }
		    else /* i == 3 */		/* (re)set keyword flag */
			curbuf->b_chartab[c] = !tilde;
		}
		++c;
	    }
	    p = skip_to_option_part(p);
	}
    }
    chartab_initialized = TRUE;
    return OK;
}

/*
 * Translate any special characters in buf[bufsize].
 * If there is not enough room, not all characters will be translated.
 */
    void
trans_characters(buf, bufsize)
    char_u  *buf;
    int	    bufsize;
{
    int	    len;	    /* length of string needing translation */
    int	    room;	    /* room in buffer after string */
    char_u  *new;	    /* translated character */
    int	    new_len;	    /* length of new[] */

    len = STRLEN(buf);
    room = bufsize - len;
    while (*buf)
    {
	new = transchar(*buf);
	new_len = STRLEN(new);
	if (new_len > 1)
	{
	    room -= new_len - 1;
	    if (room <= 0)
		return;
	    mch_memmove(buf + new_len, buf + 1, (size_t)len);
	}
	mch_memmove(buf, new, (size_t)new_len);
	buf += new_len;
	--len;
    }
}

/*
 * Catch 22: chartab[] can't be initialized before the options are
 * initialized, and initializing options may cause transchar() to be called!
 * When chartab_initialized == FALSE don't use chartab[].
 */
    char_u *
transchar(c)
    int	 c;
{
    static char_u   buf[5];
    int		    i;

    i = 0;
    if (IS_SPECIAL(c))	    /* special key code, display as ~@ char */
    {
	buf[0] = '~';
	buf[1] = '@';
	i = 2;
	c = K_SECOND(c);
    }

    if ((!chartab_initialized && ((c >= ' ' && c <= '~')
#ifdef FKMAP
			|| F_ischar(c)
#endif
		)) || (chartab[c] & CHAR_IP))	    /* printable character */
    {
	buf[i] = c;
	buf[i + 1] = NUL;
    }
    else
	transchar_nonprint(buf + i, c);
    return buf;
}

    void
transchar_nonprint(buf, c)
    char_u	*buf;
    int		c;
{
    if (c <= 0x7f)				    /* 0x00 - 0x1f and 0x7f */
    {
	if (c == NL)
	    c = NUL;			/* we use newline in place of a NUL */
	buf[0] = '^';
	buf[1] = c ^ 0x40;		/* DEL displayed as ^? */
	buf[2] = NUL;
    }
    else if (c >= ' ' + 0x80 && c <= '~' + 0x80)    /* 0xa0 - 0xfe */
    {
	buf[0] = '|';
	buf[1] = c - 0x80;
	buf[2] = NUL;
    }
    else					    /* 0x80 - 0x9f and 0xff */
    {
	buf[0] = '~';
	buf[1] = (c - 0x80) ^ 0x40;	/* 0xff displayed as ~? */
	buf[2] = NUL;
    }
}

/*
 * return the number of characters 'c' will take on the screen
 * This is used very often, keep it fast!!!
 */
    int
charsize(c)
    int c;
{
    if (IS_SPECIAL(c))
	return (chartab[K_SECOND(c)] & CHAR_MASK) + 2;
    return (chartab[c] & CHAR_MASK);
}

/*
 * Return the number of characters string 's' will take on the screen,
 * counting TABs as two characters: "^I".
 */
    int
vim_strsize(s)
    char_u *s;
{
    int	    len = 0;

    while (*s)
	len += charsize(*s++);
    return len;
}

/*
 * Return the number of characters 'c' will take on the screen, taking
 * into account the size of a tab.
 * Use a define to make it fast, this is used very often!!!
 * Also see getvcol() below.
 */

#define RET_WIN_BUF_CHARTABSIZE(wp, buf, c, col) \
    if ((c) == TAB && (!(wp)->w_p_list || lcs_tab1)) \
    { \
	int ts; \
	ts = (buf)->b_p_ts; \
	return (int)(ts - (col % ts)); \
    } \
    else \
	return charsize(c);

    int
chartabsize(c, col)
    int		c;
    colnr_t	col;
{
    RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, c, col)
}

    int
win_chartabsize(wp, c, col)
    WIN		*wp;
    int		c;
    colnr_t	col;
{
    RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, c, col)
}

/*
 * return the number of characters the string 's' will take on the screen,
 * taking into account the size of a tab
 */
    int
linetabsize(s)
    char_u	*s;
{
    colnr_t	col = 0;

    while (*s != NUL)
	col += lbr_chartabsize(s++, col);
    return (int)col;
}

/*
 * Like linetabsize(), but for a given window instead of the current one.
 */
    int
win_linetabsize(wp, s)
    WIN		*wp;
    char_u	*s;
{
    colnr_t	col = 0;

    while (*s != NUL)
	col += win_lbr_chartabsize(wp, s++, col, NULL);
    return (int)col;
}

/*
 * return TRUE if 'c' is a normal identifier character
 * letters and characters from 'isident' option.
 */
    int
vim_isIDc(c)
    int c;
{
    return (c < 0x100 && (chartab[c] & CHAR_ID));
}

/*
 * return TRUE if 'c' is a keyword character: Letters and characters from
 * 'iskeyword' option for current buffer.
 */
    int
vim_iswordc(c)
    int c;
{
    return (c < 0x100 && curbuf->b_chartab[c]);
}

    int
vim_iswordc_buf(c, buf)
    int c;
    BUF	*buf;
{
    return (c < 0x100 && buf->b_chartab[c]);
}

/*
 * return TRUE if 'c' is a valid file-name character
 */
    int
vim_isfilec(c)
    int	c;
{
    return (c < 0x100 && (chartab[c] & CHAR_IF));
}

/*
 * return TRUE if 'c' is a printable character
 */
    int
vim_isprintc(c)
    int c;
{
    return (c < 0x100 && (chartab[c] & CHAR_IP));
}

/*
 * return TRUE if 'c' is a printable character

⌨️ 快捷键说明

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