blob: 21fb4e52c5622f02715a20872027ba21db356c7d [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
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
12#ifdef FEAT_LINEBREAK
13static int win_chartabsize __ARGS((win_T *wp, char_u *p, colnr_T col));
14#endif
15
16#ifdef FEAT_MBYTE
Bram Moolenaard7b734a2010-08-12 20:17:02 +020017# if defined(HAVE_WCHAR_H)
18# include <wchar.h> /* for towupper() and towlower() */
19# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000020static int win_nolbr_chartabsize __ARGS((win_T *wp, char_u *s, colnr_T col, int *headp));
21#endif
22
Bram Moolenaar0ab2a882009-05-13 10:51:08 +000023static unsigned nr2hex __ARGS((unsigned c));
Bram Moolenaar071d4272004-06-13 20:20:40 +000024
25static int chartab_initialized = FALSE;
26
27/* b_chartab[] is an array of 32 bytes, each bit representing one of the
28 * characters 0-255. */
29#define SET_CHARTAB(buf, c) (buf)->b_chartab[(unsigned)(c) >> 3] |= (1 << ((c) & 0x7))
30#define RESET_CHARTAB(buf, c) (buf)->b_chartab[(unsigned)(c) >> 3] &= ~(1 << ((c) & 0x7))
31#define GET_CHARTAB(buf, c) ((buf)->b_chartab[(unsigned)(c) >> 3] & (1 << ((c) & 0x7)))
32
33/*
34 * Fill chartab[]. Also fills curbuf->b_chartab[] with flags for keyword
35 * characters for current buffer.
36 *
37 * Depends on the option settings 'iskeyword', 'isident', 'isfname',
38 * 'isprint' and 'encoding'.
39 *
40 * The index in chartab[] depends on 'encoding':
41 * - For non-multi-byte index with the byte (same as the character).
42 * - For DBCS index with the first byte.
43 * - For UTF-8 index with the character (when first byte is up to 0x80 it is
44 * the same as the character, if the first byte is 0x80 and above it depends
45 * on further bytes).
46 *
47 * The contents of chartab[]:
48 * - The lower two bits, masked by CT_CELL_MASK, give the number of display
49 * cells the character occupies (1 or 2). Not valid for UTF-8 above 0x80.
50 * - CT_PRINT_CHAR bit is set when the character is printable (no need to
51 * translate the character before displaying it). Note that only DBCS
52 * characters can have 2 display cells and still be printable.
53 * - CT_FNAME_CHAR bit is set when the character can be in a file name.
54 * - CT_ID_CHAR bit is set when the character can be in an identifier.
55 *
56 * Return FAIL if 'iskeyword', 'isident', 'isfname' or 'isprint' option has an
57 * error, OK otherwise.
58 */
59 int
60init_chartab()
61{
62 return buf_init_chartab(curbuf, TRUE);
63}
64
65 int
66buf_init_chartab(buf, global)
67 buf_T *buf;
68 int global; /* FALSE: only set buf->b_chartab[] */
69{
70 int c;
71 int c2;
72 char_u *p;
73 int i;
74 int tilde;
75 int do_isalpha;
76
77 if (global)
78 {
79 /*
80 * Set the default size for printable characters:
81 * From <Space> to '~' is 1 (printable), others are 2 (not printable).
82 * This also inits all 'isident' and 'isfname' flags to FALSE.
83 *
84 * EBCDIC: all chars below ' ' are not printable, all others are
85 * printable.
86 */
87 c = 0;
88 while (c < ' ')
89 chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2;
90#ifdef EBCDIC
91 while (c < 255)
92#else
93 while (c <= '~')
94#endif
95 chartab[c++] = 1 + CT_PRINT_CHAR;
96#ifdef FEAT_FKMAP
97 if (p_altkeymap)
98 {
99 while (c < YE)
100 chartab[c++] = 1 + CT_PRINT_CHAR;
101 }
102#endif
103 while (c < 256)
104 {
105#ifdef FEAT_MBYTE
106 /* UTF-8: bytes 0xa0 - 0xff are printable (latin1) */
107 if (enc_utf8 && c >= 0xa0)
108 chartab[c++] = CT_PRINT_CHAR + 1;
109 /* euc-jp characters starting with 0x8e are single width */
110 else if (enc_dbcs == DBCS_JPNU && c == 0x8e)
111 chartab[c++] = CT_PRINT_CHAR + 1;
112 /* other double-byte chars can be printable AND double-width */
113 else if (enc_dbcs != 0 && MB_BYTE2LEN(c) == 2)
114 chartab[c++] = CT_PRINT_CHAR + 2;
115 else
116#endif
117 /* the rest is unprintable by default */
118 chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2;
119 }
120
121#ifdef FEAT_MBYTE
122 /* Assume that every multi-byte char is a filename character. */
123 for (c = 1; c < 256; ++c)
124 if ((enc_dbcs != 0 && MB_BYTE2LEN(c) > 1)
125 || (enc_dbcs == DBCS_JPNU && c == 0x8e)
126 || (enc_utf8 && c >= 0xa0))
127 chartab[c] |= CT_FNAME_CHAR;
128#endif
129 }
130
131 /*
132 * Init word char flags all to FALSE
133 */
134 vim_memset(buf->b_chartab, 0, (size_t)32);
135#ifdef FEAT_MBYTE
Bram Moolenaar6bb68362005-03-22 23:03:44 +0000136 if (enc_dbcs != 0)
137 for (c = 0; c < 256; ++c)
138 {
139 /* double-byte characters are probably word characters */
140 if (MB_BYTE2LEN(c) == 2)
141 SET_CHARTAB(buf, c);
142 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000143#endif
144
145#ifdef FEAT_LISP
146 /*
147 * In lisp mode the '-' character is included in keywords.
148 */
149 if (buf->b_p_lisp)
150 SET_CHARTAB(buf, '-');
151#endif
152
153 /* Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint'
154 * options Each option is a list of characters, character numbers or
155 * ranges, separated by commas, e.g.: "200-210,x,#-178,-"
156 */
157 for (i = global ? 0 : 3; i <= 3; ++i)
158 {
159 if (i == 0)
160 p = p_isi; /* first round: 'isident' */
161 else if (i == 1)
162 p = p_isp; /* second round: 'isprint' */
163 else if (i == 2)
164 p = p_isf; /* third round: 'isfname' */
165 else /* i == 3 */
166 p = buf->b_p_isk; /* fourth round: 'iskeyword' */
167
168 while (*p)
169 {
170 tilde = FALSE;
171 do_isalpha = FALSE;
172 if (*p == '^' && p[1] != NUL)
173 {
174 tilde = TRUE;
175 ++p;
176 }
177 if (VIM_ISDIGIT(*p))
178 c = getdigits(&p);
179 else
Bram Moolenaar183bb3e2009-09-11 12:02:34 +0000180#ifdef FEAT_MBYTE
181 if (has_mbyte)
182 c = mb_ptr2char_adv(&p);
183 else
184#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000185 c = *p++;
186 c2 = -1;
187 if (*p == '-' && p[1] != NUL)
188 {
189 ++p;
190 if (VIM_ISDIGIT(*p))
191 c2 = getdigits(&p);
192 else
Bram Moolenaar2ac5e602009-11-03 15:04:20 +0000193#ifdef FEAT_MBYTE
194 if (has_mbyte)
195 c2 = mb_ptr2char_adv(&p);
196 else
197#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000198 c2 = *p++;
199 }
Bram Moolenaar2ac5e602009-11-03 15:04:20 +0000200 if (c <= 0 || c >= 256 || (c2 < c && c2 != -1) || c2 >= 256
Bram Moolenaar071d4272004-06-13 20:20:40 +0000201 || !(*p == NUL || *p == ','))
202 return FAIL;
203
204 if (c2 == -1) /* not a range */
205 {
206 /*
207 * A single '@' (not "@-@"):
208 * Decide on letters being ID/printable/keyword chars with
209 * standard function isalpha(). This takes care of locale for
210 * single-byte characters).
211 */
212 if (c == '@')
213 {
214 do_isalpha = TRUE;
215 c = 1;
216 c2 = 255;
217 }
218 else
219 c2 = c;
220 }
221 while (c <= c2)
222 {
Bram Moolenaardeefb632007-08-15 18:41:34 +0000223 /* Use the MB_ functions here, because isalpha() doesn't
224 * work properly when 'encoding' is "latin1" and the locale is
225 * "C". */
226 if (!do_isalpha || MB_ISLOWER(c) || MB_ISUPPER(c)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000227#ifdef FEAT_FKMAP
228 || (p_altkeymap && (F_isalpha(c) || F_isdigit(c)))
229#endif
230 )
231 {
232 if (i == 0) /* (re)set ID flag */
233 {
234 if (tilde)
235 chartab[c] &= ~CT_ID_CHAR;
236 else
237 chartab[c] |= CT_ID_CHAR;
238 }
239 else if (i == 1) /* (re)set printable */
240 {
241 if ((c < ' '
242#ifndef EBCDIC
243 || c > '~'
244#endif
245#ifdef FEAT_FKMAP
246 || (p_altkeymap
247 && (F_isalpha(c) || F_isdigit(c)))
248#endif
249 )
250#ifdef FEAT_MBYTE
251 /* For double-byte we keep the cell width, so
252 * that we can detect it from the first byte. */
253 && !(enc_dbcs && MB_BYTE2LEN(c) == 2)
254#endif
255 )
256 {
257 if (tilde)
258 {
259 chartab[c] = (chartab[c] & ~CT_CELL_MASK)
260 + ((dy_flags & DY_UHEX) ? 4 : 2);
261 chartab[c] &= ~CT_PRINT_CHAR;
262 }
263 else
264 {
265 chartab[c] = (chartab[c] & ~CT_CELL_MASK) + 1;
266 chartab[c] |= CT_PRINT_CHAR;
267 }
268 }
269 }
270 else if (i == 2) /* (re)set fname flag */
271 {
272 if (tilde)
273 chartab[c] &= ~CT_FNAME_CHAR;
274 else
275 chartab[c] |= CT_FNAME_CHAR;
276 }
277 else /* i == 3 */ /* (re)set keyword flag */
278 {
279 if (tilde)
280 RESET_CHARTAB(buf, c);
281 else
282 SET_CHARTAB(buf, c);
283 }
284 }
285 ++c;
286 }
287 p = skip_to_option_part(p);
288 }
289 }
290 chartab_initialized = TRUE;
291 return OK;
292}
293
294/*
295 * Translate any special characters in buf[bufsize] in-place.
296 * The result is a string with only printable characters, but if there is not
297 * enough room, not all characters will be translated.
298 */
299 void
300trans_characters(buf, bufsize)
301 char_u *buf;
302 int bufsize;
303{
304 int len; /* length of string needing translation */
305 int room; /* room in buffer after string */
306 char_u *trs; /* translated character */
307 int trs_len; /* length of trs[] */
308
309 len = (int)STRLEN(buf);
310 room = bufsize - len;
311 while (*buf != 0)
312 {
313# ifdef FEAT_MBYTE
314 /* Assume a multi-byte character doesn't need translation. */
Bram Moolenaar0fa313a2005-08-10 21:07:57 +0000315 if (has_mbyte && (trs_len = (*mb_ptr2len)(buf)) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000316 len -= trs_len;
317 else
318# endif
319 {
320 trs = transchar_byte(*buf);
321 trs_len = (int)STRLEN(trs);
322 if (trs_len > 1)
323 {
324 room -= trs_len - 1;
325 if (room <= 0)
326 return;
327 mch_memmove(buf + trs_len, buf + 1, (size_t)len);
328 }
329 mch_memmove(buf, trs, (size_t)trs_len);
330 --len;
331 }
332 buf += trs_len;
333 }
334}
335
Bram Moolenaar7cc36e92007-03-27 10:42:05 +0000336#if defined(FEAT_EVAL) || defined(FEAT_TITLE) || defined(FEAT_INS_EXPAND) \
337 || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000338/*
339 * Translate a string into allocated memory, replacing special chars with
340 * printable chars. Returns NULL when out of memory.
341 */
342 char_u *
343transstr(s)
344 char_u *s;
345{
346 char_u *res;
347 char_u *p;
348#ifdef FEAT_MBYTE
349 int l, len, c;
350 char_u hexbuf[11];
351#endif
352
353#ifdef FEAT_MBYTE
354 if (has_mbyte)
355 {
356 /* Compute the length of the result, taking account of unprintable
357 * multi-byte characters. */
358 len = 0;
359 p = s;
360 while (*p != NUL)
361 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +0000362 if ((l = (*mb_ptr2len)(p)) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000363 {
364 c = (*mb_ptr2char)(p);
365 p += l;
366 if (vim_isprintc(c))
367 len += l;
368 else
369 {
370 transchar_hex(hexbuf, c);
Bram Moolenaara93fa7e2006-04-17 22:14:47 +0000371 len += (int)STRLEN(hexbuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000372 }
373 }
374 else
375 {
376 l = byte2cells(*p++);
377 if (l > 0)
378 len += l;
379 else
380 len += 4; /* illegal byte sequence */
381 }
382 }
383 res = alloc((unsigned)(len + 1));
384 }
385 else
386#endif
387 res = alloc((unsigned)(vim_strsize(s) + 1));
388 if (res != NULL)
389 {
390 *res = NUL;
391 p = s;
392 while (*p != NUL)
393 {
394#ifdef FEAT_MBYTE
Bram Moolenaar0fa313a2005-08-10 21:07:57 +0000395 if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000396 {
397 c = (*mb_ptr2char)(p);
398 if (vim_isprintc(c))
399 STRNCAT(res, p, l); /* append printable multi-byte char */
400 else
401 transchar_hex(res + STRLEN(res), c);
402 p += l;
403 }
404 else
405#endif
406 STRCAT(res, transchar_byte(*p++));
407 }
408 }
409 return res;
410}
411#endif
412
413#if defined(FEAT_SYN_HL) || defined(FEAT_INS_EXPAND) || defined(PROTO)
414/*
Bram Moolenaar217ad922005-03-20 22:37:15 +0000415 * Convert the string "str[orglen]" to do ignore-case comparing. Uses the
416 * current locale.
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000417 * When "buf" is NULL returns an allocated string (NULL for out-of-memory).
418 * Otherwise puts the result in "buf[buflen]".
Bram Moolenaar071d4272004-06-13 20:20:40 +0000419 */
420 char_u *
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000421str_foldcase(str, orglen, buf, buflen)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000422 char_u *str;
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000423 int orglen;
424 char_u *buf;
425 int buflen;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000426{
427 garray_T ga;
428 int i;
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000429 int len = orglen;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000430
431#define GA_CHAR(i) ((char_u *)ga.ga_data)[i]
432#define GA_PTR(i) ((char_u *)ga.ga_data + i)
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000433#define STR_CHAR(i) (buf == NULL ? GA_CHAR(i) : buf[i])
434#define STR_PTR(i) (buf == NULL ? GA_PTR(i) : buf + i)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000435
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000436 /* Copy "str" into "buf" or allocated memory, unmodified. */
437 if (buf == NULL)
438 {
439 ga_init2(&ga, 1, 10);
440 if (ga_grow(&ga, len + 1) == FAIL)
441 return NULL;
442 mch_memmove(ga.ga_data, str, (size_t)len);
443 ga.ga_len = len;
444 }
445 else
446 {
447 if (len >= buflen) /* Ugly! */
448 len = buflen - 1;
449 mch_memmove(buf, str, (size_t)len);
450 }
451 if (buf == NULL)
452 GA_CHAR(len) = NUL;
453 else
454 buf[len] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000455
456 /* Make each character lower case. */
457 i = 0;
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000458 while (STR_CHAR(i) != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000459 {
460#ifdef FEAT_MBYTE
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000461 if (enc_utf8 || (has_mbyte && MB_BYTE2LEN(STR_CHAR(i)) > 1))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000462 {
463 if (enc_utf8)
464 {
Bram Moolenaarb9839212008-06-28 11:03:50 +0000465 int c = utf_ptr2char(STR_PTR(i));
466 int ol = utf_ptr2len(STR_PTR(i));
467 int lc = utf_tolower(c);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000468
Bram Moolenaarb9839212008-06-28 11:03:50 +0000469 /* Only replace the character when it is not an invalid
470 * sequence (ASCII character or more than one byte) and
471 * utf_tolower() doesn't return the original character. */
472 if ((c < 0x80 || ol > 1) && c != lc)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000473 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000474 int nl = utf_char2len(lc);
475
476 /* If the byte length changes need to shift the following
477 * characters forward or backward. */
478 if (ol != nl)
479 {
480 if (nl > ol)
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000481 {
482 if (buf == NULL ? ga_grow(&ga, nl - ol + 1) == FAIL
483 : len + nl - ol >= buflen)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000484 {
485 /* out of memory, keep old char */
486 lc = c;
487 nl = ol;
488 }
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000489 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000490 if (ol != nl)
491 {
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000492 if (buf == NULL)
493 {
Bram Moolenaar446cb832008-06-24 21:56:24 +0000494 STRMOVE(GA_PTR(i) + nl, GA_PTR(i) + ol);
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000495 ga.ga_len += nl - ol;
496 }
497 else
498 {
Bram Moolenaar446cb832008-06-24 21:56:24 +0000499 STRMOVE(buf + i + nl, buf + i + ol);
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000500 len += nl - ol;
501 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000502 }
503 }
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000504 (void)utf_char2bytes(lc, STR_PTR(i));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000505 }
506 }
507 /* skip to next multi-byte char */
Bram Moolenaar0fa313a2005-08-10 21:07:57 +0000508 i += (*mb_ptr2len)(STR_PTR(i));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000509 }
510 else
511#endif
512 {
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000513 if (buf == NULL)
514 GA_CHAR(i) = TOLOWER_LOC(GA_CHAR(i));
515 else
516 buf[i] = TOLOWER_LOC(buf[i]);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000517 ++i;
518 }
519 }
520
Bram Moolenaar6ebb1142005-01-25 21:58:26 +0000521 if (buf == NULL)
522 return (char_u *)ga.ga_data;
523 return buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000524}
525#endif
526
527/*
528 * Catch 22: chartab[] can't be initialized before the options are
529 * initialized, and initializing options may cause transchar() to be called!
530 * When chartab_initialized == FALSE don't use chartab[].
531 * Does NOT work for multi-byte characters, c must be <= 255.
532 * Also doesn't work for the first byte of a multi-byte, "c" must be a
533 * character!
534 */
535static char_u transchar_buf[7];
536
537 char_u *
538transchar(c)
539 int c;
540{
541 int i;
542
543 i = 0;
544 if (IS_SPECIAL(c)) /* special key code, display as ~@ char */
545 {
546 transchar_buf[0] = '~';
547 transchar_buf[1] = '@';
548 i = 2;
549 c = K_SECOND(c);
550 }
551
552 if ((!chartab_initialized && (
553#ifdef EBCDIC
554 (c >= 64 && c < 255)
555#else
556 (c >= ' ' && c <= '~')
557#endif
558#ifdef FEAT_FKMAP
559 || F_ischar(c)
560#endif
561 )) || (c < 256 && vim_isprintc_strict(c)))
562 {
563 /* printable character */
564 transchar_buf[i] = c;
565 transchar_buf[i + 1] = NUL;
566 }
567 else
568 transchar_nonprint(transchar_buf + i, c);
569 return transchar_buf;
570}
571
572#if defined(FEAT_MBYTE) || defined(PROTO)
573/*
574 * Like transchar(), but called with a byte instead of a character. Checks
575 * for an illegal UTF-8 byte.
576 */
577 char_u *
578transchar_byte(c)
579 int c;
580{
581 if (enc_utf8 && c >= 0x80)
582 {
583 transchar_nonprint(transchar_buf, c);
584 return transchar_buf;
585 }
586 return transchar(c);
587}
588#endif
589
590/*
591 * Convert non-printable character to two or more printable characters in
592 * "buf[]". "buf" needs to be able to hold five bytes.
593 * Does NOT work for multi-byte characters, c must be <= 255.
594 */
595 void
596transchar_nonprint(buf, c)
597 char_u *buf;
598 int c;
599{
600 if (c == NL)
601 c = NUL; /* we use newline in place of a NUL */
602 else if (c == CAR && get_fileformat(curbuf) == EOL_MAC)
603 c = NL; /* we use CR in place of NL in this case */
604
605 if (dy_flags & DY_UHEX) /* 'display' has "uhex" */
606 transchar_hex(buf, c);
607
608#ifdef EBCDIC
609 /* For EBCDIC only the characters 0-63 and 255 are not printable */
610 else if (CtrlChar(c) != 0 || c == DEL)
611#else
612 else if (c <= 0x7f) /* 0x00 - 0x1f and 0x7f */
613#endif
614 {
615 buf[0] = '^';
616#ifdef EBCDIC
617 if (c == DEL)
618 buf[1] = '?'; /* DEL displayed as ^? */
619 else
620 buf[1] = CtrlChar(c);
621#else
622 buf[1] = c ^ 0x40; /* DEL displayed as ^? */
623#endif
624
625 buf[2] = NUL;
626 }
627#ifdef FEAT_MBYTE
628 else if (enc_utf8 && c >= 0x80)
629 {
630 transchar_hex(buf, c);
631 }
632#endif
633#ifndef EBCDIC
634 else if (c >= ' ' + 0x80 && c <= '~' + 0x80) /* 0xa0 - 0xfe */
635 {
636 buf[0] = '|';
637 buf[1] = c - 0x80;
638 buf[2] = NUL;
639 }
640#else
641 else if (c < 64)
642 {
643 buf[0] = '~';
644 buf[1] = MetaChar(c);
645 buf[2] = NUL;
646 }
647#endif
648 else /* 0x80 - 0x9f and 0xff */
649 {
650 /*
651 * TODO: EBCDIC I don't know what to do with this chars, so I display
652 * them as '~?' for now
653 */
654 buf[0] = '~';
655#ifdef EBCDIC
656 buf[1] = '?'; /* 0xff displayed as ~? */
657#else
658 buf[1] = (c - 0x80) ^ 0x40; /* 0xff displayed as ~? */
659#endif
660 buf[2] = NUL;
661 }
662}
663
664 void
665transchar_hex(buf, c)
666 char_u *buf;
667 int c;
668{
669 int i = 0;
670
671 buf[0] = '<';
672#ifdef FEAT_MBYTE
673 if (c > 255)
674 {
675 buf[++i] = nr2hex((unsigned)c >> 12);
676 buf[++i] = nr2hex((unsigned)c >> 8);
677 }
678#endif
679 buf[++i] = nr2hex((unsigned)c >> 4);
Bram Moolenaar0ab2a882009-05-13 10:51:08 +0000680 buf[++i] = nr2hex((unsigned)c);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000681 buf[++i] = '>';
682 buf[++i] = NUL;
683}
684
685/*
686 * Convert the lower 4 bits of byte "c" to its hex character.
687 * Lower case letters are used to avoid the confusion of <F1> being 0xf1 or
688 * function key 1.
689 */
Bram Moolenaar0ab2a882009-05-13 10:51:08 +0000690 static unsigned
Bram Moolenaar071d4272004-06-13 20:20:40 +0000691nr2hex(c)
Bram Moolenaar0ab2a882009-05-13 10:51:08 +0000692 unsigned c;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000693{
694 if ((c & 0xf) <= 9)
695 return (c & 0xf) + '0';
696 return (c & 0xf) - 10 + 'a';
697}
698
699/*
700 * Return number of display cells occupied by byte "b".
701 * Caller must make sure 0 <= b <= 255.
702 * For multi-byte mode "b" must be the first byte of a character.
703 * A TAB is counted as two cells: "^I".
704 * For UTF-8 mode this will return 0 for bytes >= 0x80, because the number of
705 * cells depends on further bytes.
706 */
707 int
708byte2cells(b)
709 int b;
710{
711#ifdef FEAT_MBYTE
712 if (enc_utf8 && b >= 0x80)
713 return 0;
714#endif
715 return (chartab[b] & CT_CELL_MASK);
716}
717
718/*
719 * Return number of display cells occupied by character "c".
720 * "c" can be a special key (negative number) in which case 3 or 4 is returned.
721 * A TAB is counted as two cells: "^I" or four: "<09>".
722 */
723 int
724char2cells(c)
725 int c;
726{
727 if (IS_SPECIAL(c))
728 return char2cells(K_SECOND(c)) + 2;
729#ifdef FEAT_MBYTE
730 if (c >= 0x80)
731 {
732 /* UTF-8: above 0x80 need to check the value */
733 if (enc_utf8)
734 return utf_char2cells(c);
735 /* DBCS: double-byte means double-width, except for euc-jp with first
736 * byte 0x8e */
737 if (enc_dbcs != 0 && c >= 0x100)
738 {
739 if (enc_dbcs == DBCS_JPNU && ((unsigned)c >> 8) == 0x8e)
740 return 1;
741 return 2;
742 }
743 }
744#endif
745 return (chartab[c & 0xff] & CT_CELL_MASK);
746}
747
748/*
749 * Return number of display cells occupied by character at "*p".
750 * A TAB is counted as two cells: "^I" or four: "<09>".
751 */
752 int
753ptr2cells(p)
754 char_u *p;
755{
756#ifdef FEAT_MBYTE
757 /* For UTF-8 we need to look at more bytes if the first byte is >= 0x80. */
758 if (enc_utf8 && *p >= 0x80)
759 return utf_ptr2cells(p);
760 /* For DBCS we can tell the cell count from the first byte. */
761#endif
762 return (chartab[*p] & CT_CELL_MASK);
763}
764
765/*
766 * Return the number of characters string "s" will take on the screen,
767 * counting TABs as two characters: "^I".
768 */
769 int
770vim_strsize(s)
771 char_u *s;
772{
773 return vim_strnsize(s, (int)MAXCOL);
774}
775
776/*
777 * Return the number of characters string "s[len]" will take on the screen,
778 * counting TABs as two characters: "^I".
779 */
780 int
781vim_strnsize(s, len)
782 char_u *s;
783 int len;
784{
785 int size = 0;
786
787 while (*s != NUL && --len >= 0)
788 {
789#ifdef FEAT_MBYTE
790 if (has_mbyte)
791 {
Bram Moolenaar0fa313a2005-08-10 21:07:57 +0000792 int l = (*mb_ptr2len)(s);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000793
794 size += ptr2cells(s);
795 s += l;
796 len -= l - 1;
797 }
798 else
799#endif
800 size += byte2cells(*s++);
801 }
802 return size;
803}
804
805/*
806 * Return the number of characters 'c' will take on the screen, taking
807 * into account the size of a tab.
808 * Use a define to make it fast, this is used very often!!!
809 * Also see getvcol() below.
810 */
811
812#define RET_WIN_BUF_CHARTABSIZE(wp, buf, p, col) \
813 if (*(p) == TAB && (!(wp)->w_p_list || lcs_tab1)) \
814 { \
815 int ts; \
816 ts = (buf)->b_p_ts; \
817 return (int)(ts - (col % ts)); \
818 } \
819 else \
820 return ptr2cells(p);
821
822#if defined(FEAT_VREPLACE) || defined(FEAT_EX_EXTRA) || defined(FEAT_GUI) \
823 || defined(FEAT_VIRTUALEDIT) || defined(PROTO)
824 int
825chartabsize(p, col)
826 char_u *p;
827 colnr_T col;
828{
829 RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, p, col)
830}
831#endif
832
833#ifdef FEAT_LINEBREAK
834 static int
835win_chartabsize(wp, p, col)
836 win_T *wp;
837 char_u *p;
838 colnr_T col;
839{
840 RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, p, col)
841}
842#endif
843
844/*
Bram Moolenaardc536092010-07-18 15:45:49 +0200845 * Return the number of characters the string 's' will take on the screen,
846 * taking into account the size of a tab.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000847 */
848 int
849linetabsize(s)
850 char_u *s;
851{
Bram Moolenaardc536092010-07-18 15:45:49 +0200852 return linetabsize_col(0, s);
853}
854
855/*
856 * Like linetabsize(), but starting at column "startcol".
857 */
858 int
859linetabsize_col(startcol, s)
860 int startcol;
861 char_u *s;
862{
863 colnr_T col = startcol;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000864
865 while (*s != NUL)
866 col += lbr_chartabsize_adv(&s, col);
867 return (int)col;
868}
869
870/*
871 * Like linetabsize(), but for a given window instead of the current one.
872 */
873 int
874win_linetabsize(wp, p, len)
875 win_T *wp;
876 char_u *p;
877 colnr_T len;
878{
879 colnr_T col = 0;
880 char_u *s;
881
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +0000882 for (s = p; *s != NUL && (len == MAXCOL || s < p + len); mb_ptr_adv(s))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000883 col += win_lbr_chartabsize(wp, s, col, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000884 return (int)col;
885}
886
887/*
Bram Moolenaar81695252004-12-29 20:58:21 +0000888 * Return TRUE if 'c' is a normal identifier character:
889 * Letters and characters from the 'isident' option.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000890 */
891 int
892vim_isIDc(c)
893 int c;
894{
895 return (c > 0 && c < 0x100 && (chartab[c] & CT_ID_CHAR));
896}
897
898/*
899 * return TRUE if 'c' is a keyword character: Letters and characters from
900 * 'iskeyword' option for current buffer.
901 * For multi-byte characters mb_get_class() is used (builtin rules).
902 */
903 int
904vim_iswordc(c)
905 int c;
906{
907#ifdef FEAT_MBYTE
908 if (c >= 0x100)
909 {
910 if (enc_dbcs != 0)
Bram Moolenaar0ab2a882009-05-13 10:51:08 +0000911 return dbcs_class((unsigned)c >> 8, (unsigned)(c & 0xff)) >= 2;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000912 if (enc_utf8)
913 return utf_class(c) >= 2;
914 }
915#endif
916 return (c > 0 && c < 0x100 && GET_CHARTAB(curbuf, c) != 0);
917}
918
919/*
920 * Just like vim_iswordc() but uses a pointer to the (multi-byte) character.
921 */
922 int
923vim_iswordp(p)
924 char_u *p;
925{
926#ifdef FEAT_MBYTE
927 if (has_mbyte && MB_BYTE2LEN(*p) > 1)
928 return mb_get_class(p) >= 2;
929#endif
930 return GET_CHARTAB(curbuf, *p) != 0;
931}
932
933#if defined(FEAT_SYN_HL) || defined(PROTO)
934 int
935vim_iswordc_buf(p, buf)
936 char_u *p;
937 buf_T *buf;
938{
939# ifdef FEAT_MBYTE
940 if (has_mbyte && MB_BYTE2LEN(*p) > 1)
941 return mb_get_class(p) >= 2;
942# endif
943 return (GET_CHARTAB(buf, *p) != 0);
944}
Bram Moolenaarc4956c82006-03-12 21:58:43 +0000945#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000946
947/*
948 * return TRUE if 'c' is a valid file-name character
949 * Assume characters above 0x100 are valid (multi-byte).
950 */
951 int
952vim_isfilec(c)
953 int c;
954{
955 return (c >= 0x100 || (c > 0 && (chartab[c] & CT_FNAME_CHAR)));
956}
957
958/*
Bram Moolenaardd87969c2007-08-21 13:07:12 +0000959 * return TRUE if 'c' is a valid file-name character or a wildcard character
960 * Assume characters above 0x100 are valid (multi-byte).
961 * Explicitly interpret ']' as a wildcard character as mch_has_wildcard("]")
962 * returns false.
963 */
964 int
965vim_isfilec_or_wc(c)
966 int c;
967{
968 char_u buf[2];
969
970 buf[0] = (char_u)c;
971 buf[1] = NUL;
972 return vim_isfilec(c) || c == ']' || mch_has_wildcard(buf);
973}
974
975/*
Bram Moolenaar071d4272004-06-13 20:20:40 +0000976 * return TRUE if 'c' is a printable character
977 * Assume characters above 0x100 are printable (multi-byte), except for
978 * Unicode.
979 */
980 int
981vim_isprintc(c)
982 int c;
983{
984#ifdef FEAT_MBYTE
985 if (enc_utf8 && c >= 0x100)
986 return utf_printable(c);
987#endif
988 return (c >= 0x100 || (c > 0 && (chartab[c] & CT_PRINT_CHAR)));
989}
990
991/*
992 * Strict version of vim_isprintc(c), don't return TRUE if "c" is the head
993 * byte of a double-byte character.
994 */
995 int
996vim_isprintc_strict(c)
997 int c;
998{
999#ifdef FEAT_MBYTE
1000 if (enc_dbcs != 0 && c < 0x100 && MB_BYTE2LEN(c) > 1)
1001 return FALSE;
1002 if (enc_utf8 && c >= 0x100)
1003 return utf_printable(c);
1004#endif
1005 return (c >= 0x100 || (c > 0 && (chartab[c] & CT_PRINT_CHAR)));
1006}
1007
1008/*
1009 * like chartabsize(), but also check for line breaks on the screen
1010 */
1011 int
1012lbr_chartabsize(s, col)
1013 unsigned char *s;
1014 colnr_T col;
1015{
1016#ifdef FEAT_LINEBREAK
1017 if (!curwin->w_p_lbr && *p_sbr == NUL)
1018 {
1019#endif
1020#ifdef FEAT_MBYTE
1021 if (curwin->w_p_wrap)
1022 return win_nolbr_chartabsize(curwin, s, col, NULL);
1023#endif
1024 RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, s, col)
1025#ifdef FEAT_LINEBREAK
1026 }
1027 return win_lbr_chartabsize(curwin, s, col, NULL);
1028#endif
1029}
1030
1031/*
1032 * Call lbr_chartabsize() and advance the pointer.
1033 */
1034 int
1035lbr_chartabsize_adv(s, col)
1036 char_u **s;
1037 colnr_T col;
1038{
1039 int retval;
1040
1041 retval = lbr_chartabsize(*s, col);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001042 mb_ptr_adv(*s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001043 return retval;
1044}
1045
1046/*
1047 * This function is used very often, keep it fast!!!!
1048 *
1049 * If "headp" not NULL, set *headp to the size of what we for 'showbreak'
1050 * string at start of line. Warning: *headp is only set if it's a non-zero
1051 * value, init to 0 before calling.
1052 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001053 int
1054win_lbr_chartabsize(wp, s, col, headp)
1055 win_T *wp;
1056 char_u *s;
1057 colnr_T col;
Bram Moolenaar0c094b92009-05-14 20:20:33 +00001058 int *headp UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001059{
1060#ifdef FEAT_LINEBREAK
1061 int c;
1062 int size;
1063 colnr_T col2;
1064 colnr_T colmax;
1065 int added;
1066# ifdef FEAT_MBYTE
1067 int mb_added = 0;
1068# else
1069# define mb_added 0
1070# endif
1071 int numberextra;
1072 char_u *ps;
1073 int tab_corr = (*s == TAB);
Bram Moolenaar402d2fe2005-04-15 21:00:38 +00001074 int n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001075
1076 /*
1077 * No 'linebreak' and 'showbreak': return quickly.
1078 */
1079 if (!wp->w_p_lbr && *p_sbr == NUL)
1080#endif
1081 {
1082#ifdef FEAT_MBYTE
1083 if (wp->w_p_wrap)
1084 return win_nolbr_chartabsize(wp, s, col, headp);
1085#endif
1086 RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, s, col)
1087 }
1088
1089#ifdef FEAT_LINEBREAK
1090 /*
1091 * First get normal size, without 'linebreak'
1092 */
1093 size = win_chartabsize(wp, s, col);
1094 c = *s;
1095
1096 /*
1097 * If 'linebreak' set check at a blank before a non-blank if the line
1098 * needs a break here
1099 */
1100 if (wp->w_p_lbr
1101 && vim_isbreak(c)
1102 && !vim_isbreak(s[1])
1103 && !wp->w_p_list
1104 && wp->w_p_wrap
1105# ifdef FEAT_VERTSPLIT
1106 && wp->w_width != 0
1107# endif
1108 )
1109 {
1110 /*
1111 * Count all characters from first non-blank after a blank up to next
1112 * non-blank after a blank.
1113 */
1114 numberextra = win_col_off(wp);
1115 col2 = col;
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001116 colmax = (colnr_T)(W_WIDTH(wp) - numberextra);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001117 if (col >= colmax)
Bram Moolenaar402d2fe2005-04-15 21:00:38 +00001118 {
1119 n = colmax + win_col_off2(wp);
1120 if (n > 0)
1121 colmax += (((col - colmax) / n) + 1) * n;
1122 }
1123
Bram Moolenaar071d4272004-06-13 20:20:40 +00001124 for (;;)
1125 {
1126 ps = s;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001127 mb_ptr_adv(s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001128 c = *s;
1129 if (!(c != NUL
1130 && (vim_isbreak(c)
1131 || (!vim_isbreak(c)
1132 && (col2 == col || !vim_isbreak(*ps))))))
1133 break;
1134
1135 col2 += win_chartabsize(wp, s, col2);
1136 if (col2 >= colmax) /* doesn't fit */
1137 {
1138 size = colmax - col;
1139 tab_corr = FALSE;
1140 break;
1141 }
1142 }
1143 }
1144# ifdef FEAT_MBYTE
1145 else if (has_mbyte && size == 2 && MB_BYTE2LEN(*s) > 1
1146 && wp->w_p_wrap && in_win_border(wp, col))
1147 {
1148 ++size; /* Count the ">" in the last column. */
1149 mb_added = 1;
1150 }
1151# endif
1152
1153 /*
1154 * May have to add something for 'showbreak' string at start of line
1155 * Set *headp to the size of what we add.
1156 */
1157 added = 0;
1158 if (*p_sbr != NUL && wp->w_p_wrap && col != 0)
1159 {
1160 numberextra = win_col_off(wp);
1161 col += numberextra + mb_added;
1162 if (col >= (colnr_T)W_WIDTH(wp))
1163 {
1164 col -= W_WIDTH(wp);
1165 numberextra = W_WIDTH(wp) - (numberextra - win_col_off2(wp));
1166 if (numberextra > 0)
1167 col = col % numberextra;
1168 }
1169 if (col == 0 || col + size > (colnr_T)W_WIDTH(wp))
1170 {
1171 added = vim_strsize(p_sbr);
1172 if (tab_corr)
1173 size += (added / wp->w_buffer->b_p_ts) * wp->w_buffer->b_p_ts;
1174 else
1175 size += added;
1176 if (col != 0)
1177 added = 0;
1178 }
1179 }
1180 if (headp != NULL)
1181 *headp = added + mb_added;
1182 return size;
1183#endif
1184}
1185
1186#if defined(FEAT_MBYTE) || defined(PROTO)
1187/*
1188 * Like win_lbr_chartabsize(), except that we know 'linebreak' is off and
1189 * 'wrap' is on. This means we need to check for a double-byte character that
1190 * doesn't fit at the end of the screen line.
1191 */
1192 static int
1193win_nolbr_chartabsize(wp, s, col, headp)
1194 win_T *wp;
1195 char_u *s;
1196 colnr_T col;
1197 int *headp;
1198{
1199 int n;
1200
1201 if (*s == TAB && (!wp->w_p_list || lcs_tab1))
1202 {
1203 n = wp->w_buffer->b_p_ts;
1204 return (int)(n - (col % n));
1205 }
1206 n = ptr2cells(s);
1207 /* Add one cell for a double-width character in the last column of the
1208 * window, displayed with a ">". */
1209 if (n == 2 && MB_BYTE2LEN(*s) > 1 && in_win_border(wp, col))
1210 {
1211 if (headp != NULL)
1212 *headp = 1;
1213 return 3;
1214 }
1215 return n;
1216}
1217
1218/*
1219 * Return TRUE if virtual column "vcol" is in the rightmost column of window
1220 * "wp".
1221 */
1222 int
1223in_win_border(wp, vcol)
1224 win_T *wp;
1225 colnr_T vcol;
1226{
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001227 int width1; /* width of first line (after line number) */
1228 int width2; /* width of further lines */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001229
1230#ifdef FEAT_VERTSPLIT
1231 if (wp->w_width == 0) /* there is no border */
1232 return FALSE;
1233#endif
1234 width1 = W_WIDTH(wp) - win_col_off(wp);
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001235 if ((int)vcol < width1 - 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001236 return FALSE;
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001237 if ((int)vcol == width1 - 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001238 return TRUE;
1239 width2 = width1 + win_col_off2(wp);
Bram Moolenaar8701cd62009-10-07 14:20:30 +00001240 if (width2 <= 0)
1241 return FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001242 return ((vcol - width1) % width2 == width2 - 1);
1243}
1244#endif /* FEAT_MBYTE */
1245
1246/*
1247 * Get virtual column number of pos.
1248 * start: on the first position of this character (TAB, ctrl)
1249 * cursor: where the cursor is on this character (first char, except for TAB)
1250 * end: on the last position of this character (TAB, ctrl)
1251 *
1252 * This is used very often, keep it fast!
1253 */
1254 void
1255getvcol(wp, pos, start, cursor, end)
1256 win_T *wp;
1257 pos_T *pos;
1258 colnr_T *start;
1259 colnr_T *cursor;
1260 colnr_T *end;
1261{
1262 colnr_T vcol;
1263 char_u *ptr; /* points to current char */
1264 char_u *posptr; /* points to char at pos->col */
1265 int incr;
1266 int head;
1267 int ts = wp->w_buffer->b_p_ts;
1268 int c;
1269
1270 vcol = 0;
1271 ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
Bram Moolenaar37d619f2010-03-10 14:46:26 +01001272 if (pos->col == MAXCOL)
1273 posptr = NULL; /* continue until the NUL */
1274 else
1275 posptr = ptr + pos->col;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001276
1277 /*
1278 * This function is used very often, do some speed optimizations.
1279 * When 'list', 'linebreak' and 'showbreak' are not set use a simple loop.
1280 * Also use this when 'list' is set but tabs take their normal size.
1281 */
1282 if ((!wp->w_p_list || lcs_tab1 != NUL)
1283#ifdef FEAT_LINEBREAK
1284 && !wp->w_p_lbr && *p_sbr == NUL
1285#endif
1286 )
1287 {
1288#ifndef FEAT_MBYTE
1289 head = 0;
1290#endif
1291 for (;;)
1292 {
1293#ifdef FEAT_MBYTE
1294 head = 0;
1295#endif
1296 c = *ptr;
1297 /* make sure we don't go past the end of the line */
1298 if (c == NUL)
1299 {
1300 incr = 1; /* NUL at end of line only takes one column */
1301 break;
1302 }
1303 /* A tab gets expanded, depending on the current column */
1304 if (c == TAB)
1305 incr = ts - (vcol % ts);
1306 else
1307 {
1308#ifdef FEAT_MBYTE
1309 if (has_mbyte)
1310 {
1311 /* For utf-8, if the byte is >= 0x80, need to look at
1312 * further bytes to find the cell width. */
1313 if (enc_utf8 && c >= 0x80)
1314 incr = utf_ptr2cells(ptr);
1315 else
1316 incr = CHARSIZE(c);
1317
1318 /* If a double-cell char doesn't fit at the end of a line
1319 * it wraps to the next line, it's like this char is three
1320 * cells wide. */
Bram Moolenaar9c33a7c2008-02-20 13:59:32 +00001321 if (incr == 2 && wp->w_p_wrap && MB_BYTE2LEN(*ptr) > 1
1322 && in_win_border(wp, vcol))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001323 {
1324 ++incr;
1325 head = 1;
1326 }
1327 }
1328 else
1329#endif
1330 incr = CHARSIZE(c);
1331 }
1332
Bram Moolenaar37d619f2010-03-10 14:46:26 +01001333 if (posptr != NULL && ptr >= posptr) /* character at pos->col */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001334 break;
1335
1336 vcol += incr;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001337 mb_ptr_adv(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001338 }
1339 }
1340 else
1341 {
1342 for (;;)
1343 {
1344 /* A tab gets expanded, depending on the current column */
1345 head = 0;
1346 incr = win_lbr_chartabsize(wp, ptr, vcol, &head);
1347 /* make sure we don't go past the end of the line */
1348 if (*ptr == NUL)
1349 {
1350 incr = 1; /* NUL at end of line only takes one column */
1351 break;
1352 }
1353
Bram Moolenaar37d619f2010-03-10 14:46:26 +01001354 if (posptr != NULL && ptr >= posptr) /* character at pos->col */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001355 break;
1356
1357 vcol += incr;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001358 mb_ptr_adv(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001359 }
1360 }
1361 if (start != NULL)
1362 *start = vcol + head;
1363 if (end != NULL)
1364 *end = vcol + incr - 1;
1365 if (cursor != NULL)
1366 {
1367 if (*ptr == TAB
1368 && (State & NORMAL)
1369 && !wp->w_p_list
1370 && !virtual_active()
1371#ifdef FEAT_VISUAL
1372 && !(VIsual_active
1373 && (*p_sel == 'e' || ltoreq(*pos, VIsual)))
1374#endif
1375 )
1376 *cursor = vcol + incr - 1; /* cursor at end */
1377 else
1378 *cursor = vcol + head; /* cursor at start */
1379 }
1380}
1381
1382/*
1383 * Get virtual cursor column in the current window, pretending 'list' is off.
1384 */
1385 colnr_T
1386getvcol_nolist(posp)
1387 pos_T *posp;
1388{
1389 int list_save = curwin->w_p_list;
1390 colnr_T vcol;
1391
1392 curwin->w_p_list = FALSE;
1393 getvcol(curwin, posp, NULL, &vcol, NULL);
1394 curwin->w_p_list = list_save;
1395 return vcol;
1396}
1397
1398#if defined(FEAT_VIRTUALEDIT) || defined(PROTO)
1399/*
1400 * Get virtual column in virtual mode.
1401 */
1402 void
1403getvvcol(wp, pos, start, cursor, end)
1404 win_T *wp;
1405 pos_T *pos;
1406 colnr_T *start;
1407 colnr_T *cursor;
1408 colnr_T *end;
1409{
1410 colnr_T col;
1411 colnr_T coladd;
1412 colnr_T endadd;
1413# ifdef FEAT_MBYTE
1414 char_u *ptr;
1415# endif
1416
1417 if (virtual_active())
1418 {
1419 /* For virtual mode, only want one value */
1420 getvcol(wp, pos, &col, NULL, NULL);
1421
1422 coladd = pos->coladd;
1423 endadd = 0;
1424# ifdef FEAT_MBYTE
1425 /* Cannot put the cursor on part of a wide character. */
1426 ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001427 if (pos->col < (colnr_T)STRLEN(ptr))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001428 {
1429 int c = (*mb_ptr2char)(ptr + pos->col);
1430
1431 if (c != TAB && vim_isprintc(c))
1432 {
Bram Moolenaar0ab2a882009-05-13 10:51:08 +00001433 endadd = (colnr_T)(char2cells(c) - 1);
Bram Moolenaara5792f52005-11-23 21:25:05 +00001434 if (coladd > endadd) /* past end of line */
1435 endadd = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001436 else
1437 coladd = 0;
1438 }
1439 }
1440# endif
1441 col += coladd;
1442 if (start != NULL)
1443 *start = col;
1444 if (cursor != NULL)
1445 *cursor = col;
1446 if (end != NULL)
1447 *end = col + endadd;
1448 }
1449 else
1450 getvcol(wp, pos, start, cursor, end);
1451}
1452#endif
1453
1454#if defined(FEAT_VISUAL) || defined(PROTO)
1455/*
1456 * Get the leftmost and rightmost virtual column of pos1 and pos2.
1457 * Used for Visual block mode.
1458 */
1459 void
1460getvcols(wp, pos1, pos2, left, right)
1461 win_T *wp;
1462 pos_T *pos1, *pos2;
1463 colnr_T *left, *right;
1464{
1465 colnr_T from1, from2, to1, to2;
1466
1467 if (ltp(pos1, pos2))
1468 {
1469 getvvcol(wp, pos1, &from1, NULL, &to1);
1470 getvvcol(wp, pos2, &from2, NULL, &to2);
1471 }
1472 else
1473 {
1474 getvvcol(wp, pos2, &from1, NULL, &to1);
1475 getvvcol(wp, pos1, &from2, NULL, &to2);
1476 }
1477 if (from2 < from1)
1478 *left = from2;
1479 else
1480 *left = from1;
1481 if (to2 > to1)
1482 {
1483 if (*p_sel == 'e' && from2 - 1 >= to1)
1484 *right = from2 - 1;
1485 else
1486 *right = to2;
1487 }
1488 else
1489 *right = to1;
1490}
1491#endif
1492
1493/*
1494 * skipwhite: skip over ' ' and '\t'.
1495 */
1496 char_u *
Bram Moolenaar1387a602008-07-24 19:31:11 +00001497skipwhite(q)
1498 char_u *q;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001499{
Bram Moolenaar1387a602008-07-24 19:31:11 +00001500 char_u *p = q;
1501
Bram Moolenaar071d4272004-06-13 20:20:40 +00001502 while (vim_iswhite(*p)) /* skip to next non-white */
1503 ++p;
1504 return p;
1505}
1506
1507/*
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001508 * skip over digits
Bram Moolenaar071d4272004-06-13 20:20:40 +00001509 */
1510 char_u *
Bram Moolenaar1387a602008-07-24 19:31:11 +00001511skipdigits(q)
1512 char_u *q;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001513{
Bram Moolenaar1387a602008-07-24 19:31:11 +00001514 char_u *p = q;
1515
Bram Moolenaar071d4272004-06-13 20:20:40 +00001516 while (VIM_ISDIGIT(*p)) /* skip to next non-digit */
1517 ++p;
1518 return p;
1519}
1520
Bram Moolenaarc4956c82006-03-12 21:58:43 +00001521#if defined(FEAT_SYN_HL) || defined(FEAT_SPELL) || defined(PROTO)
Bram Moolenaar75c50c42005-06-04 22:06:24 +00001522/*
1523 * skip over digits and hex characters
1524 */
1525 char_u *
Bram Moolenaar1387a602008-07-24 19:31:11 +00001526skiphex(q)
1527 char_u *q;
Bram Moolenaar75c50c42005-06-04 22:06:24 +00001528{
Bram Moolenaar1387a602008-07-24 19:31:11 +00001529 char_u *p = q;
1530
Bram Moolenaar75c50c42005-06-04 22:06:24 +00001531 while (vim_isxdigit(*p)) /* skip to next non-digit */
1532 ++p;
1533 return p;
1534}
1535#endif
1536
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001537#if defined(FEAT_EX_EXTRA) || defined(PROTO)
1538/*
1539 * skip to digit (or NUL after the string)
1540 */
1541 char_u *
Bram Moolenaar1387a602008-07-24 19:31:11 +00001542skiptodigit(q)
1543 char_u *q;
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001544{
Bram Moolenaar1387a602008-07-24 19:31:11 +00001545 char_u *p = q;
1546
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001547 while (*p != NUL && !VIM_ISDIGIT(*p)) /* skip to next digit */
1548 ++p;
1549 return p;
1550}
1551
1552/*
1553 * skip to hex character (or NUL after the string)
1554 */
1555 char_u *
Bram Moolenaar1387a602008-07-24 19:31:11 +00001556skiptohex(q)
1557 char_u *q;
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001558{
Bram Moolenaar1387a602008-07-24 19:31:11 +00001559 char_u *p = q;
1560
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001561 while (*p != NUL && !vim_isxdigit(*p)) /* skip to next digit */
1562 ++p;
1563 return p;
1564}
1565#endif
1566
Bram Moolenaar071d4272004-06-13 20:20:40 +00001567/*
1568 * Variant of isdigit() that can handle characters > 0x100.
1569 * We don't use isdigit() here, because on some systems it also considers
1570 * superscript 1 to be a digit.
1571 * Use the VIM_ISDIGIT() macro for simple arguments.
1572 */
1573 int
1574vim_isdigit(c)
1575 int c;
1576{
1577 return (c >= '0' && c <= '9');
1578}
1579
1580/*
1581 * Variant of isxdigit() that can handle characters > 0x100.
1582 * We don't use isxdigit() here, because on some systems it also considers
1583 * superscript 1 to be a digit.
1584 */
1585 int
1586vim_isxdigit(c)
1587 int c;
1588{
1589 return (c >= '0' && c <= '9')
1590 || (c >= 'a' && c <= 'f')
1591 || (c >= 'A' && c <= 'F');
1592}
1593
Bram Moolenaar78622822005-08-23 21:00:13 +00001594#if defined(FEAT_MBYTE) || defined(PROTO)
1595/*
1596 * Vim's own character class functions. These exist because many library
1597 * islower()/toupper() etc. do not work properly: they crash when used with
1598 * invalid values or can't handle latin1 when the locale is C.
1599 * Speed is most important here.
1600 */
1601#define LATIN1LOWER 'l'
1602#define LATIN1UPPER 'U'
1603
1604/* !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]%_'abcdefghijklmnopqrstuvwxyz{|}~ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ */
Bram Moolenaar6e7c7f32005-08-24 22:16:11 +00001605static char_u latin1flags[257] = " UUUUUUUUUUUUUUUUUUUUUUUUUU llllllllllllllllllllllllll UUUUUUUUUUUUUUUUUUUUUUU UUUUUUUllllllllllllllllllllllll llllllll";
1606static char_u latin1upper[257] = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ÷ØÙÚÛÜÝÞÿ";
1607static char_u latin1lower[257] = " !\"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿àáâãäåæçèéêëìíîïðñòóôõö×øùúûüýþßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ";
Bram Moolenaar78622822005-08-23 21:00:13 +00001608
1609 int
1610vim_islower(c)
1611 int c;
1612{
1613 if (c <= '@')
1614 return FALSE;
1615 if (c >= 0x80)
1616 {
1617 if (enc_utf8)
1618 return utf_islower(c);
1619 if (c >= 0x100)
1620 {
1621#ifdef HAVE_ISWLOWER
1622 if (has_mbyte)
1623 return iswlower(c);
1624#endif
1625 /* islower() can't handle these chars and may crash */
1626 return FALSE;
1627 }
1628 if (enc_latin1like)
1629 return (latin1flags[c] & LATIN1LOWER) == LATIN1LOWER;
1630 }
1631 return islower(c);
1632}
1633
1634 int
1635vim_isupper(c)
1636 int c;
1637{
1638 if (c <= '@')
1639 return FALSE;
1640 if (c >= 0x80)
1641 {
1642 if (enc_utf8)
1643 return utf_isupper(c);
1644 if (c >= 0x100)
1645 {
1646#ifdef HAVE_ISWUPPER
1647 if (has_mbyte)
1648 return iswupper(c);
1649#endif
1650 /* islower() can't handle these chars and may crash */
1651 return FALSE;
1652 }
1653 if (enc_latin1like)
1654 return (latin1flags[c] & LATIN1UPPER) == LATIN1UPPER;
1655 }
1656 return isupper(c);
1657}
1658
1659 int
1660vim_toupper(c)
1661 int c;
1662{
1663 if (c <= '@')
1664 return c;
1665 if (c >= 0x80)
1666 {
1667 if (enc_utf8)
1668 return utf_toupper(c);
1669 if (c >= 0x100)
1670 {
1671#ifdef HAVE_TOWUPPER
1672 if (has_mbyte)
1673 return towupper(c);
1674#endif
1675 /* toupper() can't handle these chars and may crash */
1676 return c;
1677 }
1678 if (enc_latin1like)
1679 return latin1upper[c];
1680 }
1681 return TOUPPER_LOC(c);
1682}
1683
1684 int
1685vim_tolower(c)
1686 int c;
1687{
1688 if (c <= '@')
1689 return c;
1690 if (c >= 0x80)
1691 {
1692 if (enc_utf8)
1693 return utf_tolower(c);
1694 if (c >= 0x100)
1695 {
1696#ifdef HAVE_TOWLOWER
1697 if (has_mbyte)
1698 return towlower(c);
1699#endif
1700 /* tolower() can't handle these chars and may crash */
1701 return c;
1702 }
1703 if (enc_latin1like)
1704 return latin1lower[c];
1705 }
1706 return TOLOWER_LOC(c);
1707}
1708#endif
1709
Bram Moolenaar071d4272004-06-13 20:20:40 +00001710/*
1711 * skiptowhite: skip over text until ' ' or '\t' or NUL.
1712 */
1713 char_u *
1714skiptowhite(p)
1715 char_u *p;
1716{
1717 while (*p != ' ' && *p != '\t' && *p != NUL)
1718 ++p;
1719 return p;
1720}
1721
1722#if defined(FEAT_LISTCMDS) || defined(FEAT_SIGNS) || defined(FEAT_SNIFF) \
1723 || defined(PROTO)
1724/*
1725 * skiptowhite_esc: Like skiptowhite(), but also skip escaped chars
1726 */
1727 char_u *
1728skiptowhite_esc(p)
1729 char_u *p;
1730{
1731 while (*p != ' ' && *p != '\t' && *p != NUL)
1732 {
1733 if ((*p == '\\' || *p == Ctrl_V) && *(p + 1) != NUL)
1734 ++p;
1735 ++p;
1736 }
1737 return p;
1738}
1739#endif
1740
1741/*
1742 * Getdigits: Get a number from a string and skip over it.
1743 * Note: the argument is a pointer to a char_u pointer!
1744 */
1745 long
1746getdigits(pp)
1747 char_u **pp;
1748{
1749 char_u *p;
1750 long retval;
1751
1752 p = *pp;
1753 retval = atol((char *)p);
1754 if (*p == '-') /* skip negative sign */
1755 ++p;
1756 p = skipdigits(p); /* skip to next non-digit */
1757 *pp = p;
1758 return retval;
1759}
1760
1761/*
1762 * Return TRUE if "lbuf" is empty or only contains blanks.
1763 */
1764 int
1765vim_isblankline(lbuf)
1766 char_u *lbuf;
1767{
1768 char_u *p;
1769
1770 p = skipwhite(lbuf);
1771 return (*p == NUL || *p == '\r' || *p == '\n');
1772}
1773
1774/*
1775 * Convert a string into a long and/or unsigned long, taking care of
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00001776 * hexadecimal and octal numbers. Accepts a '-' sign.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001777 * If "hexp" is not NULL, returns a flag to indicate the type of the number:
1778 * 0 decimal
1779 * '0' octal
1780 * 'X' hex
1781 * 'x' hex
1782 * If "len" is not NULL, the length of the number in characters is returned.
1783 * If "nptr" is not NULL, the signed result is returned in it.
1784 * If "unptr" is not NULL, the unsigned result is returned in it.
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001785 * If "dooct" is non-zero recognize octal numbers, when > 1 always assume
1786 * octal number.
Bram Moolenaar97b2ad32006-03-18 21:40:56 +00001787 * If "dohex" is non-zero recognize hex numbers, when > 1 always assume
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001788 * hex number.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001789 */
1790 void
1791vim_str2nr(start, hexp, len, dooct, dohex, nptr, unptr)
1792 char_u *start;
1793 int *hexp; /* return: type of number 0 = decimal, 'x'
1794 or 'X' is hex, '0' = octal */
1795 int *len; /* return: detected length of number */
1796 int dooct; /* recognize octal number */
1797 int dohex; /* recognize hex number */
1798 long *nptr; /* return: signed result */
1799 unsigned long *unptr; /* return: unsigned result */
1800{
1801 char_u *ptr = start;
1802 int hex = 0; /* default is decimal */
1803 int negative = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001804 unsigned long un = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001805 int n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001806
1807 if (ptr[0] == '-')
1808 {
1809 negative = TRUE;
1810 ++ptr;
1811 }
1812
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001813 /* Recognize hex and octal. */
1814 if (ptr[0] == '0' && ptr[1] != '8' && ptr[1] != '9')
Bram Moolenaar071d4272004-06-13 20:20:40 +00001815 {
1816 hex = ptr[1];
1817 if (dohex && (hex == 'X' || hex == 'x') && vim_isxdigit(ptr[2]))
1818 ptr += 2; /* hexadecimal */
1819 else
1820 {
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001821 hex = 0; /* default is decimal */
1822 if (dooct)
1823 {
1824 /* Don't interpret "0", "08" or "0129" as octal. */
1825 for (n = 1; VIM_ISDIGIT(ptr[n]); ++n)
1826 {
1827 if (ptr[n] > '7')
1828 {
1829 hex = 0; /* can't be octal */
1830 break;
1831 }
1832 if (ptr[n] > '0')
1833 hex = '0'; /* assume octal */
1834 }
1835 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001836 }
1837 }
1838
1839 /*
1840 * Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
1841 */
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001842 if (hex == '0' || dooct > 1)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001843 {
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001844 /* octal */
1845 while ('0' <= *ptr && *ptr <= '7')
Bram Moolenaar071d4272004-06-13 20:20:40 +00001846 {
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001847 un = 8 * un + (unsigned long)(*ptr - '0');
1848 ++ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001849 }
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001850 }
1851 else if (hex != 0 || dohex > 1)
1852 {
1853 /* hex */
1854 while (vim_isxdigit(*ptr))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001855 {
Bram Moolenaar5c06f8b2005-05-31 22:14:58 +00001856 un = 16 * un + (unsigned long)hex2nr(*ptr);
1857 ++ptr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001858 }
1859 }
1860 else
1861 {
1862 /* decimal */
1863 while (VIM_ISDIGIT(*ptr))
1864 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001865 un = 10 * un + (unsigned long)(*ptr - '0');
1866 ++ptr;
1867 }
1868 }
1869
Bram Moolenaar071d4272004-06-13 20:20:40 +00001870 if (hexp != NULL)
1871 *hexp = hex;
1872 if (len != NULL)
1873 *len = (int)(ptr - start);
1874 if (nptr != NULL)
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00001875 {
1876 if (negative) /* account for leading '-' for decimal numbers */
1877 *nptr = -(long)un;
1878 else
1879 *nptr = (long)un;
1880 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001881 if (unptr != NULL)
1882 *unptr = un;
1883}
1884
1885/*
1886 * Return the value of a single hex character.
1887 * Only valid when the argument is '0' - '9', 'A' - 'F' or 'a' - 'f'.
1888 */
1889 int
1890hex2nr(c)
1891 int c;
1892{
1893 if (c >= 'a' && c <= 'f')
1894 return c - 'a' + 10;
1895 if (c >= 'A' && c <= 'F')
1896 return c - 'A' + 10;
1897 return c - '0';
1898}
1899
1900#if defined(FEAT_TERMRESPONSE) \
1901 || (defined(FEAT_GUI_GTK) && defined(FEAT_WINDOWS)) || defined(PROTO)
1902/*
1903 * Convert two hex characters to a byte.
1904 * Return -1 if one of the characters is not hex.
1905 */
1906 int
1907hexhex2nr(p)
1908 char_u *p;
1909{
1910 if (!vim_isxdigit(p[0]) || !vim_isxdigit(p[1]))
1911 return -1;
1912 return (hex2nr(p[0]) << 4) + hex2nr(p[1]);
1913}
1914#endif
1915
1916/*
1917 * Return TRUE if "str" starts with a backslash that should be removed.
1918 * For MS-DOS, WIN32 and OS/2 this is only done when the character after the
1919 * backslash is not a normal file name character.
1920 * '$' is a valid file name character, we don't remove the backslash before
1921 * it. This means it is not possible to use an environment variable after a
1922 * backslash. "C:\$VIM\doc" is taken literally, only "$VIM\doc" works.
1923 * Although "\ name" is valid, the backslash in "Program\ files" must be
1924 * removed. Assume a file name doesn't start with a space.
1925 * For multi-byte names, never remove a backslash before a non-ascii
1926 * character, assume that all multi-byte characters are valid file name
1927 * characters.
1928 */
1929 int
1930rem_backslash(str)
1931 char_u *str;
1932{
1933#ifdef BACKSLASH_IN_FILENAME
1934 return (str[0] == '\\'
1935# ifdef FEAT_MBYTE
1936 && str[1] < 0x80
1937# endif
1938 && (str[1] == ' '
1939 || (str[1] != NUL
1940 && str[1] != '*'
1941 && str[1] != '?'
1942 && !vim_isfilec(str[1]))));
1943#else
1944 return (str[0] == '\\' && str[1] != NUL);
1945#endif
1946}
1947
1948/*
1949 * Halve the number of backslashes in a file name argument.
1950 * For MS-DOS we only do this if the character after the backslash
1951 * is not a normal file character.
1952 */
1953 void
1954backslash_halve(p)
1955 char_u *p;
1956{
1957 for ( ; *p; ++p)
1958 if (rem_backslash(p))
Bram Moolenaar446cb832008-06-24 21:56:24 +00001959 STRMOVE(p, p + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001960}
1961
1962/*
1963 * backslash_halve() plus save the result in allocated memory.
1964 */
1965 char_u *
1966backslash_halve_save(p)
1967 char_u *p;
1968{
1969 char_u *res;
1970
1971 res = vim_strsave(p);
1972 if (res == NULL)
1973 return p;
1974 backslash_halve(res);
1975 return res;
1976}
1977
1978#if (defined(EBCDIC) && defined(FEAT_POSTSCRIPT)) || defined(PROTO)
1979/*
1980 * Table for EBCDIC to ASCII conversion unashamedly taken from xxd.c!
1981 * The first 64 entries have been added to map control characters defined in
1982 * ascii.h
1983 */
1984static char_u ebcdic2ascii_tab[256] =
1985{
1986 0000, 0001, 0002, 0003, 0004, 0011, 0006, 0177,
1987 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
1988 0020, 0021, 0022, 0023, 0024, 0012, 0010, 0027,
1989 0030, 0031, 0032, 0033, 0033, 0035, 0036, 0037,
1990 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
1991 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
1992 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
1993 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
1994 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246,
1995 0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174,
1996 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
1997 0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176,
1998 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267,
1999 0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077,
2000 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
2001 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042,
2002 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
2003 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311,
2004 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160,
2005 0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320,
2006 0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170,
2007 0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327,
2008 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
2009 0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347,
2010 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
2011 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355,
2012 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120,
2013 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363,
2014 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130,
2015 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
2016 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
2017 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377
2018};
2019
2020/*
2021 * Convert a buffer worth of characters from EBCDIC to ASCII. Only useful if
2022 * wanting 7-bit ASCII characters out the other end.
2023 */
2024 void
2025ebcdic2ascii(buffer, len)
2026 char_u *buffer;
2027 int len;
2028{
2029 int i;
2030
2031 for (i = 0; i < len; i++)
2032 buffer[i] = ebcdic2ascii_tab[buffer[i]];
2033}
2034#endif