/* 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. Load more
/* 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_LINEBREAK static int win_chartabsize __ARGS((win_T *wp, char_u *p, colnr_T col)); #endif #ifdef FEAT_MBYTE static 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. */ int init_chartab() { return buf_init_chartab(curbuf, TRUE); } int buf_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. */ 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 *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]);