1975 lines · 44.2 KB · C
RawDownload
/* 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. * See README.txt for an overview of the Vim source code. */ #include "vim.h" #ifdef FEAT_LINEBREAKstatic int win_chartabsize __ARGS((win_T *wp, char_u *p, colnr_T col));#endif #ifdef FEAT_MBYTEstatic int win_nolbr_chartabsize __ARGS((win_T *wp, char_u *s, colnr_T col, int *headp));#endif static int nr2hex __ARGS((int c)); static int    chartab_initialized = FALSE; /* b_chartab[] is an array of 32 bytes, each bit representing one of the * characters 0-255. */#define SET_CHARTAB(buf, c) (buf)->b_chartab[(unsigned)(c) >> 3] |= (1 << ((c) & 0x7))#define RESET_CHARTAB(buf, c) (buf)->b_chartab[(unsigned)(c) >> 3] &= ~(1 << ((c) & 0x7))#define GET_CHARTAB(buf, c) ((buf)->b_chartab[(unsigned)(c) >> 3] & (1 << ((c) & 0x7))) /* * Fill chartab[].  Also fills curbuf->b_chartab[] with flags for keyword * characters for current buffer. * * Depends on the option settings 'iskeyword', 'isident', 'isfname', * 'isprint' and 'encoding'. * * The index in chartab[] depends on 'encoding': * - For non-multi-byte index with the byte (same as the character). * - For DBCS index with the first byte. * - For UTF-8 index with the character (when first byte is up to 0x80 it is *   the same as the character, if the first byte is 0x80 and above it depends *   on further bytes). * * The contents of chartab[]: * - The lower two bits, masked by CT_CELL_MASK, give the number of display *   cells the character occupies (1 or 2).  Not valid for UTF-8 above 0x80. * - CT_PRINT_CHAR bit is set when the character is printable (no need to *   translate the character before displaying it).  Note that only DBCS *   characters can have 2 display cells and still be printable. * - CT_FNAME_CHAR bit is set when the character can be in a file name. * - CT_ID_CHAR bit is set when the character can be in an identifier. * * Return FAIL if 'iskeyword', 'isident', 'isfname' or 'isprint' option has an * error, OK otherwise. */    intinit_chartab(){    return buf_init_chartab(curbuf, TRUE);}     intbuf_init_chartab(buf, global)    buf_T	*buf;    int		global;		/* FALSE: only set buf->b_chartab[] */{    int		c;    int		c2;    char_u	*p;    int		i;    int		tilde;    int		do_isalpha;     if (global)    {	/*	 * 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.	 *	 * EBCDIC: all chars below ' ' are not printable, all others are	 * printable.	 */	c = 0;	while (c < ' ')	    chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2;#ifdef EBCDIC	while (c < 255)#else	while (c <= '~')#endif	    chartab[c++] = 1 + CT_PRINT_CHAR;#ifdef FEAT_FKMAP	if (p_altkeymap)	{	    while (c < YE)		chartab[c++] = 1 + CT_PRINT_CHAR;	}#endif	while (c < 256)	{#ifdef FEAT_MBYTE	    /* UTF-8: bytes 0xa0 - 0xff are printable (latin1) */	    if (enc_utf8 && c >= 0xa0)		chartab[c++] = CT_PRINT_CHAR + 1;	    /* euc-jp characters starting with 0x8e are single width */	    else if (enc_dbcs == DBCS_JPNU && c == 0x8e)		chartab[c++] = CT_PRINT_CHAR + 1;	    /* other double-byte chars can be printable AND double-width */	    else if (enc_dbcs != 0 && MB_BYTE2LEN(c) == 2)		chartab[c++] = CT_PRINT_CHAR + 2;	    else#endif		/* the rest is unprintable by default */		chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2;	} #ifdef FEAT_MBYTE	/* Assume that every multi-byte char is a filename character. */	for (c = 1; c < 256; ++c)	    if ((enc_dbcs != 0 && MB_BYTE2LEN(c) > 1)		    || (enc_dbcs == DBCS_JPNU && c == 0x8e)		    || (enc_utf8 && c >= 0xa0))		chartab[c] |= CT_FNAME_CHAR;#endif    }     /*     * Init word char flags all to FALSE     */    vim_memset(buf->b_chartab, 0, (size_t)32);#ifdef FEAT_MBYTE    if (enc_dbcs != 0)	for (c = 0; c < 256; ++c)	{	    /* double-byte characters are probably word characters */	    if (MB_BYTE2LEN(c) == 2)		SET_CHARTAB(buf, c);	}#endif #ifdef FEAT_LISP    /*     * In lisp mode the '-' character is included in keywords.     */    if (buf->b_p_lisp)	SET_CHARTAB(buf, '-');#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 = global ? 0 : 3; i <= 3; ++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 = buf->b_p_isk;	/* fourth round: 'iskeyword' */ 	while (*p)	{	    tilde = FALSE;	    do_isalpha = FALSE;	    if (*p == '^' && p[1] != NUL)	    {		tilde = TRUE;		++p;	    }	    if (VIM_ISDIGIT(*p))		c = getdigits(&p);	    else		c = *p++;	    c2 = -1;	    if (*p == '-' && p[1] != NUL)	    {		++p;		if (VIM_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 for		 * single-byte characters).		 */		if (c == '@')		{		    do_isalpha = TRUE;		    c = 1;		    c2 = 255;		}		else		    c2 = c;	    }	    while (c <= c2)	    {		if (!do_isalpha || isalpha(c)#ifdef FEAT_FKMAP			|| (p_altkeymap && (F_isalpha(c) || F_isdigit(c)))#endif			    )		{		    if (i == 0)			/* (re)set ID flag */		    {			if (tilde)			    chartab[c] &= ~CT_ID_CHAR;			else			    chartab[c] |= CT_ID_CHAR;		    }		    else if (i == 1)		/* (re)set printable */		    {			if ((c < ' '#ifndef EBCDIC				    || c > '~'#endif#ifdef FEAT_FKMAP				    || (p_altkeymap					&& (F_isalpha(c) || F_isdigit(c)))#endif			    )#ifdef FEAT_MBYTE				/* For double-byte we keep the cell width, so				 * that we can detect it from the first byte. */				&& !(enc_dbcs && MB_BYTE2LEN(c) == 2)#endif			   )			{			    if (tilde)			    {				chartab[c] = (chartab[c] & ~CT_CELL_MASK)					     + ((dy_flags & DY_UHEX) ? 4 : 2);				chartab[c] &= ~CT_PRINT_CHAR;			    }			    else			    {				chartab[c] = (chartab[c] & ~CT_CELL_MASK) + 1;				chartab[c] |= CT_PRINT_CHAR;			    }			}		    }		    else if (i == 2)		/* (re)set fname flag */		    {			if (tilde)			    chartab[c] &= ~CT_FNAME_CHAR;			else			    chartab[c] |= CT_FNAME_CHAR;		    }		    else /* i == 3 */		/* (re)set keyword flag */		    {			if (tilde)			    RESET_CHARTAB(buf, c);			else			    SET_CHARTAB(buf, c);		    }		}		++c;	    }	    p = skip_to_option_part(p);	}    }    chartab_initialized = TRUE;    return OK;} /* * Translate any special characters in buf[bufsize] in-place. * The result is a string with only printable characters, but if there is not * enough room, not all characters will be translated. */    voidtrans_characters(buf, bufsize)    char_u	*buf;    int		bufsize;{    int		len;		/* length of string needing translation */    int		room;		/* room in buffer after string */    char_u	*trs;		/* translated character */    int		trs_len;	/* length of trs[] */     len = (int)STRLEN(buf);    room = bufsize - len;    while (*buf != 0)    {# ifdef FEAT_MBYTE	/* Assume a multi-byte character doesn't need translation. */	if (has_mbyte && (trs_len = (*mb_ptr2len)(buf)) > 1)	    len -= trs_len;	else# endif	{	    trs = transchar_byte(*buf);	    trs_len = (int)STRLEN(trs);	    if (trs_len > 1)	    {		room -= trs_len - 1;		if (room <= 0)		    return;		mch_memmove(buf + trs_len, buf + 1, (size_t)len);	    }	    mch_memmove(buf, trs, (size_t)trs_len);	    --len;	}	buf += trs_len;    }} #if defined(FEAT_EVAL) || defined(FEAT_TITLE) || defined(FEAT_INS_EXPAND) \	|| defined(PROTO)/* * Translate a string into allocated memory, replacing special chars with * printable chars.  Returns NULL when out of memory. */    char_u *transstr(s)    char_u	*s;{    char_u	*res;    char_u	*p;#ifdef FEAT_MBYTE    int		l, len, c;    char_u	hexbuf[11];#endif #ifdef FEAT_MBYTE    if (has_mbyte)    {	/* Compute the length of the result, taking account of unprintable	 * multi-byte characters. */	len = 0;	p = s;	while (*p != NUL)	{	    if ((l = (*mb_ptr2len)(p)) > 1)	    {		c = (*mb_ptr2char)(p);		p += l;		if (vim_isprintc(c))		    len += l;		else		{		    transchar_hex(hexbuf, c);		    len += (int)STRLEN(hexbuf);		}	    }	    else	    {		l = byte2cells(*p++);		if (l > 0)		    len += l;		else		    len += 4;	/* illegal byte sequence */	    }	}	res = alloc((unsigned)(len + 1));    }    else#endif	res = alloc((unsigned)(vim_strsize(s) + 1));    if (res != NULL)    {	*res = NUL;	p = s;	while (*p != NUL)	{#ifdef FEAT_MBYTE	    if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)	    {		c = (*mb_ptr2char)(p);		if (vim_isprintc(c))		    STRNCAT(res, p, l);	/* append printable multi-byte char */		else		    transchar_hex(res + STRLEN(res), c);		p += l;	    }	    else#endif		STRCAT(res, transchar_byte(*p++));	}    }    return res;}#endif #if defined(FEAT_SYN_HL) || defined(FEAT_INS_EXPAND) || defined(PROTO)/* * Convert the string "str[orglen]" to do ignore-case comparing.  Uses the * current locale. * When "buf" is NULL returns an allocated string (NULL for out-of-memory). * Otherwise puts the result in "buf[buflen]". */    char_u *str_foldcase(str, orglen, buf, buflen)    char_u	*str;    int		orglen;    char_u	*buf;    int		buflen;{    garray_T	ga;    int		i;    int		len = orglen; #define GA_CHAR(i)  ((char_u *)ga.ga_data)[i]#define GA_PTR(i)   ((char_u *)ga.ga_data + i)#define STR_CHAR(i)  (buf == NULL ? GA_CHAR(i) : buf[i])#define STR_PTR(i)   (buf == NULL ? GA_PTR(i) : buf + i)     /* Copy "str" into "buf" or allocated memory, unmodified. */    if (buf == NULL)    {	ga_init2(&ga, 1, 10);	if (ga_grow(&ga, len + 1) == FAIL)	    return NULL;	mch_memmove(ga.ga_data, str, (size_t)len);	ga.ga_len = len;    }    else    {	if (len >= buflen)	    /* Ugly! */	    len = buflen - 1;	mch_memmove(buf, str, (size_t)len);    }    if (buf == NULL)	GA_CHAR(len) = NUL;    else	buf[len] = NUL;     /* Make each character lower case. */    i = 0;    while (STR_CHAR(i) != NUL)    {#ifdef FEAT_MBYTE	if (enc_utf8 || (has_mbyte && MB_BYTE2LEN(STR_CHAR(i)) > 1))	{	    if (enc_utf8)	    {		int	c, lc; 		c = utf_ptr2char(STR_PTR(i));		lc = utf_tolower(c);		if (c != lc)		{		    int	    ol = utf_char2len(c);		    int	    nl = utf_char2len(lc); 		    /* If the byte length changes need to shift the following		     * characters forward or backward. */		    if (ol != nl)		    {			if (nl > ol)			{			    if (buf == NULL ? ga_grow(&ga, nl - ol + 1) == FAIL						    : len + nl - ol >= buflen)			    {				/* out of memory, keep old char */				lc = c;				nl = ol;			    }			}			if (ol != nl)			{			    if (buf == NULL)			    {				mch_memmove(GA_PTR(i) + nl, GA_PTR(i) + ol,						  STRLEN(GA_PTR(i) + ol) + 1);				ga.ga_len += nl - ol;			    }			    else			    {				mch_memmove(buf + i + nl, buf + i + ol,						    STRLEN(buf + i + ol) + 1);				len += nl - ol;			    }			}		    }		    (void)utf_char2bytes(lc, STR_PTR(i));		}	    }	    /* skip to next multi-byte char */	    i += (*mb_ptr2len)(STR_PTR(i));	}	else#endif	{	    if (buf == NULL)		GA_CHAR(i) = TOLOWER_LOC(GA_CHAR(i));	    else		buf[i] = TOLOWER_LOC(buf[i]);

Lines 1–500 of 1975.