blob: 6cf4a2bb135983029e16466714c87012a1fdd903 [file] [log] [blame]
Bram Moolenaaredf3f972016-08-29 22:49:24 +02001/* vi:set ts=8 sts=4 sw=4 noet:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10#include "vim.h"
11
Bram Moolenaar13505972019-01-24 15:04:48 +010012#if defined(HAVE_WCHAR_H)
Bram Moolenaarc667da52019-11-30 20:52:27 +010013# include <wchar.h> // for towupper() and towlower()
Bram Moolenaar071d4272004-06-13 20:20:40 +000014#endif
Bram Moolenaar13505972019-01-24 15:04:48 +010015static int win_nolbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp);
Bram Moolenaar071d4272004-06-13 20:20:40 +000016
Bram Moolenaarf28dbce2016-01-29 22:03:47 +010017static unsigned nr2hex(unsigned c);
Bram Moolenaar071d4272004-06-13 20:20:40 +000018
19static int chartab_initialized = FALSE;
20
Bram Moolenaarc667da52019-11-30 20:52:27 +010021// b_chartab[] is an array of 32 bytes, each bit representing one of the
22// characters 0-255.
Bram Moolenaar071d4272004-06-13 20:20:40 +000023#define SET_CHARTAB(buf, c) (buf)->b_chartab[(unsigned)(c) >> 3] |= (1 << ((c) & 0x7))
24#define RESET_CHARTAB(buf, c) (buf)->b_chartab[(unsigned)(c) >> 3] &= ~(1 << ((c) & 0x7))
25#define GET_CHARTAB(buf, c) ((buf)->b_chartab[(unsigned)(c) >> 3] & (1 << ((c) & 0x7)))
26
Bram Moolenaarc667da52019-11-30 20:52:27 +010027// table used below, see init_chartab() for an explanation
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +010028static char_u g_chartab[256];
29
Bram Moolenaar071d4272004-06-13 20:20:40 +000030/*
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +010031 * Flags for g_chartab[].
32 */
Bram Moolenaarc667da52019-11-30 20:52:27 +010033#define CT_CELL_MASK 0x07 // mask: nr of display cells (1, 2 or 4)
34#define CT_PRINT_CHAR 0x10 // flag: set for printable chars
35#define CT_ID_CHAR 0x20 // flag: set for ID chars
36#define CT_FNAME_CHAR 0x40 // flag: set for file name chars
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +010037
Bram Moolenaar5843f5f2019-08-20 20:13:45 +020038static int in_win_border(win_T *wp, colnr_T vcol);
39
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +010040/*
41 * Fill g_chartab[]. Also fills curbuf->b_chartab[] with flags for keyword
Bram Moolenaar071d4272004-06-13 20:20:40 +000042 * characters for current buffer.
43 *
44 * Depends on the option settings 'iskeyword', 'isident', 'isfname',
45 * 'isprint' and 'encoding'.
46 *
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +010047 * The index in g_chartab[] depends on 'encoding':
Bram Moolenaar071d4272004-06-13 20:20:40 +000048 * - For non-multi-byte index with the byte (same as the character).
49 * - For DBCS index with the first byte.
50 * - For UTF-8 index with the character (when first byte is up to 0x80 it is
51 * the same as the character, if the first byte is 0x80 and above it depends
52 * on further bytes).
53 *
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +010054 * The contents of g_chartab[]:
Bram Moolenaar071d4272004-06-13 20:20:40 +000055 * - The lower two bits, masked by CT_CELL_MASK, give the number of display
56 * cells the character occupies (1 or 2). Not valid for UTF-8 above 0x80.
57 * - CT_PRINT_CHAR bit is set when the character is printable (no need to
58 * translate the character before displaying it). Note that only DBCS
59 * characters can have 2 display cells and still be printable.
60 * - CT_FNAME_CHAR bit is set when the character can be in a file name.
61 * - CT_ID_CHAR bit is set when the character can be in an identifier.
62 *
63 * Return FAIL if 'iskeyword', 'isident', 'isfname' or 'isprint' option has an
64 * error, OK otherwise.
65 */
66 int
Bram Moolenaar7454a062016-01-30 15:14:10 +010067init_chartab(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +000068{
69 return buf_init_chartab(curbuf, TRUE);
70}
71
72 int
Bram Moolenaar7454a062016-01-30 15:14:10 +010073buf_init_chartab(
74 buf_T *buf,
Bram Moolenaarc667da52019-11-30 20:52:27 +010075 int global) // FALSE: only set buf->b_chartab[]
Bram Moolenaar071d4272004-06-13 20:20:40 +000076{
77 int c;
78 int c2;
79 char_u *p;
80 int i;
81 int tilde;
82 int do_isalpha;
83
84 if (global)
85 {
86 /*
87 * Set the default size for printable characters:
88 * From <Space> to '~' is 1 (printable), others are 2 (not printable).
89 * This also inits all 'isident' and 'isfname' flags to FALSE.
90 *
91 * EBCDIC: all chars below ' ' are not printable, all others are
92 * printable.
93 */
94 c = 0;
95 while (c < ' ')
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +010096 g_chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +000097#ifdef EBCDIC
98 while (c < 255)
99#else
100 while (c <= '~')
101#endif
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100102 g_chartab[c++] = 1 + CT_PRINT_CHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000103 while (c < 256)
104 {
Bram Moolenaarc667da52019-11-30 20:52:27 +0100105 // UTF-8: bytes 0xa0 - 0xff are printable (latin1)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000106 if (enc_utf8 && c >= 0xa0)
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100107 g_chartab[c++] = CT_PRINT_CHAR + 1;
Bram Moolenaarc667da52019-11-30 20:52:27 +0100108 // euc-jp characters starting with 0x8e are single width
Bram Moolenaar071d4272004-06-13 20:20:40 +0000109 else if (enc_dbcs == DBCS_JPNU && c == 0x8e)
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100110 g_chartab[c++] = CT_PRINT_CHAR + 1;
Bram Moolenaarc667da52019-11-30 20:52:27 +0100111 // other double-byte chars can be printable AND double-width
Bram Moolenaar071d4272004-06-13 20:20:40 +0000112 else if (enc_dbcs != 0 && MB_BYTE2LEN(c) == 2)
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100113 g_chartab[c++] = CT_PRINT_CHAR + 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000114 else
Bram Moolenaarc667da52019-11-30 20:52:27 +0100115 // the rest is unprintable by default
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100116 g_chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000117 }
118
Bram Moolenaarc667da52019-11-30 20:52:27 +0100119 // Assume that every multi-byte char is a filename character.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000120 for (c = 1; c < 256; ++c)
121 if ((enc_dbcs != 0 && MB_BYTE2LEN(c) > 1)
122 || (enc_dbcs == DBCS_JPNU && c == 0x8e)
123 || (enc_utf8 && c >= 0xa0))
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100124 g_chartab[c] |= CT_FNAME_CHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000125 }
126
127 /*
128 * Init word char flags all to FALSE
129 */
Bram Moolenaara80faa82020-04-12 19:37:17 +0200130 CLEAR_FIELD(buf->b_chartab);
Bram Moolenaar6bb68362005-03-22 23:03:44 +0000131 if (enc_dbcs != 0)
132 for (c = 0; c < 256; ++c)
133 {
Bram Moolenaarc667da52019-11-30 20:52:27 +0100134 // double-byte characters are probably word characters
Bram Moolenaar6bb68362005-03-22 23:03:44 +0000135 if (MB_BYTE2LEN(c) == 2)
136 SET_CHARTAB(buf, c);
137 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000138
139#ifdef FEAT_LISP
140 /*
141 * In lisp mode the '-' character is included in keywords.
142 */
143 if (buf->b_p_lisp)
144 SET_CHARTAB(buf, '-');
145#endif
146
Bram Moolenaarc667da52019-11-30 20:52:27 +0100147 // Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint'
148 // options Each option is a list of characters, character numbers or
149 // ranges, separated by commas, e.g.: "200-210,x,#-178,-"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000150 for (i = global ? 0 : 3; i <= 3; ++i)
151 {
152 if (i == 0)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100153 p = p_isi; // first round: 'isident'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000154 else if (i == 1)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100155 p = p_isp; // second round: 'isprint'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000156 else if (i == 2)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100157 p = p_isf; // third round: 'isfname'
158 else // i == 3
159 p = buf->b_p_isk; // fourth round: 'iskeyword'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000160
161 while (*p)
162 {
163 tilde = FALSE;
164 do_isalpha = FALSE;
165 if (*p == '^' && p[1] != NUL)
166 {
167 tilde = TRUE;
168 ++p;
169 }
170 if (VIM_ISDIGIT(*p))
171 c = getdigits(&p);
172 else
Bram Moolenaar183bb3e2009-09-11 12:02:34 +0000173 if (has_mbyte)
174 c = mb_ptr2char_adv(&p);
175 else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000176 c = *p++;
177 c2 = -1;
178 if (*p == '-' && p[1] != NUL)
179 {
180 ++p;
181 if (VIM_ISDIGIT(*p))
182 c2 = getdigits(&p);
183 else
Bram Moolenaar2ac5e602009-11-03 15:04:20 +0000184 if (has_mbyte)
185 c2 = mb_ptr2char_adv(&p);
186 else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000187 c2 = *p++;
188 }
Bram Moolenaar2ac5e602009-11-03 15:04:20 +0000189 if (c <= 0 || c >= 256 || (c2 < c && c2 != -1) || c2 >= 256
Bram Moolenaar071d4272004-06-13 20:20:40 +0000190 || !(*p == NUL || *p == ','))
191 return FAIL;
192
Bram Moolenaarc667da52019-11-30 20:52:27 +0100193 if (c2 == -1) // not a range
Bram Moolenaar071d4272004-06-13 20:20:40 +0000194 {
195 /*
196 * A single '@' (not "@-@"):
197 * Decide on letters being ID/printable/keyword chars with
198 * standard function isalpha(). This takes care of locale for
199 * single-byte characters).
200 */
201 if (c == '@')
202 {
203 do_isalpha = TRUE;
204 c = 1;
205 c2 = 255;
206 }
207 else
208 c2 = c;
209 }
210 while (c <= c2)
211 {
Bram Moolenaarc667da52019-11-30 20:52:27 +0100212 // Use the MB_ functions here, because isalpha() doesn't
213 // work properly when 'encoding' is "latin1" and the locale is
214 // "C".
Bram Moolenaar14184a32019-02-16 15:10:30 +0100215 if (!do_isalpha || MB_ISLOWER(c) || MB_ISUPPER(c))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000216 {
Bram Moolenaarc667da52019-11-30 20:52:27 +0100217 if (i == 0) // (re)set ID flag
Bram Moolenaar071d4272004-06-13 20:20:40 +0000218 {
219 if (tilde)
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100220 g_chartab[c] &= ~CT_ID_CHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000221 else
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100222 g_chartab[c] |= CT_ID_CHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000223 }
Bram Moolenaarc667da52019-11-30 20:52:27 +0100224 else if (i == 1) // (re)set printable
Bram Moolenaar071d4272004-06-13 20:20:40 +0000225 {
226 if ((c < ' '
227#ifndef EBCDIC
228 || c > '~'
229#endif
Bram Moolenaar13505972019-01-24 15:04:48 +0100230 // For double-byte we keep the cell width, so
231 // that we can detect it from the first byte.
232 ) && !(enc_dbcs && MB_BYTE2LEN(c) == 2))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000233 {
234 if (tilde)
235 {
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100236 g_chartab[c] = (g_chartab[c] & ~CT_CELL_MASK)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000237 + ((dy_flags & DY_UHEX) ? 4 : 2);
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100238 g_chartab[c] &= ~CT_PRINT_CHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000239 }
240 else
241 {
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100242 g_chartab[c] = (g_chartab[c] & ~CT_CELL_MASK) + 1;
243 g_chartab[c] |= CT_PRINT_CHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000244 }
245 }
246 }
Bram Moolenaarc667da52019-11-30 20:52:27 +0100247 else if (i == 2) // (re)set fname flag
Bram Moolenaar071d4272004-06-13 20:20:40 +0000248 {
249 if (tilde)
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100250 g_chartab[c] &= ~CT_FNAME_CHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000251 else
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100252 g_chartab[c] |= CT_FNAME_CHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000253 }
Bram Moolenaarc667da52019-11-30 20:52:27 +0100254 else // i == 3 (re)set keyword flag
Bram Moolenaar071d4272004-06-13 20:20:40 +0000255 {
256 if (tilde)
257 RESET_CHARTAB(buf, c);
258 else
259 SET_CHARTAB(buf, c);
260 }
261 }
262 ++c;
263 }
Bram Moolenaar309379f2013-02-06 16:26:26 +0100264
265 c = *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000266 p = skip_to_option_part(p);
Bram Moolenaar309379f2013-02-06 16:26:26 +0100267 if (c == ',' && *p == NUL)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100268 // Trailing comma is not allowed.
Bram Moolenaar309379f2013-02-06 16:26:26 +0100269 return FAIL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000270 }
271 }
272 chartab_initialized = TRUE;
273 return OK;
274}
275
276/*
277 * Translate any special characters in buf[bufsize] in-place.
278 * The result is a string with only printable characters, but if there is not
279 * enough room, not all characters will be translated.
280 */
281 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100282trans_characters(
283 char_u *buf,
284 int bufsize)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000285{
Bram Moolenaarc667da52019-11-30 20:52:27 +0100286 int len; // length of string needing translation
287 int room; // room in buffer after string
288 char_u *trs; // translated character
289 int trs_len; // length of trs[]
Bram Moolenaar071d4272004-06-13 20:20:40 +0000290
291 len = (int)STRLEN(buf);
292 room = bufsize - len;
293 while (*buf != 0)
294 {
Bram Moolenaarc667da52019-11-30 20:52:27 +0100295 // Assume a multi-byte character doesn't need translation.
Bram Moolenaar0fa313a2005-08-10 21:07:57 +0000296 if (has_mbyte && (trs_len = (*mb_ptr2len)(buf)) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000297 len -= trs_len;
298 else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000299 {
300 trs = transchar_byte(*buf);
301 trs_len = (int)STRLEN(trs);
302 if (trs_len > 1)
303 {
304 room -= trs_len - 1;
305 if (room <= 0)
306 return;
307 mch_memmove(buf + trs_len, buf + 1, (size_t)len);
308 }
309 mch_memmove(buf, trs, (size_t)trs_len);
310 --len;
311 }
312 buf += trs_len;
313 }
314}
315
Bram Moolenaar071d4272004-06-13 20:20:40 +0000316/*
317 * Translate a string into allocated memory, replacing special chars with
318 * printable chars. Returns NULL when out of memory.
319 */
320 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100321transstr(char_u *s)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000322{
323 char_u *res;
324 char_u *p;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000325 int l, len, c;
326 char_u hexbuf[11];
Bram Moolenaar071d4272004-06-13 20:20:40 +0000327
Bram Moolenaar071d4272004-06-13 20:20:40 +0000328 if (has_mbyte)
329 {
Bram Moolenaarc667da52019-11-30 20:52:27 +0100330 // Compute the length of the result, taking account of unprintable
331 // multi-byte characters.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000332 len = 0;
333 p = s;
334 while (*p != NUL)
335 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +0000336 if ((l = (*mb_ptr2len)(p)) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000337 {
338 c = (*mb_ptr2char)(p);
339 p += l;
340 if (vim_isprintc(c))
341 len += l;
342 else
343 {
344 transchar_hex(hexbuf, c);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000345 len += (int)STRLEN(hexbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000346 }
347 }
348 else
349 {
350 l = byte2cells(*p++);
351 if (l > 0)
352 len += l;
353 else
Bram Moolenaarc667da52019-11-30 20:52:27 +0100354 len += 4; // illegal byte sequence
Bram Moolenaar071d4272004-06-13 20:20:40 +0000355 }
356 }
Bram Moolenaar964b3742019-05-24 18:54:09 +0200357 res = alloc(len + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000358 }
359 else
Bram Moolenaar964b3742019-05-24 18:54:09 +0200360 res = alloc(vim_strsize(s) + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000361 if (res != NULL)
362 {
363 *res = NUL;
364 p = s;
365 while (*p != NUL)
366 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +0000367 if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000368 {
369 c = (*mb_ptr2char)(p);
370 if (vim_isprintc(c))
Bram Moolenaarc667da52019-11-30 20:52:27 +0100371 STRNCAT(res, p, l); // append printable multi-byte char
Bram Moolenaar071d4272004-06-13 20:20:40 +0000372 else
373 transchar_hex(res + STRLEN(res), c);
374 p += l;
375 }
376 else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000377 STRCAT(res, transchar_byte(*p++));
378 }
379 }
380 return res;
381}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000382
Bram Moolenaar071d4272004-06-13 20:20:40 +0000383/*
Bram Moolenaar217ad922005-03-20 22:37:15 +0000384 * Convert the string "str[orglen]" to do ignore-case comparing. Uses the
385 * current locale.
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000386 * When "buf" is NULL returns an allocated string (NULL for out-of-memory).
387 * Otherwise puts the result in "buf[buflen]".
Bram Moolenaar071d4272004-06-13 20:20:40 +0000388 */
389 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100390str_foldcase(
391 char_u *str,
392 int orglen,
393 char_u *buf,
394 int buflen)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000395{
396 garray_T ga;
397 int i;
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000398 int len = orglen;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000399
400#define GA_CHAR(i) ((char_u *)ga.ga_data)[i]
401#define GA_PTR(i) ((char_u *)ga.ga_data + i)
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000402#define STR_CHAR(i) (buf == NULL ? GA_CHAR(i) : buf[i])
403#define STR_PTR(i) (buf == NULL ? GA_PTR(i) : buf + i)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000404
Bram Moolenaarc667da52019-11-30 20:52:27 +0100405 // Copy "str" into "buf" or allocated memory, unmodified.
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000406 if (buf == NULL)
407 {
408 ga_init2(&ga, 1, 10);
409 if (ga_grow(&ga, len + 1) == FAIL)
410 return NULL;
411 mch_memmove(ga.ga_data, str, (size_t)len);
412 ga.ga_len = len;
413 }
414 else
415 {
Bram Moolenaarc667da52019-11-30 20:52:27 +0100416 if (len >= buflen) // Ugly!
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000417 len = buflen - 1;
418 mch_memmove(buf, str, (size_t)len);
419 }
420 if (buf == NULL)
421 GA_CHAR(len) = NUL;
422 else
423 buf[len] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000424
Bram Moolenaarc667da52019-11-30 20:52:27 +0100425 // Make each character lower case.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000426 i = 0;
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000427 while (STR_CHAR(i) != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000428 {
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000429 if (enc_utf8 || (has_mbyte && MB_BYTE2LEN(STR_CHAR(i)) > 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000430 {
431 if (enc_utf8)
432 {
Bram Moolenaarb9839212008-06-28 11:03:50 +0000433 int c = utf_ptr2char(STR_PTR(i));
Bram Moolenaar70b2a562012-01-10 22:26:17 +0100434 int olen = utf_ptr2len(STR_PTR(i));
Bram Moolenaarb9839212008-06-28 11:03:50 +0000435 int lc = utf_tolower(c);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000436
Bram Moolenaarc667da52019-11-30 20:52:27 +0100437 // Only replace the character when it is not an invalid
438 // sequence (ASCII character or more than one byte) and
439 // utf_tolower() doesn't return the original character.
Bram Moolenaar70b2a562012-01-10 22:26:17 +0100440 if ((c < 0x80 || olen > 1) && c != lc)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000441 {
Bram Moolenaar70b2a562012-01-10 22:26:17 +0100442 int nlen = utf_char2len(lc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000443
Bram Moolenaarc667da52019-11-30 20:52:27 +0100444 // If the byte length changes need to shift the following
445 // characters forward or backward.
Bram Moolenaar70b2a562012-01-10 22:26:17 +0100446 if (olen != nlen)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000447 {
Bram Moolenaar70b2a562012-01-10 22:26:17 +0100448 if (nlen > olen)
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000449 {
Bram Moolenaar70b2a562012-01-10 22:26:17 +0100450 if (buf == NULL
451 ? ga_grow(&ga, nlen - olen + 1) == FAIL
452 : len + nlen - olen >= buflen)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000453 {
Bram Moolenaarc667da52019-11-30 20:52:27 +0100454 // out of memory, keep old char
Bram Moolenaar071d4272004-06-13 20:20:40 +0000455 lc = c;
Bram Moolenaar70b2a562012-01-10 22:26:17 +0100456 nlen = olen;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000457 }
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000458 }
Bram Moolenaar70b2a562012-01-10 22:26:17 +0100459 if (olen != nlen)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000460 {
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000461 if (buf == NULL)
462 {
Bram Moolenaar70b2a562012-01-10 22:26:17 +0100463 STRMOVE(GA_PTR(i) + nlen, GA_PTR(i) + olen);
464 ga.ga_len += nlen - olen;
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000465 }
466 else
467 {
Bram Moolenaar70b2a562012-01-10 22:26:17 +0100468 STRMOVE(buf + i + nlen, buf + i + olen);
469 len += nlen - olen;
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000470 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000471 }
472 }
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000473 (void)utf_char2bytes(lc, STR_PTR(i));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000474 }
475 }
Bram Moolenaarc667da52019-11-30 20:52:27 +0100476 // skip to next multi-byte char
Bram Moolenaar0fa313a2005-08-10 21:07:57 +0000477 i += (*mb_ptr2len)(STR_PTR(i));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000478 }
479 else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000480 {
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000481 if (buf == NULL)
482 GA_CHAR(i) = TOLOWER_LOC(GA_CHAR(i));
483 else
484 buf[i] = TOLOWER_LOC(buf[i]);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000485 ++i;
486 }
487 }
488
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000489 if (buf == NULL)
490 return (char_u *)ga.ga_data;
491 return buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000492}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000493
494/*
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100495 * Catch 22: g_chartab[] can't be initialized before the options are
Bram Moolenaar071d4272004-06-13 20:20:40 +0000496 * initialized, and initializing options may cause transchar() to be called!
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100497 * When chartab_initialized == FALSE don't use g_chartab[].
Bram Moolenaar071d4272004-06-13 20:20:40 +0000498 * Does NOT work for multi-byte characters, c must be <= 255.
499 * Also doesn't work for the first byte of a multi-byte, "c" must be a
500 * character!
501 */
502static char_u transchar_buf[7];
503
504 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100505transchar(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000506{
507 int i;
508
509 i = 0;
Bram Moolenaarc667da52019-11-30 20:52:27 +0100510 if (IS_SPECIAL(c)) // special key code, display as ~@ char
Bram Moolenaar071d4272004-06-13 20:20:40 +0000511 {
512 transchar_buf[0] = '~';
513 transchar_buf[1] = '@';
514 i = 2;
515 c = K_SECOND(c);
516 }
517
518 if ((!chartab_initialized && (
519#ifdef EBCDIC
520 (c >= 64 && c < 255)
521#else
522 (c >= ' ' && c <= '~')
523#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000524 )) || (c < 256 && vim_isprintc_strict(c)))
525 {
Bram Moolenaarc667da52019-11-30 20:52:27 +0100526 // printable character
Bram Moolenaar071d4272004-06-13 20:20:40 +0000527 transchar_buf[i] = c;
528 transchar_buf[i + 1] = NUL;
529 }
530 else
531 transchar_nonprint(transchar_buf + i, c);
532 return transchar_buf;
533}
534
Bram Moolenaar071d4272004-06-13 20:20:40 +0000535/*
536 * Like transchar(), but called with a byte instead of a character. Checks
537 * for an illegal UTF-8 byte.
538 */
539 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +0100540transchar_byte(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000541{
542 if (enc_utf8 && c >= 0x80)
543 {
544 transchar_nonprint(transchar_buf, c);
545 return transchar_buf;
546 }
547 return transchar(c);
548}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000549
550/*
551 * Convert non-printable character to two or more printable characters in
552 * "buf[]". "buf" needs to be able to hold five bytes.
553 * Does NOT work for multi-byte characters, c must be <= 255.
554 */
555 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100556transchar_nonprint(char_u *buf, int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000557{
558 if (c == NL)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100559 c = NUL; // we use newline in place of a NUL
Bram Moolenaar071d4272004-06-13 20:20:40 +0000560 else if (c == CAR && get_fileformat(curbuf) == EOL_MAC)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100561 c = NL; // we use CR in place of NL in this case
Bram Moolenaar071d4272004-06-13 20:20:40 +0000562
Bram Moolenaarc667da52019-11-30 20:52:27 +0100563 if (dy_flags & DY_UHEX) // 'display' has "uhex"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000564 transchar_hex(buf, c);
565
566#ifdef EBCDIC
Bram Moolenaarc667da52019-11-30 20:52:27 +0100567 // For EBCDIC only the characters 0-63 and 255 are not printable
Bram Moolenaar071d4272004-06-13 20:20:40 +0000568 else if (CtrlChar(c) != 0 || c == DEL)
569#else
Bram Moolenaarc667da52019-11-30 20:52:27 +0100570 else if (c <= 0x7f) // 0x00 - 0x1f and 0x7f
Bram Moolenaar071d4272004-06-13 20:20:40 +0000571#endif
572 {
573 buf[0] = '^';
574#ifdef EBCDIC
575 if (c == DEL)
Bram Moolenaarc667da52019-11-30 20:52:27 +0100576 buf[1] = '?'; // DEL displayed as ^?
Bram Moolenaar071d4272004-06-13 20:20:40 +0000577 else
578 buf[1] = CtrlChar(c);
579#else
Bram Moolenaarc667da52019-11-30 20:52:27 +0100580 buf[1] = c ^ 0x40; // DEL displayed as ^?
Bram Moolenaar071d4272004-06-13 20:20:40 +0000581#endif
582
583 buf[2] = NUL;
584 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000585 else if (enc_utf8 && c >= 0x80)
586 {
587 transchar_hex(buf, c);
588 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000589#ifndef EBCDIC
Bram Moolenaarc667da52019-11-30 20:52:27 +0100590 else if (c >= ' ' + 0x80 && c <= '~' + 0x80) // 0xa0 - 0xfe
Bram Moolenaar071d4272004-06-13 20:20:40 +0000591 {
592 buf[0] = '|';
593 buf[1] = c - 0x80;
594 buf[2] = NUL;
595 }
596#else
597 else if (c < 64)
598 {
599 buf[0] = '~';
600 buf[1] = MetaChar(c);
601 buf[2] = NUL;
602 }
603#endif
Bram Moolenaarc667da52019-11-30 20:52:27 +0100604 else // 0x80 - 0x9f and 0xff
Bram Moolenaar071d4272004-06-13 20:20:40 +0000605 {
606 /*
607 * TODO: EBCDIC I don't know what to do with this chars, so I display
608 * them as '~?' for now
609 */
610 buf[0] = '~';
611#ifdef EBCDIC
Bram Moolenaarc667da52019-11-30 20:52:27 +0100612 buf[1] = '?'; // 0xff displayed as ~?
Bram Moolenaar071d4272004-06-13 20:20:40 +0000613#else
Bram Moolenaarc667da52019-11-30 20:52:27 +0100614 buf[1] = (c - 0x80) ^ 0x40; // 0xff displayed as ~?
Bram Moolenaar071d4272004-06-13 20:20:40 +0000615#endif
616 buf[2] = NUL;
617 }
618}
619
620 void
Bram Moolenaar7454a062016-01-30 15:14:10 +0100621transchar_hex(char_u *buf, int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000622{
623 int i = 0;
624
625 buf[0] = '<';
Bram Moolenaar071d4272004-06-13 20:20:40 +0000626 if (c > 255)
627 {
628 buf[++i] = nr2hex((unsigned)c >> 12);
629 buf[++i] = nr2hex((unsigned)c >> 8);
630 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000631 buf[++i] = nr2hex((unsigned)c >> 4);
Bram Moolenaar0ab2a882009-05-13 10:51:08 +0000632 buf[++i] = nr2hex((unsigned)c);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000633 buf[++i] = '>';
634 buf[++i] = NUL;
635}
636
637/*
638 * Convert the lower 4 bits of byte "c" to its hex character.
639 * Lower case letters are used to avoid the confusion of <F1> being 0xf1 or
640 * function key 1.
641 */
Bram Moolenaar0ab2a882009-05-13 10:51:08 +0000642 static unsigned
Bram Moolenaar7454a062016-01-30 15:14:10 +0100643nr2hex(unsigned c)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000644{
645 if ((c & 0xf) <= 9)
646 return (c & 0xf) + '0';
647 return (c & 0xf) - 10 + 'a';
648}
649
650/*
651 * Return number of display cells occupied by byte "b".
652 * Caller must make sure 0 <= b <= 255.
653 * For multi-byte mode "b" must be the first byte of a character.
654 * A TAB is counted as two cells: "^I".
655 * For UTF-8 mode this will return 0 for bytes >= 0x80, because the number of
656 * cells depends on further bytes.
657 */
658 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100659byte2cells(int b)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000660{
Bram Moolenaar071d4272004-06-13 20:20:40 +0000661 if (enc_utf8 && b >= 0x80)
662 return 0;
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100663 return (g_chartab[b] & CT_CELL_MASK);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000664}
665
666/*
667 * Return number of display cells occupied by character "c".
668 * "c" can be a special key (negative number) in which case 3 or 4 is returned.
669 * A TAB is counted as two cells: "^I" or four: "<09>".
670 */
671 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100672char2cells(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000673{
674 if (IS_SPECIAL(c))
675 return char2cells(K_SECOND(c)) + 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000676 if (c >= 0x80)
677 {
Bram Moolenaarc667da52019-11-30 20:52:27 +0100678 // UTF-8: above 0x80 need to check the value
Bram Moolenaar071d4272004-06-13 20:20:40 +0000679 if (enc_utf8)
680 return utf_char2cells(c);
Bram Moolenaarc667da52019-11-30 20:52:27 +0100681 // DBCS: double-byte means double-width, except for euc-jp with first
682 // byte 0x8e
Bram Moolenaar071d4272004-06-13 20:20:40 +0000683 if (enc_dbcs != 0 && c >= 0x100)
684 {
685 if (enc_dbcs == DBCS_JPNU && ((unsigned)c >> 8) == 0x8e)
686 return 1;
687 return 2;
688 }
689 }
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100690 return (g_chartab[c & 0xff] & CT_CELL_MASK);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000691}
692
693/*
694 * Return number of display cells occupied by character at "*p".
695 * A TAB is counted as two cells: "^I" or four: "<09>".
696 */
697 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100698ptr2cells(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000699{
Bram Moolenaarc667da52019-11-30 20:52:27 +0100700 // For UTF-8 we need to look at more bytes if the first byte is >= 0x80.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000701 if (enc_utf8 && *p >= 0x80)
702 return utf_ptr2cells(p);
Bram Moolenaarc667da52019-11-30 20:52:27 +0100703 // For DBCS we can tell the cell count from the first byte.
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100704 return (g_chartab[*p] & CT_CELL_MASK);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000705}
706
707/*
Bram Moolenaar06af6022012-01-26 13:40:08 +0100708 * Return the number of character cells string "s" will take on the screen,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000709 * counting TABs as two characters: "^I".
710 */
711 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100712vim_strsize(char_u *s)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000713{
714 return vim_strnsize(s, (int)MAXCOL);
715}
716
717/*
Bram Moolenaar06af6022012-01-26 13:40:08 +0100718 * Return the number of character cells string "s[len]" will take on the
719 * screen, counting TABs as two characters: "^I".
Bram Moolenaar071d4272004-06-13 20:20:40 +0000720 */
721 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100722vim_strnsize(char_u *s, int len)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000723{
724 int size = 0;
725
726 while (*s != NUL && --len >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000727 if (has_mbyte)
728 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +0000729 int l = (*mb_ptr2len)(s);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000730
731 size += ptr2cells(s);
732 s += l;
733 len -= l - 1;
734 }
735 else
Bram Moolenaar071d4272004-06-13 20:20:40 +0000736 size += byte2cells(*s++);
Bram Moolenaar13505972019-01-24 15:04:48 +0100737
Bram Moolenaar071d4272004-06-13 20:20:40 +0000738 return size;
739}
740
741/*
742 * Return the number of characters 'c' will take on the screen, taking
743 * into account the size of a tab.
744 * Use a define to make it fast, this is used very often!!!
745 * Also see getvcol() below.
746 */
747
Bram Moolenaar04958cb2018-06-23 19:23:02 +0200748#ifdef FEAT_VARTABS
749# define RET_WIN_BUF_CHARTABSIZE(wp, buf, p, col) \
750 if (*(p) == TAB && (!(wp)->w_p_list || lcs_tab1)) \
751 { \
752 return tabstop_padding(col, (buf)->b_p_ts, (buf)->b_p_vts_array); \
753 } \
754 else \
755 return ptr2cells(p);
756#else
757# define RET_WIN_BUF_CHARTABSIZE(wp, buf, p, col) \
Bram Moolenaar071d4272004-06-13 20:20:40 +0000758 if (*(p) == TAB && (!(wp)->w_p_list || lcs_tab1)) \
759 { \
760 int ts; \
761 ts = (buf)->b_p_ts; \
762 return (int)(ts - (col % ts)); \
763 } \
764 else \
765 return ptr2cells(p);
Bram Moolenaar04958cb2018-06-23 19:23:02 +0200766#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000767
Bram Moolenaar071d4272004-06-13 20:20:40 +0000768 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100769chartabsize(char_u *p, colnr_T col)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000770{
771 RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, p, col)
772}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000773
774#ifdef FEAT_LINEBREAK
775 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100776win_chartabsize(win_T *wp, char_u *p, colnr_T col)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000777{
778 RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, p, col)
779}
780#endif
781
782/*
Bram Moolenaardc536092010-07-18 15:45:49 +0200783 * Return the number of characters the string 's' will take on the screen,
784 * taking into account the size of a tab.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000785 */
786 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100787linetabsize(char_u *s)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000788{
Bram Moolenaardc536092010-07-18 15:45:49 +0200789 return linetabsize_col(0, s);
790}
791
792/*
793 * Like linetabsize(), but starting at column "startcol".
794 */
795 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100796linetabsize_col(int startcol, char_u *s)
Bram Moolenaardc536092010-07-18 15:45:49 +0200797{
798 colnr_T col = startcol;
Bram Moolenaarc667da52019-11-30 20:52:27 +0100799 char_u *line = s; // pointer to start of line, for breakindent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000800
801 while (*s != NUL)
Bram Moolenaar597a4222014-06-25 14:39:50 +0200802 col += lbr_chartabsize_adv(line, &s, col);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000803 return (int)col;
804}
805
806/*
807 * Like linetabsize(), but for a given window instead of the current one.
808 */
809 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100810win_linetabsize(win_T *wp, char_u *line, colnr_T len)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000811{
812 colnr_T col = 0;
813 char_u *s;
814
Bram Moolenaar597a4222014-06-25 14:39:50 +0200815 for (s = line; *s != NUL && (len == MAXCOL || s < line + len);
Bram Moolenaar91acfff2017-03-12 19:22:36 +0100816 MB_PTR_ADV(s))
Bram Moolenaar597a4222014-06-25 14:39:50 +0200817 col += win_lbr_chartabsize(wp, line, s, col, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000818 return (int)col;
819}
820
821/*
Bram Moolenaar81695252004-12-29 20:58:21 +0000822 * Return TRUE if 'c' is a normal identifier character:
823 * Letters and characters from the 'isident' option.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000824 */
825 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100826vim_isIDc(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000827{
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100828 return (c > 0 && c < 0x100 && (g_chartab[c] & CT_ID_CHAR));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000829}
830
831/*
832 * return TRUE if 'c' is a keyword character: Letters and characters from
Bram Moolenaarcaa55b62017-01-10 13:51:09 +0100833 * 'iskeyword' option for the current buffer.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000834 * For multi-byte characters mb_get_class() is used (builtin rules).
835 */
836 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100837vim_iswordc(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000838{
Bram Moolenaar9d182dd2013-01-23 15:53:15 +0100839 return vim_iswordc_buf(c, curbuf);
840}
841
842 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100843vim_iswordc_buf(int c, buf_T *buf)
Bram Moolenaar9d182dd2013-01-23 15:53:15 +0100844{
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845 if (c >= 0x100)
846 {
847 if (enc_dbcs != 0)
Bram Moolenaar0ab2a882009-05-13 10:51:08 +0000848 return dbcs_class((unsigned)c >> 8, (unsigned)(c & 0xff)) >= 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849 if (enc_utf8)
Bram Moolenaar4019cf92017-01-28 16:39:34 +0100850 return utf_class_buf(c, buf) >= 2;
Bram Moolenaar4019cf92017-01-28 16:39:34 +0100851 return FALSE;
852 }
853 return (c > 0 && GET_CHARTAB(buf, c) != 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000854}
855
856/*
857 * Just like vim_iswordc() but uses a pointer to the (multi-byte) character.
858 */
859 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100860vim_iswordp(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000861{
Bram Moolenaar4019cf92017-01-28 16:39:34 +0100862 return vim_iswordp_buf(p, curbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000863}
864
Bram Moolenaar071d4272004-06-13 20:20:40 +0000865 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100866vim_iswordp_buf(char_u *p, buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000867{
Bram Moolenaar4019cf92017-01-28 16:39:34 +0100868 int c = *p;
869
Bram Moolenaar4019cf92017-01-28 16:39:34 +0100870 if (has_mbyte && MB_BYTE2LEN(c) > 1)
871 c = (*mb_ptr2char)(p);
Bram Moolenaar4019cf92017-01-28 16:39:34 +0100872 return vim_iswordc_buf(c, buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000873}
Bram Moolenaar071d4272004-06-13 20:20:40 +0000874
875/*
876 * return TRUE if 'c' is a valid file-name character
877 * Assume characters above 0x100 are valid (multi-byte).
878 */
879 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100880vim_isfilec(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000881{
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100882 return (c >= 0x100 || (c > 0 && (g_chartab[c] & CT_FNAME_CHAR)));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000883}
884
885/*
Bram Moolenaardd87969c2007-08-21 13:07:12 +0000886 * return TRUE if 'c' is a valid file-name character or a wildcard character
887 * Assume characters above 0x100 are valid (multi-byte).
888 * Explicitly interpret ']' as a wildcard character as mch_has_wildcard("]")
889 * returns false.
890 */
891 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100892vim_isfilec_or_wc(int c)
Bram Moolenaardd87969c2007-08-21 13:07:12 +0000893{
894 char_u buf[2];
895
896 buf[0] = (char_u)c;
897 buf[1] = NUL;
898 return vim_isfilec(c) || c == ']' || mch_has_wildcard(buf);
899}
900
901/*
Bram Moolenaar3317d5e2017-04-08 19:12:06 +0200902 * Return TRUE if 'c' is a printable character.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000903 * Assume characters above 0x100 are printable (multi-byte), except for
904 * Unicode.
905 */
906 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100907vim_isprintc(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000908{
Bram Moolenaar071d4272004-06-13 20:20:40 +0000909 if (enc_utf8 && c >= 0x100)
910 return utf_printable(c);
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100911 return (c >= 0x100 || (c > 0 && (g_chartab[c] & CT_PRINT_CHAR)));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000912}
913
914/*
915 * Strict version of vim_isprintc(c), don't return TRUE if "c" is the head
916 * byte of a double-byte character.
917 */
918 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100919vim_isprintc_strict(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000920{
Bram Moolenaar071d4272004-06-13 20:20:40 +0000921 if (enc_dbcs != 0 && c < 0x100 && MB_BYTE2LEN(c) > 1)
922 return FALSE;
923 if (enc_utf8 && c >= 0x100)
924 return utf_printable(c);
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +0100925 return (c >= 0x100 || (c > 0 && (g_chartab[c] & CT_PRINT_CHAR)));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000926}
927
928/*
929 * like chartabsize(), but also check for line breaks on the screen
930 */
931 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100932lbr_chartabsize(
Bram Moolenaarc667da52019-11-30 20:52:27 +0100933 char_u *line UNUSED, // start of the line
Bram Moolenaar7454a062016-01-30 15:14:10 +0100934 unsigned char *s,
935 colnr_T col)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000936{
937#ifdef FEAT_LINEBREAK
Bram Moolenaaree857022019-11-09 23:26:40 +0100938 if (!curwin->w_p_lbr && *get_showbreak_value(curwin) == NUL
939 && !curwin->w_p_bri)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000940 {
941#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000942 if (curwin->w_p_wrap)
943 return win_nolbr_chartabsize(curwin, s, col, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000944 RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, s, col)
945#ifdef FEAT_LINEBREAK
946 }
Bram Moolenaar597a4222014-06-25 14:39:50 +0200947 return win_lbr_chartabsize(curwin, line == NULL ? s : line, s, col, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000948#endif
949}
950
951/*
952 * Call lbr_chartabsize() and advance the pointer.
953 */
954 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100955lbr_chartabsize_adv(
Bram Moolenaarc667da52019-11-30 20:52:27 +0100956 char_u *line, // start of the line
Bram Moolenaar7454a062016-01-30 15:14:10 +0100957 char_u **s,
958 colnr_T col)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000959{
960 int retval;
961
Bram Moolenaar597a4222014-06-25 14:39:50 +0200962 retval = lbr_chartabsize(line, *s, col);
Bram Moolenaar91acfff2017-03-12 19:22:36 +0100963 MB_PTR_ADV(*s);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000964 return retval;
965}
966
967/*
968 * This function is used very often, keep it fast!!!!
969 *
970 * If "headp" not NULL, set *headp to the size of what we for 'showbreak'
971 * string at start of line. Warning: *headp is only set if it's a non-zero
972 * value, init to 0 before calling.
973 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000974 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100975win_lbr_chartabsize(
976 win_T *wp,
Bram Moolenaarc667da52019-11-30 20:52:27 +0100977 char_u *line UNUSED, // start of the line
Bram Moolenaar7454a062016-01-30 15:14:10 +0100978 char_u *s,
979 colnr_T col,
980 int *headp UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000981{
982#ifdef FEAT_LINEBREAK
983 int c;
984 int size;
985 colnr_T col2;
Bram Moolenaarc667da52019-11-30 20:52:27 +0100986 colnr_T col_adj = 0; // col + screen size of tab
Bram Moolenaar071d4272004-06-13 20:20:40 +0000987 colnr_T colmax;
988 int added;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000989 int mb_added = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000990 int numberextra;
991 char_u *ps;
992 int tab_corr = (*s == TAB);
Bram Moolenaar402d2fe2005-04-15 21:00:38 +0000993 int n;
Bram Moolenaaree857022019-11-09 23:26:40 +0100994 char_u *sbr;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000995
996 /*
Bram Moolenaar597a4222014-06-25 14:39:50 +0200997 * No 'linebreak', 'showbreak' and 'breakindent': return quickly.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000998 */
Bram Moolenaaree857022019-11-09 23:26:40 +0100999 if (!wp->w_p_lbr && !wp->w_p_bri && *get_showbreak_value(wp) == NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001000#endif
1001 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001002 if (wp->w_p_wrap)
1003 return win_nolbr_chartabsize(wp, s, col, headp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001004 RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, s, col)
1005 }
1006
1007#ifdef FEAT_LINEBREAK
1008 /*
1009 * First get normal size, without 'linebreak'
1010 */
1011 size = win_chartabsize(wp, s, col);
1012 c = *s;
Bram Moolenaaree739b42014-07-02 19:37:42 +02001013 if (tab_corr)
1014 col_adj = size - 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001015
1016 /*
1017 * If 'linebreak' set check at a blank before a non-blank if the line
1018 * needs a break here
1019 */
1020 if (wp->w_p_lbr
Bram Moolenaar91acfff2017-03-12 19:22:36 +01001021 && VIM_ISBREAK(c)
Bram Moolenaar977d0372017-03-12 21:31:58 +01001022 && !VIM_ISBREAK((int)s[1])
Bram Moolenaar071d4272004-06-13 20:20:40 +00001023 && wp->w_p_wrap
Bram Moolenaar4033c552017-09-16 20:54:51 +02001024 && wp->w_width != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001025 {
1026 /*
1027 * Count all characters from first non-blank after a blank up to next
1028 * non-blank after a blank.
1029 */
1030 numberextra = win_col_off(wp);
1031 col2 = col;
Bram Moolenaar02631462017-09-22 15:20:32 +02001032 colmax = (colnr_T)(wp->w_width - numberextra - col_adj);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001033 if (col >= colmax)
Bram Moolenaar402d2fe2005-04-15 21:00:38 +00001034 {
Bram Moolenaaree739b42014-07-02 19:37:42 +02001035 colmax += col_adj;
1036 n = colmax + win_col_off2(wp);
Bram Moolenaar402d2fe2005-04-15 21:00:38 +00001037 if (n > 0)
Bram Moolenaaree739b42014-07-02 19:37:42 +02001038 colmax += (((col - colmax) / n) + 1) * n - col_adj;
Bram Moolenaar402d2fe2005-04-15 21:00:38 +00001039 }
1040
Bram Moolenaar071d4272004-06-13 20:20:40 +00001041 for (;;)
1042 {
1043 ps = s;
Bram Moolenaar91acfff2017-03-12 19:22:36 +01001044 MB_PTR_ADV(s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001045 c = *s;
1046 if (!(c != NUL
Bram Moolenaar91acfff2017-03-12 19:22:36 +01001047 && (VIM_ISBREAK(c)
1048 || (!VIM_ISBREAK(c)
Bram Moolenaar977d0372017-03-12 21:31:58 +01001049 && (col2 == col || !VIM_ISBREAK((int)*ps))))))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001050 break;
1051
1052 col2 += win_chartabsize(wp, s, col2);
Bram Moolenaarc667da52019-11-30 20:52:27 +01001053 if (col2 >= colmax) // doesn't fit
Bram Moolenaar071d4272004-06-13 20:20:40 +00001054 {
Bram Moolenaaree739b42014-07-02 19:37:42 +02001055 size = colmax - col + col_adj;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001056 break;
1057 }
1058 }
1059 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001060 else if (has_mbyte && size == 2 && MB_BYTE2LEN(*s) > 1
1061 && wp->w_p_wrap && in_win_border(wp, col))
1062 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001063 ++size; // Count the ">" in the last column.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001064 mb_added = 1;
1065 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001066
1067 /*
Bram Moolenaar597a4222014-06-25 14:39:50 +02001068 * May have to add something for 'breakindent' and/or 'showbreak'
1069 * string at start of line.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001070 * Set *headp to the size of what we add.
1071 */
1072 added = 0;
Bram Moolenaaree857022019-11-09 23:26:40 +01001073 sbr = get_showbreak_value(wp);
1074 if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && col != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001075 {
Bram Moolenaard574ea22015-01-14 19:35:14 +01001076 colnr_T sbrlen = 0;
1077 int numberwidth = win_col_off(wp);
1078
1079 numberextra = numberwidth;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001080 col += numberextra + mb_added;
Bram Moolenaar02631462017-09-22 15:20:32 +02001081 if (col >= (colnr_T)wp->w_width)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001082 {
Bram Moolenaar02631462017-09-22 15:20:32 +02001083 col -= wp->w_width;
1084 numberextra = wp->w_width - (numberextra - win_col_off2(wp));
Bram Moolenaard574ea22015-01-14 19:35:14 +01001085 if (col >= numberextra && numberextra > 0)
Bram Moolenaarfe3c4102014-10-31 12:42:01 +01001086 col %= numberextra;
Bram Moolenaaree857022019-11-09 23:26:40 +01001087 if (*sbr != NUL)
Bram Moolenaar1c852102014-10-15 21:26:40 +02001088 {
Bram Moolenaaree857022019-11-09 23:26:40 +01001089 sbrlen = (colnr_T)MB_CHARLEN(sbr);
Bram Moolenaar1c852102014-10-15 21:26:40 +02001090 if (col >= sbrlen)
1091 col -= sbrlen;
1092 }
Bram Moolenaard574ea22015-01-14 19:35:14 +01001093 if (col >= numberextra && numberextra > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001094 col = col % numberextra;
Bram Moolenaard574ea22015-01-14 19:35:14 +01001095 else if (col > 0 && numberextra > 0)
1096 col += numberwidth - win_col_off2(wp);
1097
1098 numberwidth -= win_col_off2(wp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001099 }
Bram Moolenaar02631462017-09-22 15:20:32 +02001100 if (col == 0 || col + size + sbrlen > (colnr_T)wp->w_width)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001101 {
Bram Moolenaar597a4222014-06-25 14:39:50 +02001102 added = 0;
Bram Moolenaaree857022019-11-09 23:26:40 +01001103 if (*sbr != NUL)
Bram Moolenaard574ea22015-01-14 19:35:14 +01001104 {
Bram Moolenaar02631462017-09-22 15:20:32 +02001105 if (size + sbrlen + numberwidth > (colnr_T)wp->w_width)
Bram Moolenaard574ea22015-01-14 19:35:14 +01001106 {
Bram Moolenaar7833dab2019-05-27 22:01:40 +02001107 // calculate effective window width
Bram Moolenaar02631462017-09-22 15:20:32 +02001108 int width = (colnr_T)wp->w_width - sbrlen - numberwidth;
Bram Moolenaar2c519cf2019-03-21 21:45:34 +01001109 int prev_width = col
1110 ? ((colnr_T)wp->w_width - (sbrlen + col)) : 0;
Bram Moolenaar7833dab2019-05-27 22:01:40 +02001111
1112 if (width <= 0)
1113 width = (colnr_T)1;
Bram Moolenaaree857022019-11-09 23:26:40 +01001114 added += ((size - prev_width) / width) * vim_strsize(sbr);
Bram Moolenaard574ea22015-01-14 19:35:14 +01001115 if ((size - prev_width) % width)
Bram Moolenaar7833dab2019-05-27 22:01:40 +02001116 // wrapped, add another length of 'sbr'
Bram Moolenaaree857022019-11-09 23:26:40 +01001117 added += vim_strsize(sbr);
Bram Moolenaard574ea22015-01-14 19:35:14 +01001118 }
1119 else
Bram Moolenaaree857022019-11-09 23:26:40 +01001120 added += vim_strsize(sbr);
Bram Moolenaard574ea22015-01-14 19:35:14 +01001121 }
Bram Moolenaar597a4222014-06-25 14:39:50 +02001122 if (wp->w_p_bri)
1123 added += get_breakindent_win(wp, line);
1124
Bram Moolenaar95765082014-08-24 21:19:25 +02001125 size += added;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001126 if (col != 0)
1127 added = 0;
1128 }
1129 }
1130 if (headp != NULL)
1131 *headp = added + mb_added;
1132 return size;
1133#endif
1134}
1135
Bram Moolenaar071d4272004-06-13 20:20:40 +00001136/*
1137 * Like win_lbr_chartabsize(), except that we know 'linebreak' is off and
1138 * 'wrap' is on. This means we need to check for a double-byte character that
1139 * doesn't fit at the end of the screen line.
1140 */
1141 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001142win_nolbr_chartabsize(
1143 win_T *wp,
1144 char_u *s,
1145 colnr_T col,
1146 int *headp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001147{
1148 int n;
1149
1150 if (*s == TAB && (!wp->w_p_list || lcs_tab1))
1151 {
Bram Moolenaar04958cb2018-06-23 19:23:02 +02001152# ifdef FEAT_VARTABS
1153 return tabstop_padding(col, wp->w_buffer->b_p_ts,
1154 wp->w_buffer->b_p_vts_array);
1155# else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001156 n = wp->w_buffer->b_p_ts;
1157 return (int)(n - (col % n));
Bram Moolenaar04958cb2018-06-23 19:23:02 +02001158# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001159 }
1160 n = ptr2cells(s);
Bram Moolenaarc667da52019-11-30 20:52:27 +01001161 // Add one cell for a double-width character in the last column of the
1162 // window, displayed with a ">".
Bram Moolenaar071d4272004-06-13 20:20:40 +00001163 if (n == 2 && MB_BYTE2LEN(*s) > 1 && in_win_border(wp, col))
1164 {
1165 if (headp != NULL)
1166 *headp = 1;
1167 return 3;
1168 }
1169 return n;
1170}
1171
1172/*
1173 * Return TRUE if virtual column "vcol" is in the rightmost column of window
1174 * "wp".
1175 */
Bram Moolenaar5843f5f2019-08-20 20:13:45 +02001176 static int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001177in_win_border(win_T *wp, colnr_T vcol)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001178{
Bram Moolenaarc667da52019-11-30 20:52:27 +01001179 int width1; // width of first line (after line number)
1180 int width2; // width of further lines
Bram Moolenaar071d4272004-06-13 20:20:40 +00001181
Bram Moolenaarc667da52019-11-30 20:52:27 +01001182 if (wp->w_width == 0) // there is no border
Bram Moolenaar071d4272004-06-13 20:20:40 +00001183 return FALSE;
Bram Moolenaar02631462017-09-22 15:20:32 +02001184 width1 = wp->w_width - win_col_off(wp);
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001185 if ((int)vcol < width1 - 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001186 return FALSE;
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001187 if ((int)vcol == width1 - 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001188 return TRUE;
1189 width2 = width1 + win_col_off2(wp);
Bram Moolenaar8701cd62009-10-07 14:20:30 +00001190 if (width2 <= 0)
1191 return FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001192 return ((vcol - width1) % width2 == width2 - 1);
1193}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001194
1195/*
1196 * Get virtual column number of pos.
1197 * start: on the first position of this character (TAB, ctrl)
1198 * cursor: where the cursor is on this character (first char, except for TAB)
1199 * end: on the last position of this character (TAB, ctrl)
1200 *
1201 * This is used very often, keep it fast!
1202 */
1203 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001204getvcol(
1205 win_T *wp,
1206 pos_T *pos,
1207 colnr_T *start,
1208 colnr_T *cursor,
1209 colnr_T *end)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001210{
1211 colnr_T vcol;
Bram Moolenaarc667da52019-11-30 20:52:27 +01001212 char_u *ptr; // points to current char
1213 char_u *posptr; // points to char at pos->col
1214 char_u *line; // start of the line
Bram Moolenaar071d4272004-06-13 20:20:40 +00001215 int incr;
1216 int head;
Bram Moolenaar04958cb2018-06-23 19:23:02 +02001217#ifdef FEAT_VARTABS
1218 int *vts = wp->w_buffer->b_p_vts_array;
1219#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001220 int ts = wp->w_buffer->b_p_ts;
1221 int c;
1222
1223 vcol = 0;
Bram Moolenaar597a4222014-06-25 14:39:50 +02001224 line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
Bram Moolenaar37d619f2010-03-10 14:46:26 +01001225 if (pos->col == MAXCOL)
Bram Moolenaarc667da52019-11-30 20:52:27 +01001226 posptr = NULL; // continue until the NUL
Bram Moolenaar37d619f2010-03-10 14:46:26 +01001227 else
Bram Moolenaar0c0590d2017-01-28 13:48:10 +01001228 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001229 // Special check for an empty line, which can happen on exit, when
1230 // ml_get_buf() always returns an empty string.
Bram Moolenaar955f1982017-02-05 15:10:51 +01001231 if (*ptr == NUL)
1232 pos->col = 0;
Bram Moolenaar37d619f2010-03-10 14:46:26 +01001233 posptr = ptr + pos->col;
Bram Moolenaar0c0590d2017-01-28 13:48:10 +01001234 if (has_mbyte)
Bram Moolenaarc667da52019-11-30 20:52:27 +01001235 // always start on the first byte
Bram Moolenaar0c0590d2017-01-28 13:48:10 +01001236 posptr -= (*mb_head_off)(line, posptr);
Bram Moolenaar0c0590d2017-01-28 13:48:10 +01001237 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001238
1239 /*
1240 * This function is used very often, do some speed optimizations.
Bram Moolenaar597a4222014-06-25 14:39:50 +02001241 * When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set
1242 * use a simple loop.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001243 * Also use this when 'list' is set but tabs take their normal size.
1244 */
1245 if ((!wp->w_p_list || lcs_tab1 != NUL)
1246#ifdef FEAT_LINEBREAK
Bram Moolenaaree857022019-11-09 23:26:40 +01001247 && !wp->w_p_lbr && *get_showbreak_value(wp) == NUL && !wp->w_p_bri
Bram Moolenaar071d4272004-06-13 20:20:40 +00001248#endif
1249 )
1250 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001251 for (;;)
1252 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001253 head = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001254 c = *ptr;
Bram Moolenaarc667da52019-11-30 20:52:27 +01001255 // make sure we don't go past the end of the line
Bram Moolenaar071d4272004-06-13 20:20:40 +00001256 if (c == NUL)
1257 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001258 incr = 1; // NUL at end of line only takes one column
Bram Moolenaar071d4272004-06-13 20:20:40 +00001259 break;
1260 }
Bram Moolenaarc667da52019-11-30 20:52:27 +01001261 // A tab gets expanded, depending on the current column
Bram Moolenaar071d4272004-06-13 20:20:40 +00001262 if (c == TAB)
Bram Moolenaar04958cb2018-06-23 19:23:02 +02001263#ifdef FEAT_VARTABS
1264 incr = tabstop_padding(vcol, ts, vts);
1265#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001266 incr = ts - (vcol % ts);
Bram Moolenaar04958cb2018-06-23 19:23:02 +02001267#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001268 else
1269 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001270 if (has_mbyte)
1271 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001272 // For utf-8, if the byte is >= 0x80, need to look at
1273 // further bytes to find the cell width.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001274 if (enc_utf8 && c >= 0x80)
1275 incr = utf_ptr2cells(ptr);
1276 else
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +01001277 incr = g_chartab[c] & CT_CELL_MASK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001278
Bram Moolenaarc667da52019-11-30 20:52:27 +01001279 // If a double-cell char doesn't fit at the end of a line
1280 // it wraps to the next line, it's like this char is three
1281 // cells wide.
Bram Moolenaar9c33a7c2008-02-20 13:59:32 +00001282 if (incr == 2 && wp->w_p_wrap && MB_BYTE2LEN(*ptr) > 1
1283 && in_win_border(wp, vcol))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001284 {
1285 ++incr;
1286 head = 1;
1287 }
1288 }
1289 else
Bram Moolenaar88e8f9f2016-01-20 22:48:02 +01001290 incr = g_chartab[c] & CT_CELL_MASK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001291 }
1292
Bram Moolenaarc667da52019-11-30 20:52:27 +01001293 if (posptr != NULL && ptr >= posptr) // character at pos->col
Bram Moolenaar071d4272004-06-13 20:20:40 +00001294 break;
1295
1296 vcol += incr;
Bram Moolenaar91acfff2017-03-12 19:22:36 +01001297 MB_PTR_ADV(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001298 }
1299 }
1300 else
1301 {
1302 for (;;)
1303 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001304 // A tab gets expanded, depending on the current column
Bram Moolenaar071d4272004-06-13 20:20:40 +00001305 head = 0;
Bram Moolenaar597a4222014-06-25 14:39:50 +02001306 incr = win_lbr_chartabsize(wp, line, ptr, vcol, &head);
Bram Moolenaarc667da52019-11-30 20:52:27 +01001307 // make sure we don't go past the end of the line
Bram Moolenaar071d4272004-06-13 20:20:40 +00001308 if (*ptr == NUL)
1309 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001310 incr = 1; // NUL at end of line only takes one column
Bram Moolenaar071d4272004-06-13 20:20:40 +00001311 break;
1312 }
1313
Bram Moolenaarc667da52019-11-30 20:52:27 +01001314 if (posptr != NULL && ptr >= posptr) // character at pos->col
Bram Moolenaar071d4272004-06-13 20:20:40 +00001315 break;
1316
1317 vcol += incr;
Bram Moolenaar91acfff2017-03-12 19:22:36 +01001318 MB_PTR_ADV(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001319 }
1320 }
1321 if (start != NULL)
1322 *start = vcol + head;
1323 if (end != NULL)
1324 *end = vcol + incr - 1;
1325 if (cursor != NULL)
1326 {
1327 if (*ptr == TAB
1328 && (State & NORMAL)
1329 && !wp->w_p_list
1330 && !virtual_active()
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01001331 && !(VIsual_active
1332 && (*p_sel == 'e' || LTOREQ_POS(*pos, VIsual)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001333 )
Bram Moolenaarc667da52019-11-30 20:52:27 +01001334 *cursor = vcol + incr - 1; // cursor at end
Bram Moolenaar071d4272004-06-13 20:20:40 +00001335 else
Bram Moolenaarc667da52019-11-30 20:52:27 +01001336 *cursor = vcol + head; // cursor at start
Bram Moolenaar071d4272004-06-13 20:20:40 +00001337 }
1338}
1339
1340/*
1341 * Get virtual cursor column in the current window, pretending 'list' is off.
1342 */
1343 colnr_T
Bram Moolenaar7454a062016-01-30 15:14:10 +01001344getvcol_nolist(pos_T *posp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001345{
1346 int list_save = curwin->w_p_list;
1347 colnr_T vcol;
1348
1349 curwin->w_p_list = FALSE;
Bram Moolenaardb0eede2018-04-25 22:38:17 +02001350 if (posp->coladd)
1351 getvvcol(curwin, posp, NULL, &vcol, NULL);
1352 else
Bram Moolenaardb0eede2018-04-25 22:38:17 +02001353 getvcol(curwin, posp, NULL, &vcol, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001354 curwin->w_p_list = list_save;
1355 return vcol;
1356}
1357
Bram Moolenaar071d4272004-06-13 20:20:40 +00001358/*
1359 * Get virtual column in virtual mode.
1360 */
1361 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001362getvvcol(
1363 win_T *wp,
1364 pos_T *pos,
1365 colnr_T *start,
1366 colnr_T *cursor,
1367 colnr_T *end)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001368{
1369 colnr_T col;
1370 colnr_T coladd;
1371 colnr_T endadd;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001372 char_u *ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001373
1374 if (virtual_active())
1375 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001376 // For virtual mode, only want one value
Bram Moolenaar071d4272004-06-13 20:20:40 +00001377 getvcol(wp, pos, &col, NULL, NULL);
1378
1379 coladd = pos->coladd;
1380 endadd = 0;
Bram Moolenaarc667da52019-11-30 20:52:27 +01001381 // Cannot put the cursor on part of a wide character.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001382 ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001383 if (pos->col < (colnr_T)STRLEN(ptr))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001384 {
1385 int c = (*mb_ptr2char)(ptr + pos->col);
1386
1387 if (c != TAB && vim_isprintc(c))
1388 {
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001389 endadd = (colnr_T)(char2cells(c) - 1);
Bram Moolenaarc667da52019-11-30 20:52:27 +01001390 if (coladd > endadd) // past end of line
Bram Moolenaara5792f52005-11-23 21:25:05 +00001391 endadd = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001392 else
1393 coladd = 0;
1394 }
1395 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001396 col += coladd;
1397 if (start != NULL)
1398 *start = col;
1399 if (cursor != NULL)
1400 *cursor = col;
1401 if (end != NULL)
1402 *end = col + endadd;
1403 }
1404 else
1405 getvcol(wp, pos, start, cursor, end);
1406}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001407
Bram Moolenaar071d4272004-06-13 20:20:40 +00001408/*
1409 * Get the leftmost and rightmost virtual column of pos1 and pos2.
1410 * Used for Visual block mode.
1411 */
1412 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001413getvcols(
1414 win_T *wp,
1415 pos_T *pos1,
1416 pos_T *pos2,
1417 colnr_T *left,
1418 colnr_T *right)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001419{
1420 colnr_T from1, from2, to1, to2;
1421
Bram Moolenaarb5aedf32017-03-12 18:23:53 +01001422 if (LT_POSP(pos1, pos2))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001423 {
1424 getvvcol(wp, pos1, &from1, NULL, &to1);
1425 getvvcol(wp, pos2, &from2, NULL, &to2);
1426 }
1427 else
1428 {
1429 getvvcol(wp, pos2, &from1, NULL, &to1);
1430 getvvcol(wp, pos1, &from2, NULL, &to2);
1431 }
1432 if (from2 < from1)
1433 *left = from2;
1434 else
1435 *left = from1;
1436 if (to2 > to1)
1437 {
1438 if (*p_sel == 'e' && from2 - 1 >= to1)
1439 *right = from2 - 1;
1440 else
1441 *right = to2;
1442 }
1443 else
1444 *right = to1;
1445}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001446
1447/*
1448 * skipwhite: skip over ' ' and '\t'.
1449 */
1450 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001451skipwhite(char_u *q)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001452{
Bram Moolenaar1387a602008-07-24 19:31:11 +00001453 char_u *p = q;
1454
Bram Moolenaarc667da52019-11-30 20:52:27 +01001455 while (VIM_ISWHITE(*p)) // skip to next non-white
Bram Moolenaar071d4272004-06-13 20:20:40 +00001456 ++p;
1457 return p;
1458}
1459
1460/*
Bram Moolenaare2e69e42017-09-02 20:30:35 +02001461 * getwhitecols: return the number of whitespace
1462 * columns (bytes) at the start of a given line
1463 */
1464 int
1465getwhitecols_curline()
1466{
1467 return getwhitecols(ml_get_curline());
1468}
1469
1470 int
1471getwhitecols(char_u *p)
1472{
1473 return skipwhite(p) - p;
1474}
1475
1476/*
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001477 * skip over digits
Bram Moolenaar071d4272004-06-13 20:20:40 +00001478 */
1479 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001480skipdigits(char_u *q)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001481{
Bram Moolenaar1387a602008-07-24 19:31:11 +00001482 char_u *p = q;
1483
Bram Moolenaarc667da52019-11-30 20:52:27 +01001484 while (VIM_ISDIGIT(*p)) // skip to next non-digit
Bram Moolenaar071d4272004-06-13 20:20:40 +00001485 ++p;
1486 return p;
1487}
1488
Bram Moolenaarc4956c82006-03-12 21:58:43 +00001489#if defined(FEAT_SYN_HL) || defined(FEAT_SPELL) || defined(PROTO)
Bram Moolenaar75c50c42005-06-04 22:06:24 +00001490/*
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001491 * skip over binary digits
1492 */
1493 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001494skipbin(char_u *q)
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001495{
1496 char_u *p = q;
1497
Bram Moolenaarc667da52019-11-30 20:52:27 +01001498 while (vim_isbdigit(*p)) // skip to next non-digit
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001499 ++p;
1500 return p;
1501}
1502
1503/*
Bram Moolenaar75c50c42005-06-04 22:06:24 +00001504 * skip over digits and hex characters
1505 */
1506 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001507skiphex(char_u *q)
Bram Moolenaar75c50c42005-06-04 22:06:24 +00001508{
Bram Moolenaar1387a602008-07-24 19:31:11 +00001509 char_u *p = q;
1510
Bram Moolenaarc667da52019-11-30 20:52:27 +01001511 while (vim_isxdigit(*p)) // skip to next non-digit
Bram Moolenaar75c50c42005-06-04 22:06:24 +00001512 ++p;
1513 return p;
1514}
1515#endif
1516
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001517/*
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001518 * skip to bin digit (or NUL after the string)
1519 */
1520 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001521skiptobin(char_u *q)
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001522{
1523 char_u *p = q;
1524
Bram Moolenaarc667da52019-11-30 20:52:27 +01001525 while (*p != NUL && !vim_isbdigit(*p)) // skip to next digit
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001526 ++p;
1527 return p;
1528}
1529
1530/*
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001531 * skip to digit (or NUL after the string)
1532 */
1533 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001534skiptodigit(char_u *q)
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001535{
Bram Moolenaar1387a602008-07-24 19:31:11 +00001536 char_u *p = q;
1537
Bram Moolenaarc667da52019-11-30 20:52:27 +01001538 while (*p != NUL && !VIM_ISDIGIT(*p)) // skip to next digit
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001539 ++p;
1540 return p;
1541}
1542
1543/*
1544 * skip to hex character (or NUL after the string)
1545 */
1546 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001547skiptohex(char_u *q)
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001548{
Bram Moolenaar1387a602008-07-24 19:31:11 +00001549 char_u *p = q;
1550
Bram Moolenaarc667da52019-11-30 20:52:27 +01001551 while (*p != NUL && !vim_isxdigit(*p)) // skip to next digit
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001552 ++p;
1553 return p;
1554}
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001555
Bram Moolenaar071d4272004-06-13 20:20:40 +00001556/*
1557 * Variant of isdigit() that can handle characters > 0x100.
1558 * We don't use isdigit() here, because on some systems it also considers
1559 * superscript 1 to be a digit.
1560 * Use the VIM_ISDIGIT() macro for simple arguments.
1561 */
1562 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001563vim_isdigit(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001564{
1565 return (c >= '0' && c <= '9');
1566}
1567
1568/*
1569 * Variant of isxdigit() that can handle characters > 0x100.
1570 * We don't use isxdigit() here, because on some systems it also considers
1571 * superscript 1 to be a digit.
1572 */
1573 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001574vim_isxdigit(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001575{
1576 return (c >= '0' && c <= '9')
1577 || (c >= 'a' && c <= 'f')
1578 || (c >= 'A' && c <= 'F');
1579}
1580
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001581/*
1582 * Corollary of vim_isdigit and vim_isxdigit() that can handle
1583 * characters > 0x100.
1584 */
1585 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001586vim_isbdigit(int c)
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001587{
1588 return (c == '0' || c == '1');
1589}
1590
Bram Moolenaar78622822005-08-23 21:00:13 +00001591/*
1592 * Vim's own character class functions. These exist because many library
1593 * islower()/toupper() etc. do not work properly: they crash when used with
1594 * invalid values or can't handle latin1 when the locale is C.
1595 * Speed is most important here.
1596 */
1597#define LATIN1LOWER 'l'
1598#define LATIN1UPPER 'U'
1599
Bram Moolenaar6e7c7f32005-08-24 22:16:11 +00001600static char_u latin1flags[257] = " UUUUUUUUUUUUUUUUUUUUUUUUUU llllllllllllllllllllllllll UUUUUUUUUUUUUUUUUUUUUUU UUUUUUUllllllllllllllllllllllll llllllll";
Bram Moolenaar936347b2012-05-25 11:56:22 +02001601static char_u latin1upper[257] = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xf7\xd8\xd9\xda\xdb\xdc\xdd\xde\xff";
1602static char_u latin1lower[257] = " !\"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xd7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
Bram Moolenaar78622822005-08-23 21:00:13 +00001603
1604 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001605vim_islower(int c)
Bram Moolenaar78622822005-08-23 21:00:13 +00001606{
1607 if (c <= '@')
1608 return FALSE;
1609 if (c >= 0x80)
1610 {
1611 if (enc_utf8)
1612 return utf_islower(c);
1613 if (c >= 0x100)
1614 {
1615#ifdef HAVE_ISWLOWER
1616 if (has_mbyte)
1617 return iswlower(c);
1618#endif
Bram Moolenaarc667da52019-11-30 20:52:27 +01001619 // islower() can't handle these chars and may crash
Bram Moolenaar78622822005-08-23 21:00:13 +00001620 return FALSE;
1621 }
1622 if (enc_latin1like)
1623 return (latin1flags[c] & LATIN1LOWER) == LATIN1LOWER;
1624 }
1625 return islower(c);
1626}
1627
1628 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001629vim_isupper(int c)
Bram Moolenaar78622822005-08-23 21:00:13 +00001630{
1631 if (c <= '@')
1632 return FALSE;
1633 if (c >= 0x80)
1634 {
1635 if (enc_utf8)
1636 return utf_isupper(c);
1637 if (c >= 0x100)
1638 {
1639#ifdef HAVE_ISWUPPER
1640 if (has_mbyte)
1641 return iswupper(c);
1642#endif
Bram Moolenaarc667da52019-11-30 20:52:27 +01001643 // islower() can't handle these chars and may crash
Bram Moolenaar78622822005-08-23 21:00:13 +00001644 return FALSE;
1645 }
1646 if (enc_latin1like)
1647 return (latin1flags[c] & LATIN1UPPER) == LATIN1UPPER;
1648 }
1649 return isupper(c);
1650}
1651
1652 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001653vim_toupper(int c)
Bram Moolenaar78622822005-08-23 21:00:13 +00001654{
1655 if (c <= '@')
1656 return c;
Bram Moolenaar3317d5e2017-04-08 19:12:06 +02001657 if (c >= 0x80 || !(cmp_flags & CMP_KEEPASCII))
Bram Moolenaar78622822005-08-23 21:00:13 +00001658 {
1659 if (enc_utf8)
1660 return utf_toupper(c);
1661 if (c >= 0x100)
1662 {
1663#ifdef HAVE_TOWUPPER
1664 if (has_mbyte)
1665 return towupper(c);
1666#endif
Bram Moolenaarc667da52019-11-30 20:52:27 +01001667 // toupper() can't handle these chars and may crash
Bram Moolenaar78622822005-08-23 21:00:13 +00001668 return c;
1669 }
1670 if (enc_latin1like)
1671 return latin1upper[c];
1672 }
Bram Moolenaar1cc48202017-04-09 13:41:59 +02001673 if (c < 0x80 && (cmp_flags & CMP_KEEPASCII))
1674 return TOUPPER_ASC(c);
Bram Moolenaar78622822005-08-23 21:00:13 +00001675 return TOUPPER_LOC(c);
1676}
1677
1678 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001679vim_tolower(int c)
Bram Moolenaar78622822005-08-23 21:00:13 +00001680{
1681 if (c <= '@')
1682 return c;
Bram Moolenaar3317d5e2017-04-08 19:12:06 +02001683 if (c >= 0x80 || !(cmp_flags & CMP_KEEPASCII))
Bram Moolenaar78622822005-08-23 21:00:13 +00001684 {
1685 if (enc_utf8)
1686 return utf_tolower(c);
1687 if (c >= 0x100)
1688 {
1689#ifdef HAVE_TOWLOWER
1690 if (has_mbyte)
1691 return towlower(c);
1692#endif
Bram Moolenaarc667da52019-11-30 20:52:27 +01001693 // tolower() can't handle these chars and may crash
Bram Moolenaar78622822005-08-23 21:00:13 +00001694 return c;
1695 }
1696 if (enc_latin1like)
1697 return latin1lower[c];
1698 }
Bram Moolenaar1cc48202017-04-09 13:41:59 +02001699 if (c < 0x80 && (cmp_flags & CMP_KEEPASCII))
1700 return TOLOWER_ASC(c);
Bram Moolenaar78622822005-08-23 21:00:13 +00001701 return TOLOWER_LOC(c);
1702}
Bram Moolenaar78622822005-08-23 21:00:13 +00001703
Bram Moolenaar071d4272004-06-13 20:20:40 +00001704/*
1705 * skiptowhite: skip over text until ' ' or '\t' or NUL.
1706 */
1707 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001708skiptowhite(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001709{
1710 while (*p != ' ' && *p != '\t' && *p != NUL)
1711 ++p;
1712 return p;
1713}
1714
Bram Moolenaar071d4272004-06-13 20:20:40 +00001715/*
1716 * skiptowhite_esc: Like skiptowhite(), but also skip escaped chars
1717 */
1718 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01001719skiptowhite_esc(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001720{
1721 while (*p != ' ' && *p != '\t' && *p != NUL)
1722 {
1723 if ((*p == '\\' || *p == Ctrl_V) && *(p + 1) != NUL)
1724 ++p;
1725 ++p;
1726 }
1727 return p;
1728}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001729
1730/*
1731 * Getdigits: Get a number from a string and skip over it.
1732 * Note: the argument is a pointer to a char_u pointer!
1733 */
1734 long
Bram Moolenaar7454a062016-01-30 15:14:10 +01001735getdigits(char_u **pp)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001736{
1737 char_u *p;
1738 long retval;
1739
1740 p = *pp;
1741 retval = atol((char *)p);
Bram Moolenaarc667da52019-11-30 20:52:27 +01001742 if (*p == '-') // skip negative sign
Bram Moolenaar071d4272004-06-13 20:20:40 +00001743 ++p;
Bram Moolenaarc667da52019-11-30 20:52:27 +01001744 p = skipdigits(p); // skip to next non-digit
Bram Moolenaar071d4272004-06-13 20:20:40 +00001745 *pp = p;
1746 return retval;
1747}
1748
1749/*
1750 * Return TRUE if "lbuf" is empty or only contains blanks.
1751 */
1752 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001753vim_isblankline(char_u *lbuf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001754{
1755 char_u *p;
1756
1757 p = skipwhite(lbuf);
1758 return (*p == NUL || *p == '\r' || *p == '\n');
1759}
1760
1761/*
1762 * Convert a string into a long and/or unsigned long, taking care of
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001763 * hexadecimal, octal, and binary numbers. Accepts a '-' sign.
1764 * If "prep" is not NULL, returns a flag to indicate the type of the number:
Bram Moolenaar071d4272004-06-13 20:20:40 +00001765 * 0 decimal
1766 * '0' octal
Bram Moolenaarc17e66c2020-06-02 21:38:22 +02001767 * 'O' octal
1768 * 'o' octal
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001769 * 'B' bin
1770 * 'b' bin
Bram Moolenaar071d4272004-06-13 20:20:40 +00001771 * 'X' hex
1772 * 'x' hex
1773 * If "len" is not NULL, the length of the number in characters is returned.
1774 * If "nptr" is not NULL, the signed result is returned in it.
1775 * If "unptr" is not NULL, the unsigned result is returned in it.
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001776 * If "what" contains STR2NR_BIN recognize binary numbers
1777 * If "what" contains STR2NR_OCT recognize octal numbers
1778 * If "what" contains STR2NR_HEX recognize hex numbers
1779 * If "what" contains STR2NR_FORCE always assume bin/oct/hex.
Bram Moolenaar1ac90b42019-09-15 14:49:52 +02001780 * If "what" contains STR2NR_QUOTE ignore embedded single quotes
Bram Moolenaarce157752017-10-28 16:07:33 +02001781 * If maxlen > 0, check at a maximum maxlen chars.
Bram Moolenaar16e9b852019-05-19 19:59:35 +02001782 * If strict is TRUE, check the number strictly. return *len = 0 if fail.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001783 */
1784 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01001785vim_str2nr(
1786 char_u *start,
Bram Moolenaar16e9b852019-05-19 19:59:35 +02001787 int *prep, // return: type of number 0 = decimal, 'x'
Bram Moolenaarc17e66c2020-06-02 21:38:22 +02001788 // or 'X' is hex, '0', 'o' or 'O' is octal,
1789 // 'b' or 'B' is bin
Bram Moolenaar16e9b852019-05-19 19:59:35 +02001790 int *len, // return: detected length of number
1791 int what, // what numbers to recognize
1792 varnumber_T *nptr, // return: signed result
1793 uvarnumber_T *unptr, // return: unsigned result
1794 int maxlen, // max length of string to check
1795 int strict) // check strictly
Bram Moolenaar071d4272004-06-13 20:20:40 +00001796{
1797 char_u *ptr = start;
Bram Moolenaar16e9b852019-05-19 19:59:35 +02001798 int pre = 0; // default is decimal
Bram Moolenaar071d4272004-06-13 20:20:40 +00001799 int negative = FALSE;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001800 uvarnumber_T un = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001801 int n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001802
Bram Moolenaar16e9b852019-05-19 19:59:35 +02001803 if (len != NULL)
1804 *len = 0;
1805
Bram Moolenaar071d4272004-06-13 20:20:40 +00001806 if (ptr[0] == '-')
1807 {
1808 negative = TRUE;
1809 ++ptr;
1810 }
1811
Bram Moolenaarc667da52019-11-30 20:52:27 +01001812 // Recognize hex, octal, and bin.
Bram Moolenaar5d1bc782015-07-17 13:03:48 +02001813 if (ptr[0] == '0' && ptr[1] != '8' && ptr[1] != '9'
1814 && (maxlen == 0 || maxlen > 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001815 {
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001816 pre = ptr[1];
1817 if ((what & STR2NR_HEX)
1818 && (pre == 'X' || pre == 'x') && vim_isxdigit(ptr[2])
1819 && (maxlen == 0 || maxlen > 2))
Bram Moolenaarc667da52019-11-30 20:52:27 +01001820 // hexadecimal
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001821 ptr += 2;
1822 else if ((what & STR2NR_BIN)
1823 && (pre == 'B' || pre == 'b') && vim_isbdigit(ptr[2])
1824 && (maxlen == 0 || maxlen > 2))
Bram Moolenaarc667da52019-11-30 20:52:27 +01001825 // binary
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001826 ptr += 2;
Bram Moolenaarc17e66c2020-06-02 21:38:22 +02001827 else if ((what & STR2NR_OOCT)
1828 && (pre == 'O' || pre == 'o') && vim_isbdigit(ptr[2])
1829 && (maxlen == 0 || maxlen > 2))
1830 // octal with prefix "0o"
1831 ptr += 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001832 else
1833 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001834 // decimal or octal, default is decimal
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001835 pre = 0;
1836 if (what & STR2NR_OCT)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001837 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001838 // Don't interpret "0", "08" or "0129" as octal.
Bram Moolenaarce157752017-10-28 16:07:33 +02001839 for (n = 1; n != maxlen && VIM_ISDIGIT(ptr[n]); ++n)
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001840 {
1841 if (ptr[n] > '7')
1842 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001843 pre = 0; // can't be octal
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001844 break;
1845 }
Bram Moolenaarc667da52019-11-30 20:52:27 +01001846 pre = '0'; // assume octal
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001847 }
1848 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001849 }
1850 }
1851
Bram Moolenaar16e9b852019-05-19 19:59:35 +02001852 // Do the conversion manually to avoid sscanf() quirks.
Bram Moolenaar5d1bc782015-07-17 13:03:48 +02001853 n = 1;
Bram Moolenaar1ac90b42019-09-15 14:49:52 +02001854 if (pre == 'B' || pre == 'b'
1855 || ((what & STR2NR_BIN) && (what & STR2NR_FORCE)))
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001856 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001857 // bin
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001858 if (pre != 0)
Bram Moolenaarc667da52019-11-30 20:52:27 +01001859 n += 2; // skip over "0b"
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001860 while ('0' <= *ptr && *ptr <= '1')
1861 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001862 // avoid ubsan error for overflow
Bram Moolenaar07ccf7c2018-06-12 17:25:36 +02001863 if (un <= UVARNUM_MAX / 2)
1864 un = 2 * un + (uvarnumber_T)(*ptr - '0');
Bram Moolenaar7a40ea22017-01-22 18:34:57 +01001865 else
1866 un = UVARNUM_MAX;
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001867 ++ptr;
1868 if (n++ == maxlen)
1869 break;
Bram Moolenaar1ac90b42019-09-15 14:49:52 +02001870 if ((what & STR2NR_QUOTE) && *ptr == '\''
1871 && '0' <= ptr[1] && ptr[1] <= '1')
1872 {
1873 ++ptr;
1874 if (n++ == maxlen)
1875 break;
1876 }
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001877 }
1878 }
Bram Moolenaarc17e66c2020-06-02 21:38:22 +02001879 else if (pre == 'O' || pre == 'o' ||
1880 pre == '0' || ((what & STR2NR_OCT) && (what & STR2NR_FORCE)))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001881 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001882 // octal
Bram Moolenaarc17e66c2020-06-02 21:38:22 +02001883 if (pre != 0 && pre != '0')
1884 n += 2; // skip over "0o"
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001885 while ('0' <= *ptr && *ptr <= '7')
Bram Moolenaar071d4272004-06-13 20:20:40 +00001886 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001887 // avoid ubsan error for overflow
Bram Moolenaar07ccf7c2018-06-12 17:25:36 +02001888 if (un <= UVARNUM_MAX / 8)
Bram Moolenaar7a40ea22017-01-22 18:34:57 +01001889 un = 8 * un + (uvarnumber_T)(*ptr - '0');
1890 else
1891 un = UVARNUM_MAX;
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001892 ++ptr;
Bram Moolenaar5d1bc782015-07-17 13:03:48 +02001893 if (n++ == maxlen)
1894 break;
Bram Moolenaar1ac90b42019-09-15 14:49:52 +02001895 if ((what & STR2NR_QUOTE) && *ptr == '\''
1896 && '0' <= ptr[1] && ptr[1] <= '7')
1897 {
1898 ++ptr;
1899 if (n++ == maxlen)
1900 break;
1901 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001902 }
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001903 }
Bram Moolenaar1ac90b42019-09-15 14:49:52 +02001904 else if (pre != 0 || ((what & STR2NR_HEX) && (what & STR2NR_FORCE)))
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001905 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001906 // hex
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001907 if (pre != 0)
Bram Moolenaarc667da52019-11-30 20:52:27 +01001908 n += 2; // skip over "0x"
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001909 while (vim_isxdigit(*ptr))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001910 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001911 // avoid ubsan error for overflow
Bram Moolenaar07ccf7c2018-06-12 17:25:36 +02001912 if (un <= UVARNUM_MAX / 16)
Bram Moolenaar7a40ea22017-01-22 18:34:57 +01001913 un = 16 * un + (uvarnumber_T)hex2nr(*ptr);
1914 else
1915 un = UVARNUM_MAX;
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001916 ++ptr;
Bram Moolenaar5d1bc782015-07-17 13:03:48 +02001917 if (n++ == maxlen)
1918 break;
Bram Moolenaar1ac90b42019-09-15 14:49:52 +02001919 if ((what & STR2NR_QUOTE) && *ptr == '\'' && vim_isxdigit(ptr[1]))
1920 {
1921 ++ptr;
1922 if (n++ == maxlen)
1923 break;
1924 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001925 }
1926 }
1927 else
1928 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001929 // decimal
Bram Moolenaar071d4272004-06-13 20:20:40 +00001930 while (VIM_ISDIGIT(*ptr))
1931 {
Bram Moolenaar07ccf7c2018-06-12 17:25:36 +02001932 uvarnumber_T digit = (uvarnumber_T)(*ptr - '0');
1933
Bram Moolenaarc667da52019-11-30 20:52:27 +01001934 // avoid ubsan error for overflow
Bram Moolenaar07ccf7c2018-06-12 17:25:36 +02001935 if (un < UVARNUM_MAX / 10
1936 || (un == UVARNUM_MAX / 10 && digit <= UVARNUM_MAX % 10))
1937 un = 10 * un + digit;
Bram Moolenaar7a40ea22017-01-22 18:34:57 +01001938 else
1939 un = UVARNUM_MAX;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001940 ++ptr;
Bram Moolenaar5d1bc782015-07-17 13:03:48 +02001941 if (n++ == maxlen)
1942 break;
Bram Moolenaar1ac90b42019-09-15 14:49:52 +02001943 if ((what & STR2NR_QUOTE) && *ptr == '\'' && VIM_ISDIGIT(ptr[1]))
1944 {
1945 ++ptr;
1946 if (n++ == maxlen)
1947 break;
1948 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001949 }
1950 }
Bram Moolenaar1ac90b42019-09-15 14:49:52 +02001951
Bram Moolenaar4b96df52020-01-26 22:00:26 +01001952 // Check for an alphanumeric character immediately following, that is
Bram Moolenaar16e9b852019-05-19 19:59:35 +02001953 // most likely a typo.
1954 if (strict && n - 1 != maxlen && ASCII_ISALNUM(*ptr))
1955 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001956
Bram Moolenaar887c1fe2016-01-02 17:56:35 +01001957 if (prep != NULL)
1958 *prep = pre;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001959 if (len != NULL)
1960 *len = (int)(ptr - start);
1961 if (nptr != NULL)
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00001962 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001963 if (negative) // account for leading '-' for decimal numbers
Bram Moolenaar7a40ea22017-01-22 18:34:57 +01001964 {
Bram Moolenaarc667da52019-11-30 20:52:27 +01001965 // avoid ubsan error for overflow
Bram Moolenaar7a40ea22017-01-22 18:34:57 +01001966 if (un > VARNUM_MAX)
1967 *nptr = VARNUM_MIN;
1968 else
1969 *nptr = -(varnumber_T)un;
1970 }
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00001971 else
Bram Moolenaar7a40ea22017-01-22 18:34:57 +01001972 {
1973 if (un > VARNUM_MAX)
1974 un = VARNUM_MAX;
Bram Moolenaar22fcfad2016-07-01 18:17:26 +02001975 *nptr = (varnumber_T)un;
Bram Moolenaar7a40ea22017-01-22 18:34:57 +01001976 }
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00001977 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001978 if (unptr != NULL)
1979 *unptr = un;
1980}
1981
1982/*
1983 * Return the value of a single hex character.
1984 * Only valid when the argument is '0' - '9', 'A' - 'F' or 'a' - 'f'.
1985 */
1986 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001987hex2nr(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001988{
1989 if (c >= 'a' && c <= 'f')
1990 return c - 'a' + 10;
1991 if (c >= 'A' && c <= 'F')
1992 return c - 'A' + 10;
1993 return c - '0';
1994}
1995
Bram Moolenaar4033c552017-09-16 20:54:51 +02001996#if defined(FEAT_TERMRESPONSE) || defined(FEAT_GUI_GTK) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001997/*
1998 * Convert two hex characters to a byte.
1999 * Return -1 if one of the characters is not hex.
2000 */
2001 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002002hexhex2nr(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002003{
2004 if (!vim_isxdigit(p[0]) || !vim_isxdigit(p[1]))
2005 return -1;
2006 return (hex2nr(p[0]) << 4) + hex2nr(p[1]);
2007}
2008#endif
2009
2010/*
2011 * Return TRUE if "str" starts with a backslash that should be removed.
Bram Moolenaar2c519cf2019-03-21 21:45:34 +01002012 * For MS-DOS, MSWIN and OS/2 this is only done when the character after the
Bram Moolenaar071d4272004-06-13 20:20:40 +00002013 * backslash is not a normal file name character.
2014 * '$' is a valid file name character, we don't remove the backslash before
2015 * it. This means it is not possible to use an environment variable after a
2016 * backslash. "C:\$VIM\doc" is taken literally, only "$VIM\doc" works.
2017 * Although "\ name" is valid, the backslash in "Program\ files" must be
2018 * removed. Assume a file name doesn't start with a space.
2019 * For multi-byte names, never remove a backslash before a non-ascii
2020 * character, assume that all multi-byte characters are valid file name
2021 * characters.
2022 */
2023 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01002024rem_backslash(char_u *str)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002025{
2026#ifdef BACKSLASH_IN_FILENAME
2027 return (str[0] == '\\'
Bram Moolenaar071d4272004-06-13 20:20:40 +00002028 && str[1] < 0x80
Bram Moolenaar071d4272004-06-13 20:20:40 +00002029 && (str[1] == ' '
2030 || (str[1] != NUL
2031 && str[1] != '*'
2032 && str[1] != '?'
2033 && !vim_isfilec(str[1]))));
2034#else
2035 return (str[0] == '\\' && str[1] != NUL);
2036#endif
2037}
2038
2039/*
2040 * Halve the number of backslashes in a file name argument.
2041 * For MS-DOS we only do this if the character after the backslash
2042 * is not a normal file character.
2043 */
2044 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002045backslash_halve(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002046{
2047 for ( ; *p; ++p)
2048 if (rem_backslash(p))
Bram Moolenaar446cb832008-06-24 21:56:24 +00002049 STRMOVE(p, p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002050}
2051
2052/*
2053 * backslash_halve() plus save the result in allocated memory.
Bram Moolenaare2c453d2019-08-21 14:37:09 +02002054 * However, returns "p" when out of memory.
Bram Moolenaar071d4272004-06-13 20:20:40 +00002055 */
2056 char_u *
Bram Moolenaar7454a062016-01-30 15:14:10 +01002057backslash_halve_save(char_u *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002058{
2059 char_u *res;
2060
2061 res = vim_strsave(p);
2062 if (res == NULL)
2063 return p;
2064 backslash_halve(res);
2065 return res;
2066}
2067
2068#if (defined(EBCDIC) && defined(FEAT_POSTSCRIPT)) || defined(PROTO)
2069/*
2070 * Table for EBCDIC to ASCII conversion unashamedly taken from xxd.c!
2071 * The first 64 entries have been added to map control characters defined in
2072 * ascii.h
2073 */
2074static char_u ebcdic2ascii_tab[256] =
2075{
2076 0000, 0001, 0002, 0003, 0004, 0011, 0006, 0177,
2077 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
2078 0020, 0021, 0022, 0023, 0024, 0012, 0010, 0027,
2079 0030, 0031, 0032, 0033, 0033, 0035, 0036, 0037,
2080 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
2081 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
2082 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
2083 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
2084 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246,
2085 0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174,
2086 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
2087 0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176,
2088 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267,
2089 0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077,
2090 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
2091 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042,
2092 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
2093 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311,
2094 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160,
2095 0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320,
2096 0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170,
2097 0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327,
2098 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
2099 0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347,
2100 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
2101 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355,
2102 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120,
2103 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363,
2104 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130,
2105 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
2106 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
2107 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377
2108};
2109
2110/*
2111 * Convert a buffer worth of characters from EBCDIC to ASCII. Only useful if
2112 * wanting 7-bit ASCII characters out the other end.
2113 */
2114 void
Bram Moolenaar7454a062016-01-30 15:14:10 +01002115ebcdic2ascii(char_u *buffer, int len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002116{
2117 int i;
2118
2119 for (i = 0; i < len; i++)
2120 buffer[i] = ebcdic2ascii_tab[buffer[i]];
2121}
2122#endif