blob: 336eec62443241cd355902ae66eb2941f7a9f25a [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
17static int win_nolbr_chartabsize __ARGS((win_T *wp, char_u *s, colnr_T col, int *headp));
18#endif
19
20static int nr2hex __ARGS((int c));
21
22static int chartab_initialized = FALSE;
23
24/* b_chartab[] is an array of 32 bytes, each bit representing one of the
25 * characters 0-255. */
26#define SET_CHARTAB(buf, c) (buf)->b_chartab[(unsigned)(c) >> 3] |= (1 << ((c) & 0x7))
27#define RESET_CHARTAB(buf, c) (buf)->b_chartab[(unsigned)(c) >> 3] &= ~(1 << ((c) & 0x7))
28#define GET_CHARTAB(buf, c) ((buf)->b_chartab[(unsigned)(c) >> 3] & (1 << ((c) & 0x7)))
29
30/*
31 * Fill chartab[]. Also fills curbuf->b_chartab[] with flags for keyword
32 * characters for current buffer.
33 *
34 * Depends on the option settings 'iskeyword', 'isident', 'isfname',
35 * 'isprint' and 'encoding'.
36 *
37 * The index in chartab[] depends on 'encoding':
38 * - For non-multi-byte index with the byte (same as the character).
39 * - For DBCS index with the first byte.
40 * - For UTF-8 index with the character (when first byte is up to 0x80 it is
41 * the same as the character, if the first byte is 0x80 and above it depends
42 * on further bytes).
43 *
44 * The contents of chartab[]:
45 * - The lower two bits, masked by CT_CELL_MASK, give the number of display
46 * cells the character occupies (1 or 2). Not valid for UTF-8 above 0x80.
47 * - CT_PRINT_CHAR bit is set when the character is printable (no need to
48 * translate the character before displaying it). Note that only DBCS
49 * characters can have 2 display cells and still be printable.
50 * - CT_FNAME_CHAR bit is set when the character can be in a file name.
51 * - CT_ID_CHAR bit is set when the character can be in an identifier.
52 *
53 * Return FAIL if 'iskeyword', 'isident', 'isfname' or 'isprint' option has an
54 * error, OK otherwise.
55 */
56 int
57init_chartab()
58{
59 return buf_init_chartab(curbuf, TRUE);
60}
61
62 int
63buf_init_chartab(buf, global)
64 buf_T *buf;
65 int global; /* FALSE: only set buf->b_chartab[] */
66{
67 int c;
68 int c2;
69 char_u *p;
70 int i;
71 int tilde;
72 int do_isalpha;
73
74 if (global)
75 {
76 /*
77 * Set the default size for printable characters:
78 * From <Space> to '~' is 1 (printable), others are 2 (not printable).
79 * This also inits all 'isident' and 'isfname' flags to FALSE.
80 *
81 * EBCDIC: all chars below ' ' are not printable, all others are
82 * printable.
83 */
84 c = 0;
85 while (c < ' ')
86 chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2;
87#ifdef EBCDIC
88 while (c < 255)
89#else
90 while (c <= '~')
91#endif
92 chartab[c++] = 1 + CT_PRINT_CHAR;
93#ifdef FEAT_FKMAP
94 if (p_altkeymap)
95 {
96 while (c < YE)
97 chartab[c++] = 1 + CT_PRINT_CHAR;
98 }
99#endif
100 while (c < 256)
101 {
102#ifdef FEAT_MBYTE
103 /* UTF-8: bytes 0xa0 - 0xff are printable (latin1) */
104 if (enc_utf8 && c >= 0xa0)
105 chartab[c++] = CT_PRINT_CHAR + 1;
106 /* euc-jp characters starting with 0x8e are single width */
107 else if (enc_dbcs == DBCS_JPNU && c == 0x8e)
108 chartab[c++] = CT_PRINT_CHAR + 1;
109 /* other double-byte chars can be printable AND double-width */
110 else if (enc_dbcs != 0 && MB_BYTE2LEN(c) == 2)
111 chartab[c++] = CT_PRINT_CHAR + 2;
112 else
113#endif
114 /* the rest is unprintable by default */
115 chartab[c++] = (dy_flags & DY_UHEX) ? 4 : 2;
116 }
117
118#ifdef FEAT_MBYTE
119 /* Assume that every multi-byte char is a filename character. */
120 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))
124 chartab[c] |= CT_FNAME_CHAR;
125#endif
126 }
127
128 /*
129 * Init word char flags all to FALSE
130 */
131 vim_memset(buf->b_chartab, 0, (size_t)32);
132#ifdef FEAT_MBYTE
133 for (c = 0; c < 256; ++c)
134 {
135 /* double-byte characters are probably word characters */
136 if (enc_dbcs != 0 && MB_BYTE2LEN(c) == 2)
137 SET_CHARTAB(buf, c);
138 }
139#endif
140
141#ifdef FEAT_LISP
142 /*
143 * In lisp mode the '-' character is included in keywords.
144 */
145 if (buf->b_p_lisp)
146 SET_CHARTAB(buf, '-');
147#endif
148
149 /* Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint'
150 * options Each option is a list of characters, character numbers or
151 * ranges, separated by commas, e.g.: "200-210,x,#-178,-"
152 */
153 for (i = global ? 0 : 3; i <= 3; ++i)
154 {
155 if (i == 0)
156 p = p_isi; /* first round: 'isident' */
157 else if (i == 1)
158 p = p_isp; /* second round: 'isprint' */
159 else if (i == 2)
160 p = p_isf; /* third round: 'isfname' */
161 else /* i == 3 */
162 p = buf->b_p_isk; /* fourth round: 'iskeyword' */
163
164 while (*p)
165 {
166 tilde = FALSE;
167 do_isalpha = FALSE;
168 if (*p == '^' && p[1] != NUL)
169 {
170 tilde = TRUE;
171 ++p;
172 }
173 if (VIM_ISDIGIT(*p))
174 c = getdigits(&p);
175 else
176 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
184 c2 = *p++;
185 }
186 if (c <= 0 || (c2 < c && c2 != -1) || c2 >= 256
187 || !(*p == NUL || *p == ','))
188 return FAIL;
189
190 if (c2 == -1) /* not a range */
191 {
192 /*
193 * A single '@' (not "@-@"):
194 * Decide on letters being ID/printable/keyword chars with
195 * standard function isalpha(). This takes care of locale for
196 * single-byte characters).
197 */
198 if (c == '@')
199 {
200 do_isalpha = TRUE;
201 c = 1;
202 c2 = 255;
203 }
204 else
205 c2 = c;
206 }
207 while (c <= c2)
208 {
209 if (!do_isalpha || isalpha(c)
210#ifdef FEAT_FKMAP
211 || (p_altkeymap && (F_isalpha(c) || F_isdigit(c)))
212#endif
213 )
214 {
215 if (i == 0) /* (re)set ID flag */
216 {
217 if (tilde)
218 chartab[c] &= ~CT_ID_CHAR;
219 else
220 chartab[c] |= CT_ID_CHAR;
221 }
222 else if (i == 1) /* (re)set printable */
223 {
224 if ((c < ' '
225#ifndef EBCDIC
226 || c > '~'
227#endif
228#ifdef FEAT_FKMAP
229 || (p_altkeymap
230 && (F_isalpha(c) || F_isdigit(c)))
231#endif
232 )
233#ifdef FEAT_MBYTE
234 /* For double-byte we keep the cell width, so
235 * that we can detect it from the first byte. */
236 && !(enc_dbcs && MB_BYTE2LEN(c) == 2)
237#endif
238 )
239 {
240 if (tilde)
241 {
242 chartab[c] = (chartab[c] & ~CT_CELL_MASK)
243 + ((dy_flags & DY_UHEX) ? 4 : 2);
244 chartab[c] &= ~CT_PRINT_CHAR;
245 }
246 else
247 {
248 chartab[c] = (chartab[c] & ~CT_CELL_MASK) + 1;
249 chartab[c] |= CT_PRINT_CHAR;
250 }
251 }
252 }
253 else if (i == 2) /* (re)set fname flag */
254 {
255 if (tilde)
256 chartab[c] &= ~CT_FNAME_CHAR;
257 else
258 chartab[c] |= CT_FNAME_CHAR;
259 }
260 else /* i == 3 */ /* (re)set keyword flag */
261 {
262 if (tilde)
263 RESET_CHARTAB(buf, c);
264 else
265 SET_CHARTAB(buf, c);
266 }
267 }
268 ++c;
269 }
270 p = skip_to_option_part(p);
271 }
272 }
273 chartab_initialized = TRUE;
274 return OK;
275}
276
277/*
278 * Translate any special characters in buf[bufsize] in-place.
279 * The result is a string with only printable characters, but if there is not
280 * enough room, not all characters will be translated.
281 */
282 void
283trans_characters(buf, bufsize)
284 char_u *buf;
285 int bufsize;
286{
287 int len; /* length of string needing translation */
288 int room; /* room in buffer after string */
289 char_u *trs; /* translated character */
290 int trs_len; /* length of trs[] */
291
292 len = (int)STRLEN(buf);
293 room = bufsize - len;
294 while (*buf != 0)
295 {
296# ifdef FEAT_MBYTE
297 /* Assume a multi-byte character doesn't need translation. */
298 if (has_mbyte && (trs_len = (*mb_ptr2len_check)(buf)) > 1)
299 len -= trs_len;
300 else
301# endif
302 {
303 trs = transchar_byte(*buf);
304 trs_len = (int)STRLEN(trs);
305 if (trs_len > 1)
306 {
307 room -= trs_len - 1;
308 if (room <= 0)
309 return;
310 mch_memmove(buf + trs_len, buf + 1, (size_t)len);
311 }
312 mch_memmove(buf, trs, (size_t)trs_len);
313 --len;
314 }
315 buf += trs_len;
316 }
317}
318
319#if defined(FEAT_EVAL) || defined(FEAT_TITLE) || defined(PROTO)
320/*
321 * Translate a string into allocated memory, replacing special chars with
322 * printable chars. Returns NULL when out of memory.
323 */
324 char_u *
325transstr(s)
326 char_u *s;
327{
328 char_u *res;
329 char_u *p;
330#ifdef FEAT_MBYTE
331 int l, len, c;
332 char_u hexbuf[11];
333#endif
334
335#ifdef FEAT_MBYTE
336 if (has_mbyte)
337 {
338 /* Compute the length of the result, taking account of unprintable
339 * multi-byte characters. */
340 len = 0;
341 p = s;
342 while (*p != NUL)
343 {
344 if ((l = (*mb_ptr2len_check)(p)) > 1)
345 {
346 c = (*mb_ptr2char)(p);
347 p += l;
348 if (vim_isprintc(c))
349 len += l;
350 else
351 {
352 transchar_hex(hexbuf, c);
353 len += STRLEN(hexbuf);
354 }
355 }
356 else
357 {
358 l = byte2cells(*p++);
359 if (l > 0)
360 len += l;
361 else
362 len += 4; /* illegal byte sequence */
363 }
364 }
365 res = alloc((unsigned)(len + 1));
366 }
367 else
368#endif
369 res = alloc((unsigned)(vim_strsize(s) + 1));
370 if (res != NULL)
371 {
372 *res = NUL;
373 p = s;
374 while (*p != NUL)
375 {
376#ifdef FEAT_MBYTE
377 if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
378 {
379 c = (*mb_ptr2char)(p);
380 if (vim_isprintc(c))
381 STRNCAT(res, p, l); /* append printable multi-byte char */
382 else
383 transchar_hex(res + STRLEN(res), c);
384 p += l;
385 }
386 else
387#endif
388 STRCAT(res, transchar_byte(*p++));
389 }
390 }
391 return res;
392}
393#endif
394
395#if defined(FEAT_SYN_HL) || defined(FEAT_INS_EXPAND) || defined(PROTO)
396/*
397 * Convert the string "p[len]" to do ignore-case comparing. Uses the current
398 * locale. Returns an allocated string (NULL for out-of-memory).
399 */
400 char_u *
401str_foldcase(str, len)
402 char_u *str;
403 int len;
404{
405 garray_T ga;
406 int i;
407
408#define GA_CHAR(i) ((char_u *)ga.ga_data)[i]
409#define GA_PTR(i) ((char_u *)ga.ga_data + i)
410
411 /* Copy "str" into allocated memory, unmodified. */
412 ga_init2(&ga, 1, 10);
413 if (ga_grow(&ga, len + 1) == FAIL)
414 return NULL;
415 mch_memmove(ga.ga_data, str, (size_t)len);
416 GA_CHAR(len) = NUL;
417 ga.ga_len = len;
418 ga.ga_room -= len;
419
420 /* Make each character lower case. */
421 i = 0;
422 while (GA_CHAR(i) != NUL)
423 {
424#ifdef FEAT_MBYTE
425 if (enc_utf8 || (has_mbyte && MB_BYTE2LEN(GA_CHAR(i)) > 1))
426 {
427 if (enc_utf8)
428 {
429 int c, lc;
430
431 c = utf_ptr2char(GA_PTR(i));
432 lc = utf_tolower(c);
433 if (c != lc)
434 {
435 int ol = utf_char2len(c);
436 int nl = utf_char2len(lc);
437
438 /* If the byte length changes need to shift the following
439 * characters forward or backward. */
440 if (ol != nl)
441 {
442 if (nl > ol)
443 if (ga_grow(&ga, nl - ol) == FAIL)
444 {
445 /* out of memory, keep old char */
446 lc = c;
447 nl = ol;
448 }
449 if (ol != nl)
450 {
451 mch_memmove(GA_PTR(i) + nl, GA_PTR(i) + ol,
452 STRLEN(GA_PTR(i) + ol) + 1);
453 ga.ga_len += nl - ol;
454 ga.ga_room -= nl - ol;
455 }
456 }
457 (void)utf_char2bytes(lc, GA_PTR(i));
458 }
459 }
460 /* skip to next multi-byte char */
461 i += (*mb_ptr2len_check)(GA_PTR(i));
462 }
463 else
464#endif
465 {
466 GA_CHAR(i) = TOLOWER_LOC(GA_CHAR(i));
467 ++i;
468 }
469 }
470
471 return (char_u *)ga.ga_data;
472}
473#endif
474
475/*
476 * Catch 22: chartab[] can't be initialized before the options are
477 * initialized, and initializing options may cause transchar() to be called!
478 * When chartab_initialized == FALSE don't use chartab[].
479 * Does NOT work for multi-byte characters, c must be <= 255.
480 * Also doesn't work for the first byte of a multi-byte, "c" must be a
481 * character!
482 */
483static char_u transchar_buf[7];
484
485 char_u *
486transchar(c)
487 int c;
488{
489 int i;
490
491 i = 0;
492 if (IS_SPECIAL(c)) /* special key code, display as ~@ char */
493 {
494 transchar_buf[0] = '~';
495 transchar_buf[1] = '@';
496 i = 2;
497 c = K_SECOND(c);
498 }
499
500 if ((!chartab_initialized && (
501#ifdef EBCDIC
502 (c >= 64 && c < 255)
503#else
504 (c >= ' ' && c <= '~')
505#endif
506#ifdef FEAT_FKMAP
507 || F_ischar(c)
508#endif
509 )) || (c < 256 && vim_isprintc_strict(c)))
510 {
511 /* printable character */
512 transchar_buf[i] = c;
513 transchar_buf[i + 1] = NUL;
514 }
515 else
516 transchar_nonprint(transchar_buf + i, c);
517 return transchar_buf;
518}
519
520#if defined(FEAT_MBYTE) || defined(PROTO)
521/*
522 * Like transchar(), but called with a byte instead of a character. Checks
523 * for an illegal UTF-8 byte.
524 */
525 char_u *
526transchar_byte(c)
527 int c;
528{
529 if (enc_utf8 && c >= 0x80)
530 {
531 transchar_nonprint(transchar_buf, c);
532 return transchar_buf;
533 }
534 return transchar(c);
535}
536#endif
537
538/*
539 * Convert non-printable character to two or more printable characters in
540 * "buf[]". "buf" needs to be able to hold five bytes.
541 * Does NOT work for multi-byte characters, c must be <= 255.
542 */
543 void
544transchar_nonprint(buf, c)
545 char_u *buf;
546 int c;
547{
548 if (c == NL)
549 c = NUL; /* we use newline in place of a NUL */
550 else if (c == CAR && get_fileformat(curbuf) == EOL_MAC)
551 c = NL; /* we use CR in place of NL in this case */
552
553 if (dy_flags & DY_UHEX) /* 'display' has "uhex" */
554 transchar_hex(buf, c);
555
556#ifdef EBCDIC
557 /* For EBCDIC only the characters 0-63 and 255 are not printable */
558 else if (CtrlChar(c) != 0 || c == DEL)
559#else
560 else if (c <= 0x7f) /* 0x00 - 0x1f and 0x7f */
561#endif
562 {
563 buf[0] = '^';
564#ifdef EBCDIC
565 if (c == DEL)
566 buf[1] = '?'; /* DEL displayed as ^? */
567 else
568 buf[1] = CtrlChar(c);
569#else
570 buf[1] = c ^ 0x40; /* DEL displayed as ^? */
571#endif
572
573 buf[2] = NUL;
574 }
575#ifdef FEAT_MBYTE
576 else if (enc_utf8 && c >= 0x80)
577 {
578 transchar_hex(buf, c);
579 }
580#endif
581#ifndef EBCDIC
582 else if (c >= ' ' + 0x80 && c <= '~' + 0x80) /* 0xa0 - 0xfe */
583 {
584 buf[0] = '|';
585 buf[1] = c - 0x80;
586 buf[2] = NUL;
587 }
588#else
589 else if (c < 64)
590 {
591 buf[0] = '~';
592 buf[1] = MetaChar(c);
593 buf[2] = NUL;
594 }
595#endif
596 else /* 0x80 - 0x9f and 0xff */
597 {
598 /*
599 * TODO: EBCDIC I don't know what to do with this chars, so I display
600 * them as '~?' for now
601 */
602 buf[0] = '~';
603#ifdef EBCDIC
604 buf[1] = '?'; /* 0xff displayed as ~? */
605#else
606 buf[1] = (c - 0x80) ^ 0x40; /* 0xff displayed as ~? */
607#endif
608 buf[2] = NUL;
609 }
610}
611
612 void
613transchar_hex(buf, c)
614 char_u *buf;
615 int c;
616{
617 int i = 0;
618
619 buf[0] = '<';
620#ifdef FEAT_MBYTE
621 if (c > 255)
622 {
623 buf[++i] = nr2hex((unsigned)c >> 12);
624 buf[++i] = nr2hex((unsigned)c >> 8);
625 }
626#endif
627 buf[++i] = nr2hex((unsigned)c >> 4);
628 buf[++i] = nr2hex(c);
629 buf[++i] = '>';
630 buf[++i] = NUL;
631}
632
633/*
634 * Convert the lower 4 bits of byte "c" to its hex character.
635 * Lower case letters are used to avoid the confusion of <F1> being 0xf1 or
636 * function key 1.
637 */
638 static int
639nr2hex(c)
640 int c;
641{
642 if ((c & 0xf) <= 9)
643 return (c & 0xf) + '0';
644 return (c & 0xf) - 10 + 'a';
645}
646
647/*
648 * Return number of display cells occupied by byte "b".
649 * Caller must make sure 0 <= b <= 255.
650 * For multi-byte mode "b" must be the first byte of a character.
651 * A TAB is counted as two cells: "^I".
652 * For UTF-8 mode this will return 0 for bytes >= 0x80, because the number of
653 * cells depends on further bytes.
654 */
655 int
656byte2cells(b)
657 int b;
658{
659#ifdef FEAT_MBYTE
660 if (enc_utf8 && b >= 0x80)
661 return 0;
662#endif
663 return (chartab[b] & CT_CELL_MASK);
664}
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
672char2cells(c)
673 int c;
674{
675 if (IS_SPECIAL(c))
676 return char2cells(K_SECOND(c)) + 2;
677#ifdef FEAT_MBYTE
678 if (c >= 0x80)
679 {
680 /* UTF-8: above 0x80 need to check the value */
681 if (enc_utf8)
682 return utf_char2cells(c);
683 /* DBCS: double-byte means double-width, except for euc-jp with first
684 * byte 0x8e */
685 if (enc_dbcs != 0 && c >= 0x100)
686 {
687 if (enc_dbcs == DBCS_JPNU && ((unsigned)c >> 8) == 0x8e)
688 return 1;
689 return 2;
690 }
691 }
692#endif
693 return (chartab[c & 0xff] & CT_CELL_MASK);
694}
695
696/*
697 * Return number of display cells occupied by character at "*p".
698 * A TAB is counted as two cells: "^I" or four: "<09>".
699 */
700 int
701ptr2cells(p)
702 char_u *p;
703{
704#ifdef FEAT_MBYTE
705 /* For UTF-8 we need to look at more bytes if the first byte is >= 0x80. */
706 if (enc_utf8 && *p >= 0x80)
707 return utf_ptr2cells(p);
708 /* For DBCS we can tell the cell count from the first byte. */
709#endif
710 return (chartab[*p] & CT_CELL_MASK);
711}
712
713/*
714 * Return the number of characters string "s" will take on the screen,
715 * counting TABs as two characters: "^I".
716 */
717 int
718vim_strsize(s)
719 char_u *s;
720{
721 return vim_strnsize(s, (int)MAXCOL);
722}
723
724/*
725 * Return the number of characters string "s[len]" will take on the screen,
726 * counting TABs as two characters: "^I".
727 */
728 int
729vim_strnsize(s, len)
730 char_u *s;
731 int len;
732{
733 int size = 0;
734
735 while (*s != NUL && --len >= 0)
736 {
737#ifdef FEAT_MBYTE
738 if (has_mbyte)
739 {
740 int l = (*mb_ptr2len_check)(s);
741
742 size += ptr2cells(s);
743 s += l;
744 len -= l - 1;
745 }
746 else
747#endif
748 size += byte2cells(*s++);
749 }
750 return size;
751}
752
753/*
754 * Return the number of characters 'c' will take on the screen, taking
755 * into account the size of a tab.
756 * Use a define to make it fast, this is used very often!!!
757 * Also see getvcol() below.
758 */
759
760#define RET_WIN_BUF_CHARTABSIZE(wp, buf, p, col) \
761 if (*(p) == TAB && (!(wp)->w_p_list || lcs_tab1)) \
762 { \
763 int ts; \
764 ts = (buf)->b_p_ts; \
765 return (int)(ts - (col % ts)); \
766 } \
767 else \
768 return ptr2cells(p);
769
770#if defined(FEAT_VREPLACE) || defined(FEAT_EX_EXTRA) || defined(FEAT_GUI) \
771 || defined(FEAT_VIRTUALEDIT) || defined(PROTO)
772 int
773chartabsize(p, col)
774 char_u *p;
775 colnr_T col;
776{
777 RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, p, col)
778}
779#endif
780
781#ifdef FEAT_LINEBREAK
782 static int
783win_chartabsize(wp, p, col)
784 win_T *wp;
785 char_u *p;
786 colnr_T col;
787{
788 RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, p, col)
789}
790#endif
791
792/*
793 * return the number of characters the string 's' will take on the screen,
794 * taking into account the size of a tab
795 */
796 int
797linetabsize(s)
798 char_u *s;
799{
800 colnr_T col = 0;
801
802 while (*s != NUL)
803 col += lbr_chartabsize_adv(&s, col);
804 return (int)col;
805}
806
807/*
808 * Like linetabsize(), but for a given window instead of the current one.
809 */
810 int
811win_linetabsize(wp, p, len)
812 win_T *wp;
813 char_u *p;
814 colnr_T len;
815{
816 colnr_T col = 0;
817 char_u *s;
818
819 for (s = p; *s != NUL && (len == MAXCOL || s < p + len); )
820 {
821 col += win_lbr_chartabsize(wp, s, col, NULL);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000822 mb_ptr_adv(s);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000823 }
824 return (int)col;
825}
826
827/*
828 * return TRUE if 'c' is a normal identifier character
829 * letters and characters from 'isident' option.
830 */
831 int
832vim_isIDc(c)
833 int c;
834{
835 return (c > 0 && c < 0x100 && (chartab[c] & CT_ID_CHAR));
836}
837
838/*
839 * return TRUE if 'c' is a keyword character: Letters and characters from
840 * 'iskeyword' option for current buffer.
841 * For multi-byte characters mb_get_class() is used (builtin rules).
842 */
843 int
844vim_iswordc(c)
845 int c;
846{
847#ifdef FEAT_MBYTE
848 if (c >= 0x100)
849 {
850 if (enc_dbcs != 0)
851 return dbcs_class((unsigned)c >> 8, c & 0xff) >= 2;
852 if (enc_utf8)
853 return utf_class(c) >= 2;
854 }
855#endif
856 return (c > 0 && c < 0x100 && GET_CHARTAB(curbuf, c) != 0);
857}
858
859/*
860 * Just like vim_iswordc() but uses a pointer to the (multi-byte) character.
861 */
862 int
863vim_iswordp(p)
864 char_u *p;
865{
866#ifdef FEAT_MBYTE
867 if (has_mbyte && MB_BYTE2LEN(*p) > 1)
868 return mb_get_class(p) >= 2;
869#endif
870 return GET_CHARTAB(curbuf, *p) != 0;
871}
872
873#if defined(FEAT_SYN_HL) || defined(PROTO)
874 int
875vim_iswordc_buf(p, buf)
876 char_u *p;
877 buf_T *buf;
878{
879# ifdef FEAT_MBYTE
880 if (has_mbyte && MB_BYTE2LEN(*p) > 1)
881 return mb_get_class(p) >= 2;
882# endif
883 return (GET_CHARTAB(buf, *p) != 0);
884}
885#endif
886
887/*
888 * return TRUE if 'c' is a valid file-name character
889 * Assume characters above 0x100 are valid (multi-byte).
890 */
891 int
892vim_isfilec(c)
893 int c;
894{
895 return (c >= 0x100 || (c > 0 && (chartab[c] & CT_FNAME_CHAR)));
896}
897
898/*
899 * return TRUE if 'c' is a printable character
900 * Assume characters above 0x100 are printable (multi-byte), except for
901 * Unicode.
902 */
903 int
904vim_isprintc(c)
905 int c;
906{
907#ifdef FEAT_MBYTE
908 if (enc_utf8 && c >= 0x100)
909 return utf_printable(c);
910#endif
911 return (c >= 0x100 || (c > 0 && (chartab[c] & CT_PRINT_CHAR)));
912}
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
919vim_isprintc_strict(c)
920 int c;
921{
922#ifdef FEAT_MBYTE
923 if (enc_dbcs != 0 && c < 0x100 && MB_BYTE2LEN(c) > 1)
924 return FALSE;
925 if (enc_utf8 && c >= 0x100)
926 return utf_printable(c);
927#endif
928 return (c >= 0x100 || (c > 0 && (chartab[c] & CT_PRINT_CHAR)));
929}
930
931/*
932 * like chartabsize(), but also check for line breaks on the screen
933 */
934 int
935lbr_chartabsize(s, col)
936 unsigned char *s;
937 colnr_T col;
938{
939#ifdef FEAT_LINEBREAK
940 if (!curwin->w_p_lbr && *p_sbr == NUL)
941 {
942#endif
943#ifdef FEAT_MBYTE
944 if (curwin->w_p_wrap)
945 return win_nolbr_chartabsize(curwin, s, col, NULL);
946#endif
947 RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, s, col)
948#ifdef FEAT_LINEBREAK
949 }
950 return win_lbr_chartabsize(curwin, s, col, NULL);
951#endif
952}
953
954/*
955 * Call lbr_chartabsize() and advance the pointer.
956 */
957 int
958lbr_chartabsize_adv(s, col)
959 char_u **s;
960 colnr_T col;
961{
962 int retval;
963
964 retval = lbr_chartabsize(*s, col);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000965 mb_ptr_adv(*s);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000966 return retval;
967}
968
969/*
970 * This function is used very often, keep it fast!!!!
971 *
972 * If "headp" not NULL, set *headp to the size of what we for 'showbreak'
973 * string at start of line. Warning: *headp is only set if it's a non-zero
974 * value, init to 0 before calling.
975 */
976/*ARGSUSED*/
977 int
978win_lbr_chartabsize(wp, s, col, headp)
979 win_T *wp;
980 char_u *s;
981 colnr_T col;
982 int *headp;
983{
984#ifdef FEAT_LINEBREAK
985 int c;
986 int size;
987 colnr_T col2;
988 colnr_T colmax;
989 int added;
990# ifdef FEAT_MBYTE
991 int mb_added = 0;
992# else
993# define mb_added 0
994# endif
995 int numberextra;
996 char_u *ps;
997 int tab_corr = (*s == TAB);
998
999 /*
1000 * No 'linebreak' and 'showbreak': return quickly.
1001 */
1002 if (!wp->w_p_lbr && *p_sbr == NUL)
1003#endif
1004 {
1005#ifdef FEAT_MBYTE
1006 if (wp->w_p_wrap)
1007 return win_nolbr_chartabsize(wp, s, col, headp);
1008#endif
1009 RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, s, col)
1010 }
1011
1012#ifdef FEAT_LINEBREAK
1013 /*
1014 * First get normal size, without 'linebreak'
1015 */
1016 size = win_chartabsize(wp, s, col);
1017 c = *s;
1018
1019 /*
1020 * If 'linebreak' set check at a blank before a non-blank if the line
1021 * needs a break here
1022 */
1023 if (wp->w_p_lbr
1024 && vim_isbreak(c)
1025 && !vim_isbreak(s[1])
1026 && !wp->w_p_list
1027 && wp->w_p_wrap
1028# ifdef FEAT_VERTSPLIT
1029 && wp->w_width != 0
1030# endif
1031 )
1032 {
1033 /*
1034 * Count all characters from first non-blank after a blank up to next
1035 * non-blank after a blank.
1036 */
1037 numberextra = win_col_off(wp);
1038 col2 = col;
1039 colmax = W_WIDTH(wp) - numberextra;
1040 if (col >= colmax)
1041 colmax += (((col - colmax)
1042 / (colmax + win_col_off2(wp))) + 1)
1043 * (colmax + win_col_off2(wp));
1044 for (;;)
1045 {
1046 ps = s;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001047 mb_ptr_adv(s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001048 c = *s;
1049 if (!(c != NUL
1050 && (vim_isbreak(c)
1051 || (!vim_isbreak(c)
1052 && (col2 == col || !vim_isbreak(*ps))))))
1053 break;
1054
1055 col2 += win_chartabsize(wp, s, col2);
1056 if (col2 >= colmax) /* doesn't fit */
1057 {
1058 size = colmax - col;
1059 tab_corr = FALSE;
1060 break;
1061 }
1062 }
1063 }
1064# ifdef FEAT_MBYTE
1065 else if (has_mbyte && size == 2 && MB_BYTE2LEN(*s) > 1
1066 && wp->w_p_wrap && in_win_border(wp, col))
1067 {
1068 ++size; /* Count the ">" in the last column. */
1069 mb_added = 1;
1070 }
1071# endif
1072
1073 /*
1074 * May have to add something for 'showbreak' string at start of line
1075 * Set *headp to the size of what we add.
1076 */
1077 added = 0;
1078 if (*p_sbr != NUL && wp->w_p_wrap && col != 0)
1079 {
1080 numberextra = win_col_off(wp);
1081 col += numberextra + mb_added;
1082 if (col >= (colnr_T)W_WIDTH(wp))
1083 {
1084 col -= W_WIDTH(wp);
1085 numberextra = W_WIDTH(wp) - (numberextra - win_col_off2(wp));
1086 if (numberextra > 0)
1087 col = col % numberextra;
1088 }
1089 if (col == 0 || col + size > (colnr_T)W_WIDTH(wp))
1090 {
1091 added = vim_strsize(p_sbr);
1092 if (tab_corr)
1093 size += (added / wp->w_buffer->b_p_ts) * wp->w_buffer->b_p_ts;
1094 else
1095 size += added;
1096 if (col != 0)
1097 added = 0;
1098 }
1099 }
1100 if (headp != NULL)
1101 *headp = added + mb_added;
1102 return size;
1103#endif
1104}
1105
1106#if defined(FEAT_MBYTE) || defined(PROTO)
1107/*
1108 * Like win_lbr_chartabsize(), except that we know 'linebreak' is off and
1109 * 'wrap' is on. This means we need to check for a double-byte character that
1110 * doesn't fit at the end of the screen line.
1111 */
1112 static int
1113win_nolbr_chartabsize(wp, s, col, headp)
1114 win_T *wp;
1115 char_u *s;
1116 colnr_T col;
1117 int *headp;
1118{
1119 int n;
1120
1121 if (*s == TAB && (!wp->w_p_list || lcs_tab1))
1122 {
1123 n = wp->w_buffer->b_p_ts;
1124 return (int)(n - (col % n));
1125 }
1126 n = ptr2cells(s);
1127 /* Add one cell for a double-width character in the last column of the
1128 * window, displayed with a ">". */
1129 if (n == 2 && MB_BYTE2LEN(*s) > 1 && in_win_border(wp, col))
1130 {
1131 if (headp != NULL)
1132 *headp = 1;
1133 return 3;
1134 }
1135 return n;
1136}
1137
1138/*
1139 * Return TRUE if virtual column "vcol" is in the rightmost column of window
1140 * "wp".
1141 */
1142 int
1143in_win_border(wp, vcol)
1144 win_T *wp;
1145 colnr_T vcol;
1146{
1147 colnr_T width1; /* width of first line (after line number) */
1148 colnr_T width2; /* width of further lines */
1149
1150#ifdef FEAT_VERTSPLIT
1151 if (wp->w_width == 0) /* there is no border */
1152 return FALSE;
1153#endif
1154 width1 = W_WIDTH(wp) - win_col_off(wp);
1155 if (vcol < width1 - 1)
1156 return FALSE;
1157 if (vcol == width1 - 1)
1158 return TRUE;
1159 width2 = width1 + win_col_off2(wp);
1160 return ((vcol - width1) % width2 == width2 - 1);
1161}
1162#endif /* FEAT_MBYTE */
1163
1164/*
1165 * Get virtual column number of pos.
1166 * start: on the first position of this character (TAB, ctrl)
1167 * cursor: where the cursor is on this character (first char, except for TAB)
1168 * end: on the last position of this character (TAB, ctrl)
1169 *
1170 * This is used very often, keep it fast!
1171 */
1172 void
1173getvcol(wp, pos, start, cursor, end)
1174 win_T *wp;
1175 pos_T *pos;
1176 colnr_T *start;
1177 colnr_T *cursor;
1178 colnr_T *end;
1179{
1180 colnr_T vcol;
1181 char_u *ptr; /* points to current char */
1182 char_u *posptr; /* points to char at pos->col */
1183 int incr;
1184 int head;
1185 int ts = wp->w_buffer->b_p_ts;
1186 int c;
1187
1188 vcol = 0;
1189 ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
1190 posptr = ptr + pos->col;
1191
1192 /*
1193 * This function is used very often, do some speed optimizations.
1194 * When 'list', 'linebreak' and 'showbreak' are not set use a simple loop.
1195 * Also use this when 'list' is set but tabs take their normal size.
1196 */
1197 if ((!wp->w_p_list || lcs_tab1 != NUL)
1198#ifdef FEAT_LINEBREAK
1199 && !wp->w_p_lbr && *p_sbr == NUL
1200#endif
1201 )
1202 {
1203#ifndef FEAT_MBYTE
1204 head = 0;
1205#endif
1206 for (;;)
1207 {
1208#ifdef FEAT_MBYTE
1209 head = 0;
1210#endif
1211 c = *ptr;
1212 /* make sure we don't go past the end of the line */
1213 if (c == NUL)
1214 {
1215 incr = 1; /* NUL at end of line only takes one column */
1216 break;
1217 }
1218 /* A tab gets expanded, depending on the current column */
1219 if (c == TAB)
1220 incr = ts - (vcol % ts);
1221 else
1222 {
1223#ifdef FEAT_MBYTE
1224 if (has_mbyte)
1225 {
1226 /* For utf-8, if the byte is >= 0x80, need to look at
1227 * further bytes to find the cell width. */
1228 if (enc_utf8 && c >= 0x80)
1229 incr = utf_ptr2cells(ptr);
1230 else
1231 incr = CHARSIZE(c);
1232
1233 /* If a double-cell char doesn't fit at the end of a line
1234 * it wraps to the next line, it's like this char is three
1235 * cells wide. */
1236 if (incr == 2 && wp->w_p_wrap && in_win_border(wp, vcol))
1237 {
1238 ++incr;
1239 head = 1;
1240 }
1241 }
1242 else
1243#endif
1244 incr = CHARSIZE(c);
1245 }
1246
1247 if (ptr >= posptr) /* character at pos->col */
1248 break;
1249
1250 vcol += incr;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001251 mb_ptr_adv(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001252 }
1253 }
1254 else
1255 {
1256 for (;;)
1257 {
1258 /* A tab gets expanded, depending on the current column */
1259 head = 0;
1260 incr = win_lbr_chartabsize(wp, ptr, vcol, &head);
1261 /* make sure we don't go past the end of the line */
1262 if (*ptr == NUL)
1263 {
1264 incr = 1; /* NUL at end of line only takes one column */
1265 break;
1266 }
1267
1268 if (ptr >= posptr) /* character at pos->col */
1269 break;
1270
1271 vcol += incr;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001272 mb_ptr_adv(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001273 }
1274 }
1275 if (start != NULL)
1276 *start = vcol + head;
1277 if (end != NULL)
1278 *end = vcol + incr - 1;
1279 if (cursor != NULL)
1280 {
1281 if (*ptr == TAB
1282 && (State & NORMAL)
1283 && !wp->w_p_list
1284 && !virtual_active()
1285#ifdef FEAT_VISUAL
1286 && !(VIsual_active
1287 && (*p_sel == 'e' || ltoreq(*pos, VIsual)))
1288#endif
1289 )
1290 *cursor = vcol + incr - 1; /* cursor at end */
1291 else
1292 *cursor = vcol + head; /* cursor at start */
1293 }
1294}
1295
1296/*
1297 * Get virtual cursor column in the current window, pretending 'list' is off.
1298 */
1299 colnr_T
1300getvcol_nolist(posp)
1301 pos_T *posp;
1302{
1303 int list_save = curwin->w_p_list;
1304 colnr_T vcol;
1305
1306 curwin->w_p_list = FALSE;
1307 getvcol(curwin, posp, NULL, &vcol, NULL);
1308 curwin->w_p_list = list_save;
1309 return vcol;
1310}
1311
1312#if defined(FEAT_VIRTUALEDIT) || defined(PROTO)
1313/*
1314 * Get virtual column in virtual mode.
1315 */
1316 void
1317getvvcol(wp, pos, start, cursor, end)
1318 win_T *wp;
1319 pos_T *pos;
1320 colnr_T *start;
1321 colnr_T *cursor;
1322 colnr_T *end;
1323{
1324 colnr_T col;
1325 colnr_T coladd;
1326 colnr_T endadd;
1327# ifdef FEAT_MBYTE
1328 char_u *ptr;
1329# endif
1330
1331 if (virtual_active())
1332 {
1333 /* For virtual mode, only want one value */
1334 getvcol(wp, pos, &col, NULL, NULL);
1335
1336 coladd = pos->coladd;
1337 endadd = 0;
1338# ifdef FEAT_MBYTE
1339 /* Cannot put the cursor on part of a wide character. */
1340 ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
1341 if (pos->col < STRLEN(ptr))
1342 {
1343 int c = (*mb_ptr2char)(ptr + pos->col);
1344
1345 if (c != TAB && vim_isprintc(c))
1346 {
1347 endadd = char2cells(c) - 1;
1348 if (coladd >= endadd)
1349 coladd -= endadd;
1350 else
1351 coladd = 0;
1352 }
1353 }
1354# endif
1355 col += coladd;
1356 if (start != NULL)
1357 *start = col;
1358 if (cursor != NULL)
1359 *cursor = col;
1360 if (end != NULL)
1361 *end = col + endadd;
1362 }
1363 else
1364 getvcol(wp, pos, start, cursor, end);
1365}
1366#endif
1367
1368#if defined(FEAT_VISUAL) || defined(PROTO)
1369/*
1370 * Get the leftmost and rightmost virtual column of pos1 and pos2.
1371 * Used for Visual block mode.
1372 */
1373 void
1374getvcols(wp, pos1, pos2, left, right)
1375 win_T *wp;
1376 pos_T *pos1, *pos2;
1377 colnr_T *left, *right;
1378{
1379 colnr_T from1, from2, to1, to2;
1380
1381 if (ltp(pos1, pos2))
1382 {
1383 getvvcol(wp, pos1, &from1, NULL, &to1);
1384 getvvcol(wp, pos2, &from2, NULL, &to2);
1385 }
1386 else
1387 {
1388 getvvcol(wp, pos2, &from1, NULL, &to1);
1389 getvvcol(wp, pos1, &from2, NULL, &to2);
1390 }
1391 if (from2 < from1)
1392 *left = from2;
1393 else
1394 *left = from1;
1395 if (to2 > to1)
1396 {
1397 if (*p_sel == 'e' && from2 - 1 >= to1)
1398 *right = from2 - 1;
1399 else
1400 *right = to2;
1401 }
1402 else
1403 *right = to1;
1404}
1405#endif
1406
1407/*
1408 * skipwhite: skip over ' ' and '\t'.
1409 */
1410 char_u *
1411skipwhite(p)
1412 char_u *p;
1413{
1414 while (vim_iswhite(*p)) /* skip to next non-white */
1415 ++p;
1416 return p;
1417}
1418
1419/*
1420 * skipdigits: skip over digits;
1421 */
1422 char_u *
1423skipdigits(p)
1424 char_u *p;
1425{
1426 while (VIM_ISDIGIT(*p)) /* skip to next non-digit */
1427 ++p;
1428 return p;
1429}
1430
1431/*
1432 * Variant of isdigit() that can handle characters > 0x100.
1433 * We don't use isdigit() here, because on some systems it also considers
1434 * superscript 1 to be a digit.
1435 * Use the VIM_ISDIGIT() macro for simple arguments.
1436 */
1437 int
1438vim_isdigit(c)
1439 int c;
1440{
1441 return (c >= '0' && c <= '9');
1442}
1443
1444/*
1445 * Variant of isxdigit() that can handle characters > 0x100.
1446 * We don't use isxdigit() here, because on some systems it also considers
1447 * superscript 1 to be a digit.
1448 */
1449 int
1450vim_isxdigit(c)
1451 int c;
1452{
1453 return (c >= '0' && c <= '9')
1454 || (c >= 'a' && c <= 'f')
1455 || (c >= 'A' && c <= 'F');
1456}
1457
1458/*
1459 * skiptowhite: skip over text until ' ' or '\t' or NUL.
1460 */
1461 char_u *
1462skiptowhite(p)
1463 char_u *p;
1464{
1465 while (*p != ' ' && *p != '\t' && *p != NUL)
1466 ++p;
1467 return p;
1468}
1469
1470#if defined(FEAT_LISTCMDS) || defined(FEAT_SIGNS) || defined(FEAT_SNIFF) \
1471 || defined(PROTO)
1472/*
1473 * skiptowhite_esc: Like skiptowhite(), but also skip escaped chars
1474 */
1475 char_u *
1476skiptowhite_esc(p)
1477 char_u *p;
1478{
1479 while (*p != ' ' && *p != '\t' && *p != NUL)
1480 {
1481 if ((*p == '\\' || *p == Ctrl_V) && *(p + 1) != NUL)
1482 ++p;
1483 ++p;
1484 }
1485 return p;
1486}
1487#endif
1488
1489/*
1490 * Getdigits: Get a number from a string and skip over it.
1491 * Note: the argument is a pointer to a char_u pointer!
1492 */
1493 long
1494getdigits(pp)
1495 char_u **pp;
1496{
1497 char_u *p;
1498 long retval;
1499
1500 p = *pp;
1501 retval = atol((char *)p);
1502 if (*p == '-') /* skip negative sign */
1503 ++p;
1504 p = skipdigits(p); /* skip to next non-digit */
1505 *pp = p;
1506 return retval;
1507}
1508
1509/*
1510 * Return TRUE if "lbuf" is empty or only contains blanks.
1511 */
1512 int
1513vim_isblankline(lbuf)
1514 char_u *lbuf;
1515{
1516 char_u *p;
1517
1518 p = skipwhite(lbuf);
1519 return (*p == NUL || *p == '\r' || *p == '\n');
1520}
1521
1522/*
1523 * Convert a string into a long and/or unsigned long, taking care of
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00001524 * hexadecimal and octal numbers. Accepts a '-' sign.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001525 * If "hexp" is not NULL, returns a flag to indicate the type of the number:
1526 * 0 decimal
1527 * '0' octal
1528 * 'X' hex
1529 * 'x' hex
1530 * If "len" is not NULL, the length of the number in characters is returned.
1531 * If "nptr" is not NULL, the signed result is returned in it.
1532 * If "unptr" is not NULL, the unsigned result is returned in it.
1533 */
1534 void
1535vim_str2nr(start, hexp, len, dooct, dohex, nptr, unptr)
1536 char_u *start;
1537 int *hexp; /* return: type of number 0 = decimal, 'x'
1538 or 'X' is hex, '0' = octal */
1539 int *len; /* return: detected length of number */
1540 int dooct; /* recognize octal number */
1541 int dohex; /* recognize hex number */
1542 long *nptr; /* return: signed result */
1543 unsigned long *unptr; /* return: unsigned result */
1544{
1545 char_u *ptr = start;
1546 int hex = 0; /* default is decimal */
1547 int negative = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001548 unsigned long un = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001549 int n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001550
1551 if (ptr[0] == '-')
1552 {
1553 negative = TRUE;
1554 ++ptr;
1555 }
1556
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001557 /* Recognize hex and octal. */
1558 if (ptr[0] == '0' && ptr[1] != '8' && ptr[1] != '9')
Bram Moolenaar071d4272004-06-13 20:20:40 +00001559 {
1560 hex = ptr[1];
1561 if (dohex && (hex == 'X' || hex == 'x') && vim_isxdigit(ptr[2]))
1562 ptr += 2; /* hexadecimal */
1563 else
1564 {
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001565 hex = 0; /* default is decimal */
1566 if (dooct)
1567 {
1568 /* Don't interpret "0", "08" or "0129" as octal. */
1569 for (n = 1; VIM_ISDIGIT(ptr[n]); ++n)
1570 {
1571 if (ptr[n] > '7')
1572 {
1573 hex = 0; /* can't be octal */
1574 break;
1575 }
1576 if (ptr[n] > '0')
1577 hex = '0'; /* assume octal */
1578 }
1579 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001580 }
1581 }
1582
1583 /*
1584 * Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
1585 */
1586 if (hex)
1587 {
1588 if (hex == '0')
1589 {
1590 /* octal */
1591 while ('0' <= *ptr && *ptr <= '7')
1592 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001593 un = 8 * un + (unsigned long)(*ptr - '0');
1594 ++ptr;
1595 }
1596 }
1597 else
1598 {
1599 /* hex */
1600 while (vim_isxdigit(*ptr))
1601 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001602 un = 16 * un + (unsigned long)hex2nr(*ptr);
1603 ++ptr;
1604 }
1605 }
1606 }
1607 else
1608 {
1609 /* decimal */
1610 while (VIM_ISDIGIT(*ptr))
1611 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001612 un = 10 * un + (unsigned long)(*ptr - '0');
1613 ++ptr;
1614 }
1615 }
1616
Bram Moolenaar071d4272004-06-13 20:20:40 +00001617 if (hexp != NULL)
1618 *hexp = hex;
1619 if (len != NULL)
1620 *len = (int)(ptr - start);
1621 if (nptr != NULL)
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00001622 {
1623 if (negative) /* account for leading '-' for decimal numbers */
1624 *nptr = -(long)un;
1625 else
1626 *nptr = (long)un;
1627 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001628 if (unptr != NULL)
1629 *unptr = un;
1630}
1631
1632/*
1633 * Return the value of a single hex character.
1634 * Only valid when the argument is '0' - '9', 'A' - 'F' or 'a' - 'f'.
1635 */
1636 int
1637hex2nr(c)
1638 int c;
1639{
1640 if (c >= 'a' && c <= 'f')
1641 return c - 'a' + 10;
1642 if (c >= 'A' && c <= 'F')
1643 return c - 'A' + 10;
1644 return c - '0';
1645}
1646
1647#if defined(FEAT_TERMRESPONSE) \
1648 || (defined(FEAT_GUI_GTK) && defined(FEAT_WINDOWS)) || defined(PROTO)
1649/*
1650 * Convert two hex characters to a byte.
1651 * Return -1 if one of the characters is not hex.
1652 */
1653 int
1654hexhex2nr(p)
1655 char_u *p;
1656{
1657 if (!vim_isxdigit(p[0]) || !vim_isxdigit(p[1]))
1658 return -1;
1659 return (hex2nr(p[0]) << 4) + hex2nr(p[1]);
1660}
1661#endif
1662
1663/*
1664 * Return TRUE if "str" starts with a backslash that should be removed.
1665 * For MS-DOS, WIN32 and OS/2 this is only done when the character after the
1666 * backslash is not a normal file name character.
1667 * '$' is a valid file name character, we don't remove the backslash before
1668 * it. This means it is not possible to use an environment variable after a
1669 * backslash. "C:\$VIM\doc" is taken literally, only "$VIM\doc" works.
1670 * Although "\ name" is valid, the backslash in "Program\ files" must be
1671 * removed. Assume a file name doesn't start with a space.
1672 * For multi-byte names, never remove a backslash before a non-ascii
1673 * character, assume that all multi-byte characters are valid file name
1674 * characters.
1675 */
1676 int
1677rem_backslash(str)
1678 char_u *str;
1679{
1680#ifdef BACKSLASH_IN_FILENAME
1681 return (str[0] == '\\'
1682# ifdef FEAT_MBYTE
1683 && str[1] < 0x80
1684# endif
1685 && (str[1] == ' '
1686 || (str[1] != NUL
1687 && str[1] != '*'
1688 && str[1] != '?'
1689 && !vim_isfilec(str[1]))));
1690#else
1691 return (str[0] == '\\' && str[1] != NUL);
1692#endif
1693}
1694
1695/*
1696 * Halve the number of backslashes in a file name argument.
1697 * For MS-DOS we only do this if the character after the backslash
1698 * is not a normal file character.
1699 */
1700 void
1701backslash_halve(p)
1702 char_u *p;
1703{
1704 for ( ; *p; ++p)
1705 if (rem_backslash(p))
1706 STRCPY(p, p + 1);
1707}
1708
1709/*
1710 * backslash_halve() plus save the result in allocated memory.
1711 */
1712 char_u *
1713backslash_halve_save(p)
1714 char_u *p;
1715{
1716 char_u *res;
1717
1718 res = vim_strsave(p);
1719 if (res == NULL)
1720 return p;
1721 backslash_halve(res);
1722 return res;
1723}
1724
1725#if (defined(EBCDIC) && defined(FEAT_POSTSCRIPT)) || defined(PROTO)
1726/*
1727 * Table for EBCDIC to ASCII conversion unashamedly taken from xxd.c!
1728 * The first 64 entries have been added to map control characters defined in
1729 * ascii.h
1730 */
1731static char_u ebcdic2ascii_tab[256] =
1732{
1733 0000, 0001, 0002, 0003, 0004, 0011, 0006, 0177,
1734 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
1735 0020, 0021, 0022, 0023, 0024, 0012, 0010, 0027,
1736 0030, 0031, 0032, 0033, 0033, 0035, 0036, 0037,
1737 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
1738 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
1739 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
1740 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
1741 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246,
1742 0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174,
1743 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
1744 0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176,
1745 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267,
1746 0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077,
1747 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
1748 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042,
1749 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
1750 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311,
1751 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160,
1752 0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320,
1753 0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170,
1754 0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327,
1755 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
1756 0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347,
1757 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
1758 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355,
1759 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120,
1760 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363,
1761 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130,
1762 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
1763 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
1764 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377
1765};
1766
1767/*
1768 * Convert a buffer worth of characters from EBCDIC to ASCII. Only useful if
1769 * wanting 7-bit ASCII characters out the other end.
1770 */
1771 void
1772ebcdic2ascii(buffer, len)
1773 char_u *buffer;
1774 int len;
1775{
1776 int i;
1777
1778 for (i = 0; i < len; i++)
1779 buffer[i] = ebcdic2ascii_tab[buffer[i]];
1780}
1781#endif