blob: 7d01980bdb7cd88c1fea5673862dd590bb66cd19 [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;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000418
419 /* Make each character lower case. */
420 i = 0;
421 while (GA_CHAR(i) != NUL)
422 {
423#ifdef FEAT_MBYTE
424 if (enc_utf8 || (has_mbyte && MB_BYTE2LEN(GA_CHAR(i)) > 1))
425 {
426 if (enc_utf8)
427 {
428 int c, lc;
429
430 c = utf_ptr2char(GA_PTR(i));
431 lc = utf_tolower(c);
432 if (c != lc)
433 {
434 int ol = utf_char2len(c);
435 int nl = utf_char2len(lc);
436
437 /* If the byte length changes need to shift the following
438 * characters forward or backward. */
439 if (ol != nl)
440 {
441 if (nl > ol)
442 if (ga_grow(&ga, nl - ol) == FAIL)
443 {
444 /* out of memory, keep old char */
445 lc = c;
446 nl = ol;
447 }
448 if (ol != nl)
449 {
450 mch_memmove(GA_PTR(i) + nl, GA_PTR(i) + ol,
451 STRLEN(GA_PTR(i) + ol) + 1);
452 ga.ga_len += nl - ol;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000453 }
454 }
455 (void)utf_char2bytes(lc, GA_PTR(i));
456 }
457 }
458 /* skip to next multi-byte char */
459 i += (*mb_ptr2len_check)(GA_PTR(i));
460 }
461 else
462#endif
463 {
464 GA_CHAR(i) = TOLOWER_LOC(GA_CHAR(i));
465 ++i;
466 }
467 }
468
469 return (char_u *)ga.ga_data;
470}
471#endif
472
473/*
474 * Catch 22: chartab[] can't be initialized before the options are
475 * initialized, and initializing options may cause transchar() to be called!
476 * When chartab_initialized == FALSE don't use chartab[].
477 * Does NOT work for multi-byte characters, c must be <= 255.
478 * Also doesn't work for the first byte of a multi-byte, "c" must be a
479 * character!
480 */
481static char_u transchar_buf[7];
482
483 char_u *
484transchar(c)
485 int c;
486{
487 int i;
488
489 i = 0;
490 if (IS_SPECIAL(c)) /* special key code, display as ~@ char */
491 {
492 transchar_buf[0] = '~';
493 transchar_buf[1] = '@';
494 i = 2;
495 c = K_SECOND(c);
496 }
497
498 if ((!chartab_initialized && (
499#ifdef EBCDIC
500 (c >= 64 && c < 255)
501#else
502 (c >= ' ' && c <= '~')
503#endif
504#ifdef FEAT_FKMAP
505 || F_ischar(c)
506#endif
507 )) || (c < 256 && vim_isprintc_strict(c)))
508 {
509 /* printable character */
510 transchar_buf[i] = c;
511 transchar_buf[i + 1] = NUL;
512 }
513 else
514 transchar_nonprint(transchar_buf + i, c);
515 return transchar_buf;
516}
517
518#if defined(FEAT_MBYTE) || defined(PROTO)
519/*
520 * Like transchar(), but called with a byte instead of a character. Checks
521 * for an illegal UTF-8 byte.
522 */
523 char_u *
524transchar_byte(c)
525 int c;
526{
527 if (enc_utf8 && c >= 0x80)
528 {
529 transchar_nonprint(transchar_buf, c);
530 return transchar_buf;
531 }
532 return transchar(c);
533}
534#endif
535
536/*
537 * Convert non-printable character to two or more printable characters in
538 * "buf[]". "buf" needs to be able to hold five bytes.
539 * Does NOT work for multi-byte characters, c must be <= 255.
540 */
541 void
542transchar_nonprint(buf, c)
543 char_u *buf;
544 int c;
545{
546 if (c == NL)
547 c = NUL; /* we use newline in place of a NUL */
548 else if (c == CAR && get_fileformat(curbuf) == EOL_MAC)
549 c = NL; /* we use CR in place of NL in this case */
550
551 if (dy_flags & DY_UHEX) /* 'display' has "uhex" */
552 transchar_hex(buf, c);
553
554#ifdef EBCDIC
555 /* For EBCDIC only the characters 0-63 and 255 are not printable */
556 else if (CtrlChar(c) != 0 || c == DEL)
557#else
558 else if (c <= 0x7f) /* 0x00 - 0x1f and 0x7f */
559#endif
560 {
561 buf[0] = '^';
562#ifdef EBCDIC
563 if (c == DEL)
564 buf[1] = '?'; /* DEL displayed as ^? */
565 else
566 buf[1] = CtrlChar(c);
567#else
568 buf[1] = c ^ 0x40; /* DEL displayed as ^? */
569#endif
570
571 buf[2] = NUL;
572 }
573#ifdef FEAT_MBYTE
574 else if (enc_utf8 && c >= 0x80)
575 {
576 transchar_hex(buf, c);
577 }
578#endif
579#ifndef EBCDIC
580 else if (c >= ' ' + 0x80 && c <= '~' + 0x80) /* 0xa0 - 0xfe */
581 {
582 buf[0] = '|';
583 buf[1] = c - 0x80;
584 buf[2] = NUL;
585 }
586#else
587 else if (c < 64)
588 {
589 buf[0] = '~';
590 buf[1] = MetaChar(c);
591 buf[2] = NUL;
592 }
593#endif
594 else /* 0x80 - 0x9f and 0xff */
595 {
596 /*
597 * TODO: EBCDIC I don't know what to do with this chars, so I display
598 * them as '~?' for now
599 */
600 buf[0] = '~';
601#ifdef EBCDIC
602 buf[1] = '?'; /* 0xff displayed as ~? */
603#else
604 buf[1] = (c - 0x80) ^ 0x40; /* 0xff displayed as ~? */
605#endif
606 buf[2] = NUL;
607 }
608}
609
610 void
611transchar_hex(buf, c)
612 char_u *buf;
613 int c;
614{
615 int i = 0;
616
617 buf[0] = '<';
618#ifdef FEAT_MBYTE
619 if (c > 255)
620 {
621 buf[++i] = nr2hex((unsigned)c >> 12);
622 buf[++i] = nr2hex((unsigned)c >> 8);
623 }
624#endif
625 buf[++i] = nr2hex((unsigned)c >> 4);
626 buf[++i] = nr2hex(c);
627 buf[++i] = '>';
628 buf[++i] = NUL;
629}
630
631/*
632 * Convert the lower 4 bits of byte "c" to its hex character.
633 * Lower case letters are used to avoid the confusion of <F1> being 0xf1 or
634 * function key 1.
635 */
636 static int
637nr2hex(c)
638 int c;
639{
640 if ((c & 0xf) <= 9)
641 return (c & 0xf) + '0';
642 return (c & 0xf) - 10 + 'a';
643}
644
645/*
646 * Return number of display cells occupied by byte "b".
647 * Caller must make sure 0 <= b <= 255.
648 * For multi-byte mode "b" must be the first byte of a character.
649 * A TAB is counted as two cells: "^I".
650 * For UTF-8 mode this will return 0 for bytes >= 0x80, because the number of
651 * cells depends on further bytes.
652 */
653 int
654byte2cells(b)
655 int b;
656{
657#ifdef FEAT_MBYTE
658 if (enc_utf8 && b >= 0x80)
659 return 0;
660#endif
661 return (chartab[b] & CT_CELL_MASK);
662}
663
664/*
665 * Return number of display cells occupied by character "c".
666 * "c" can be a special key (negative number) in which case 3 or 4 is returned.
667 * A TAB is counted as two cells: "^I" or four: "<09>".
668 */
669 int
670char2cells(c)
671 int c;
672{
673 if (IS_SPECIAL(c))
674 return char2cells(K_SECOND(c)) + 2;
675#ifdef FEAT_MBYTE
676 if (c >= 0x80)
677 {
678 /* UTF-8: above 0x80 need to check the value */
679 if (enc_utf8)
680 return utf_char2cells(c);
681 /* DBCS: double-byte means double-width, except for euc-jp with first
682 * byte 0x8e */
683 if (enc_dbcs != 0 && c >= 0x100)
684 {
685 if (enc_dbcs == DBCS_JPNU && ((unsigned)c >> 8) == 0x8e)
686 return 1;
687 return 2;
688 }
689 }
690#endif
691 return (chartab[c & 0xff] & CT_CELL_MASK);
692}
693
694/*
695 * Return number of display cells occupied by character at "*p".
696 * A TAB is counted as two cells: "^I" or four: "<09>".
697 */
698 int
699ptr2cells(p)
700 char_u *p;
701{
702#ifdef FEAT_MBYTE
703 /* For UTF-8 we need to look at more bytes if the first byte is >= 0x80. */
704 if (enc_utf8 && *p >= 0x80)
705 return utf_ptr2cells(p);
706 /* For DBCS we can tell the cell count from the first byte. */
707#endif
708 return (chartab[*p] & CT_CELL_MASK);
709}
710
711/*
712 * Return the number of characters string "s" will take on the screen,
713 * counting TABs as two characters: "^I".
714 */
715 int
716vim_strsize(s)
717 char_u *s;
718{
719 return vim_strnsize(s, (int)MAXCOL);
720}
721
722/*
723 * Return the number of characters string "s[len]" will take on the screen,
724 * counting TABs as two characters: "^I".
725 */
726 int
727vim_strnsize(s, len)
728 char_u *s;
729 int len;
730{
731 int size = 0;
732
733 while (*s != NUL && --len >= 0)
734 {
735#ifdef FEAT_MBYTE
736 if (has_mbyte)
737 {
738 int l = (*mb_ptr2len_check)(s);
739
740 size += ptr2cells(s);
741 s += l;
742 len -= l - 1;
743 }
744 else
745#endif
746 size += byte2cells(*s++);
747 }
748 return size;
749}
750
751/*
752 * Return the number of characters 'c' will take on the screen, taking
753 * into account the size of a tab.
754 * Use a define to make it fast, this is used very often!!!
755 * Also see getvcol() below.
756 */
757
758#define RET_WIN_BUF_CHARTABSIZE(wp, buf, p, col) \
759 if (*(p) == TAB && (!(wp)->w_p_list || lcs_tab1)) \
760 { \
761 int ts; \
762 ts = (buf)->b_p_ts; \
763 return (int)(ts - (col % ts)); \
764 } \
765 else \
766 return ptr2cells(p);
767
768#if defined(FEAT_VREPLACE) || defined(FEAT_EX_EXTRA) || defined(FEAT_GUI) \
769 || defined(FEAT_VIRTUALEDIT) || defined(PROTO)
770 int
771chartabsize(p, col)
772 char_u *p;
773 colnr_T col;
774{
775 RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, p, col)
776}
777#endif
778
779#ifdef FEAT_LINEBREAK
780 static int
781win_chartabsize(wp, p, col)
782 win_T *wp;
783 char_u *p;
784 colnr_T col;
785{
786 RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, p, col)
787}
788#endif
789
790/*
791 * return the number of characters the string 's' will take on the screen,
792 * taking into account the size of a tab
793 */
794 int
795linetabsize(s)
796 char_u *s;
797{
798 colnr_T col = 0;
799
800 while (*s != NUL)
801 col += lbr_chartabsize_adv(&s, col);
802 return (int)col;
803}
804
805/*
806 * Like linetabsize(), but for a given window instead of the current one.
807 */
808 int
809win_linetabsize(wp, p, len)
810 win_T *wp;
811 char_u *p;
812 colnr_T len;
813{
814 colnr_T col = 0;
815 char_u *s;
816
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +0000817 for (s = p; *s != NUL && (len == MAXCOL || s < p + len); mb_ptr_adv(s))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000818 col += win_lbr_chartabsize(wp, s, col, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000819 return (int)col;
820}
821
822/*
Bram Moolenaar81695252004-12-29 20:58:21 +0000823 * Return TRUE if 'c' is a normal identifier character:
824 * Letters and characters from the 'isident' option.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000825 */
826 int
827vim_isIDc(c)
828 int c;
829{
830 return (c > 0 && c < 0x100 && (chartab[c] & CT_ID_CHAR));
831}
832
833/*
834 * return TRUE if 'c' is a keyword character: Letters and characters from
835 * 'iskeyword' option for current buffer.
836 * For multi-byte characters mb_get_class() is used (builtin rules).
837 */
838 int
839vim_iswordc(c)
840 int c;
841{
842#ifdef FEAT_MBYTE
843 if (c >= 0x100)
844 {
845 if (enc_dbcs != 0)
846 return dbcs_class((unsigned)c >> 8, c & 0xff) >= 2;
847 if (enc_utf8)
848 return utf_class(c) >= 2;
849 }
850#endif
851 return (c > 0 && c < 0x100 && GET_CHARTAB(curbuf, c) != 0);
852}
853
854/*
855 * Just like vim_iswordc() but uses a pointer to the (multi-byte) character.
856 */
857 int
858vim_iswordp(p)
859 char_u *p;
860{
861#ifdef FEAT_MBYTE
862 if (has_mbyte && MB_BYTE2LEN(*p) > 1)
863 return mb_get_class(p) >= 2;
864#endif
865 return GET_CHARTAB(curbuf, *p) != 0;
866}
867
868#if defined(FEAT_SYN_HL) || defined(PROTO)
869 int
870vim_iswordc_buf(p, buf)
871 char_u *p;
872 buf_T *buf;
873{
874# ifdef FEAT_MBYTE
875 if (has_mbyte && MB_BYTE2LEN(*p) > 1)
876 return mb_get_class(p) >= 2;
877# endif
878 return (GET_CHARTAB(buf, *p) != 0);
879}
880#endif
881
882/*
883 * return TRUE if 'c' is a valid file-name character
884 * Assume characters above 0x100 are valid (multi-byte).
885 */
886 int
887vim_isfilec(c)
888 int c;
889{
890 return (c >= 0x100 || (c > 0 && (chartab[c] & CT_FNAME_CHAR)));
891}
892
893/*
894 * return TRUE if 'c' is a printable character
895 * Assume characters above 0x100 are printable (multi-byte), except for
896 * Unicode.
897 */
898 int
899vim_isprintc(c)
900 int c;
901{
902#ifdef FEAT_MBYTE
903 if (enc_utf8 && c >= 0x100)
904 return utf_printable(c);
905#endif
906 return (c >= 0x100 || (c > 0 && (chartab[c] & CT_PRINT_CHAR)));
907}
908
909/*
910 * Strict version of vim_isprintc(c), don't return TRUE if "c" is the head
911 * byte of a double-byte character.
912 */
913 int
914vim_isprintc_strict(c)
915 int c;
916{
917#ifdef FEAT_MBYTE
918 if (enc_dbcs != 0 && c < 0x100 && MB_BYTE2LEN(c) > 1)
919 return FALSE;
920 if (enc_utf8 && c >= 0x100)
921 return utf_printable(c);
922#endif
923 return (c >= 0x100 || (c > 0 && (chartab[c] & CT_PRINT_CHAR)));
924}
925
926/*
927 * like chartabsize(), but also check for line breaks on the screen
928 */
929 int
930lbr_chartabsize(s, col)
931 unsigned char *s;
932 colnr_T col;
933{
934#ifdef FEAT_LINEBREAK
935 if (!curwin->w_p_lbr && *p_sbr == NUL)
936 {
937#endif
938#ifdef FEAT_MBYTE
939 if (curwin->w_p_wrap)
940 return win_nolbr_chartabsize(curwin, s, col, NULL);
941#endif
942 RET_WIN_BUF_CHARTABSIZE(curwin, curbuf, s, col)
943#ifdef FEAT_LINEBREAK
944 }
945 return win_lbr_chartabsize(curwin, s, col, NULL);
946#endif
947}
948
949/*
950 * Call lbr_chartabsize() and advance the pointer.
951 */
952 int
953lbr_chartabsize_adv(s, col)
954 char_u **s;
955 colnr_T col;
956{
957 int retval;
958
959 retval = lbr_chartabsize(*s, col);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000960 mb_ptr_adv(*s);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000961 return retval;
962}
963
964/*
965 * This function is used very often, keep it fast!!!!
966 *
967 * If "headp" not NULL, set *headp to the size of what we for 'showbreak'
968 * string at start of line. Warning: *headp is only set if it's a non-zero
969 * value, init to 0 before calling.
970 */
971/*ARGSUSED*/
972 int
973win_lbr_chartabsize(wp, s, col, headp)
974 win_T *wp;
975 char_u *s;
976 colnr_T col;
977 int *headp;
978{
979#ifdef FEAT_LINEBREAK
980 int c;
981 int size;
982 colnr_T col2;
983 colnr_T colmax;
984 int added;
985# ifdef FEAT_MBYTE
986 int mb_added = 0;
987# else
988# define mb_added 0
989# endif
990 int numberextra;
991 char_u *ps;
992 int tab_corr = (*s == TAB);
993
994 /*
995 * No 'linebreak' and 'showbreak': return quickly.
996 */
997 if (!wp->w_p_lbr && *p_sbr == NUL)
998#endif
999 {
1000#ifdef FEAT_MBYTE
1001 if (wp->w_p_wrap)
1002 return win_nolbr_chartabsize(wp, s, col, headp);
1003#endif
1004 RET_WIN_BUF_CHARTABSIZE(wp, wp->w_buffer, s, col)
1005 }
1006
1007#ifdef FEAT_LINEBREAK
1008 /*
1009 * First get normal size, without 'linebreak'
1010 */
1011 size = win_chartabsize(wp, s, col);
1012 c = *s;
1013
1014 /*
1015 * If 'linebreak' set check at a blank before a non-blank if the line
1016 * needs a break here
1017 */
1018 if (wp->w_p_lbr
1019 && vim_isbreak(c)
1020 && !vim_isbreak(s[1])
1021 && !wp->w_p_list
1022 && wp->w_p_wrap
1023# ifdef FEAT_VERTSPLIT
1024 && wp->w_width != 0
1025# endif
1026 )
1027 {
1028 /*
1029 * Count all characters from first non-blank after a blank up to next
1030 * non-blank after a blank.
1031 */
1032 numberextra = win_col_off(wp);
1033 col2 = col;
1034 colmax = W_WIDTH(wp) - numberextra;
1035 if (col >= colmax)
1036 colmax += (((col - colmax)
1037 / (colmax + win_col_off2(wp))) + 1)
1038 * (colmax + win_col_off2(wp));
1039 for (;;)
1040 {
1041 ps = s;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001042 mb_ptr_adv(s);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001043 c = *s;
1044 if (!(c != NUL
1045 && (vim_isbreak(c)
1046 || (!vim_isbreak(c)
1047 && (col2 == col || !vim_isbreak(*ps))))))
1048 break;
1049
1050 col2 += win_chartabsize(wp, s, col2);
1051 if (col2 >= colmax) /* doesn't fit */
1052 {
1053 size = colmax - col;
1054 tab_corr = FALSE;
1055 break;
1056 }
1057 }
1058 }
1059# ifdef FEAT_MBYTE
1060 else if (has_mbyte && size == 2 && MB_BYTE2LEN(*s) > 1
1061 && wp->w_p_wrap && in_win_border(wp, col))
1062 {
1063 ++size; /* Count the ">" in the last column. */
1064 mb_added = 1;
1065 }
1066# endif
1067
1068 /*
1069 * May have to add something for 'showbreak' string at start of line
1070 * Set *headp to the size of what we add.
1071 */
1072 added = 0;
1073 if (*p_sbr != NUL && wp->w_p_wrap && col != 0)
1074 {
1075 numberextra = win_col_off(wp);
1076 col += numberextra + mb_added;
1077 if (col >= (colnr_T)W_WIDTH(wp))
1078 {
1079 col -= W_WIDTH(wp);
1080 numberextra = W_WIDTH(wp) - (numberextra - win_col_off2(wp));
1081 if (numberextra > 0)
1082 col = col % numberextra;
1083 }
1084 if (col == 0 || col + size > (colnr_T)W_WIDTH(wp))
1085 {
1086 added = vim_strsize(p_sbr);
1087 if (tab_corr)
1088 size += (added / wp->w_buffer->b_p_ts) * wp->w_buffer->b_p_ts;
1089 else
1090 size += added;
1091 if (col != 0)
1092 added = 0;
1093 }
1094 }
1095 if (headp != NULL)
1096 *headp = added + mb_added;
1097 return size;
1098#endif
1099}
1100
1101#if defined(FEAT_MBYTE) || defined(PROTO)
1102/*
1103 * Like win_lbr_chartabsize(), except that we know 'linebreak' is off and
1104 * 'wrap' is on. This means we need to check for a double-byte character that
1105 * doesn't fit at the end of the screen line.
1106 */
1107 static int
1108win_nolbr_chartabsize(wp, s, col, headp)
1109 win_T *wp;
1110 char_u *s;
1111 colnr_T col;
1112 int *headp;
1113{
1114 int n;
1115
1116 if (*s == TAB && (!wp->w_p_list || lcs_tab1))
1117 {
1118 n = wp->w_buffer->b_p_ts;
1119 return (int)(n - (col % n));
1120 }
1121 n = ptr2cells(s);
1122 /* Add one cell for a double-width character in the last column of the
1123 * window, displayed with a ">". */
1124 if (n == 2 && MB_BYTE2LEN(*s) > 1 && in_win_border(wp, col))
1125 {
1126 if (headp != NULL)
1127 *headp = 1;
1128 return 3;
1129 }
1130 return n;
1131}
1132
1133/*
1134 * Return TRUE if virtual column "vcol" is in the rightmost column of window
1135 * "wp".
1136 */
1137 int
1138in_win_border(wp, vcol)
1139 win_T *wp;
1140 colnr_T vcol;
1141{
1142 colnr_T width1; /* width of first line (after line number) */
1143 colnr_T width2; /* width of further lines */
1144
1145#ifdef FEAT_VERTSPLIT
1146 if (wp->w_width == 0) /* there is no border */
1147 return FALSE;
1148#endif
1149 width1 = W_WIDTH(wp) - win_col_off(wp);
1150 if (vcol < width1 - 1)
1151 return FALSE;
1152 if (vcol == width1 - 1)
1153 return TRUE;
1154 width2 = width1 + win_col_off2(wp);
1155 return ((vcol - width1) % width2 == width2 - 1);
1156}
1157#endif /* FEAT_MBYTE */
1158
1159/*
1160 * Get virtual column number of pos.
1161 * start: on the first position of this character (TAB, ctrl)
1162 * cursor: where the cursor is on this character (first char, except for TAB)
1163 * end: on the last position of this character (TAB, ctrl)
1164 *
1165 * This is used very often, keep it fast!
1166 */
1167 void
1168getvcol(wp, pos, start, cursor, end)
1169 win_T *wp;
1170 pos_T *pos;
1171 colnr_T *start;
1172 colnr_T *cursor;
1173 colnr_T *end;
1174{
1175 colnr_T vcol;
1176 char_u *ptr; /* points to current char */
1177 char_u *posptr; /* points to char at pos->col */
1178 int incr;
1179 int head;
1180 int ts = wp->w_buffer->b_p_ts;
1181 int c;
1182
1183 vcol = 0;
1184 ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
1185 posptr = ptr + pos->col;
1186
1187 /*
1188 * This function is used very often, do some speed optimizations.
1189 * When 'list', 'linebreak' and 'showbreak' are not set use a simple loop.
1190 * Also use this when 'list' is set but tabs take their normal size.
1191 */
1192 if ((!wp->w_p_list || lcs_tab1 != NUL)
1193#ifdef FEAT_LINEBREAK
1194 && !wp->w_p_lbr && *p_sbr == NUL
1195#endif
1196 )
1197 {
1198#ifndef FEAT_MBYTE
1199 head = 0;
1200#endif
1201 for (;;)
1202 {
1203#ifdef FEAT_MBYTE
1204 head = 0;
1205#endif
1206 c = *ptr;
1207 /* make sure we don't go past the end of the line */
1208 if (c == NUL)
1209 {
1210 incr = 1; /* NUL at end of line only takes one column */
1211 break;
1212 }
1213 /* A tab gets expanded, depending on the current column */
1214 if (c == TAB)
1215 incr = ts - (vcol % ts);
1216 else
1217 {
1218#ifdef FEAT_MBYTE
1219 if (has_mbyte)
1220 {
1221 /* For utf-8, if the byte is >= 0x80, need to look at
1222 * further bytes to find the cell width. */
1223 if (enc_utf8 && c >= 0x80)
1224 incr = utf_ptr2cells(ptr);
1225 else
1226 incr = CHARSIZE(c);
1227
1228 /* If a double-cell char doesn't fit at the end of a line
1229 * it wraps to the next line, it's like this char is three
1230 * cells wide. */
1231 if (incr == 2 && wp->w_p_wrap && in_win_border(wp, vcol))
1232 {
1233 ++incr;
1234 head = 1;
1235 }
1236 }
1237 else
1238#endif
1239 incr = CHARSIZE(c);
1240 }
1241
1242 if (ptr >= posptr) /* character at pos->col */
1243 break;
1244
1245 vcol += incr;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001246 mb_ptr_adv(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001247 }
1248 }
1249 else
1250 {
1251 for (;;)
1252 {
1253 /* A tab gets expanded, depending on the current column */
1254 head = 0;
1255 incr = win_lbr_chartabsize(wp, ptr, vcol, &head);
1256 /* make sure we don't go past the end of the line */
1257 if (*ptr == NUL)
1258 {
1259 incr = 1; /* NUL at end of line only takes one column */
1260 break;
1261 }
1262
1263 if (ptr >= posptr) /* character at pos->col */
1264 break;
1265
1266 vcol += incr;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001267 mb_ptr_adv(ptr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001268 }
1269 }
1270 if (start != NULL)
1271 *start = vcol + head;
1272 if (end != NULL)
1273 *end = vcol + incr - 1;
1274 if (cursor != NULL)
1275 {
1276 if (*ptr == TAB
1277 && (State & NORMAL)
1278 && !wp->w_p_list
1279 && !virtual_active()
1280#ifdef FEAT_VISUAL
1281 && !(VIsual_active
1282 && (*p_sel == 'e' || ltoreq(*pos, VIsual)))
1283#endif
1284 )
1285 *cursor = vcol + incr - 1; /* cursor at end */
1286 else
1287 *cursor = vcol + head; /* cursor at start */
1288 }
1289}
1290
1291/*
1292 * Get virtual cursor column in the current window, pretending 'list' is off.
1293 */
1294 colnr_T
1295getvcol_nolist(posp)
1296 pos_T *posp;
1297{
1298 int list_save = curwin->w_p_list;
1299 colnr_T vcol;
1300
1301 curwin->w_p_list = FALSE;
1302 getvcol(curwin, posp, NULL, &vcol, NULL);
1303 curwin->w_p_list = list_save;
1304 return vcol;
1305}
1306
1307#if defined(FEAT_VIRTUALEDIT) || defined(PROTO)
1308/*
1309 * Get virtual column in virtual mode.
1310 */
1311 void
1312getvvcol(wp, pos, start, cursor, end)
1313 win_T *wp;
1314 pos_T *pos;
1315 colnr_T *start;
1316 colnr_T *cursor;
1317 colnr_T *end;
1318{
1319 colnr_T col;
1320 colnr_T coladd;
1321 colnr_T endadd;
1322# ifdef FEAT_MBYTE
1323 char_u *ptr;
1324# endif
1325
1326 if (virtual_active())
1327 {
1328 /* For virtual mode, only want one value */
1329 getvcol(wp, pos, &col, NULL, NULL);
1330
1331 coladd = pos->coladd;
1332 endadd = 0;
1333# ifdef FEAT_MBYTE
1334 /* Cannot put the cursor on part of a wide character. */
1335 ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
1336 if (pos->col < STRLEN(ptr))
1337 {
1338 int c = (*mb_ptr2char)(ptr + pos->col);
1339
1340 if (c != TAB && vim_isprintc(c))
1341 {
1342 endadd = char2cells(c) - 1;
1343 if (coladd >= endadd)
1344 coladd -= endadd;
1345 else
1346 coladd = 0;
1347 }
1348 }
1349# endif
1350 col += coladd;
1351 if (start != NULL)
1352 *start = col;
1353 if (cursor != NULL)
1354 *cursor = col;
1355 if (end != NULL)
1356 *end = col + endadd;
1357 }
1358 else
1359 getvcol(wp, pos, start, cursor, end);
1360}
1361#endif
1362
1363#if defined(FEAT_VISUAL) || defined(PROTO)
1364/*
1365 * Get the leftmost and rightmost virtual column of pos1 and pos2.
1366 * Used for Visual block mode.
1367 */
1368 void
1369getvcols(wp, pos1, pos2, left, right)
1370 win_T *wp;
1371 pos_T *pos1, *pos2;
1372 colnr_T *left, *right;
1373{
1374 colnr_T from1, from2, to1, to2;
1375
1376 if (ltp(pos1, pos2))
1377 {
1378 getvvcol(wp, pos1, &from1, NULL, &to1);
1379 getvvcol(wp, pos2, &from2, NULL, &to2);
1380 }
1381 else
1382 {
1383 getvvcol(wp, pos2, &from1, NULL, &to1);
1384 getvvcol(wp, pos1, &from2, NULL, &to2);
1385 }
1386 if (from2 < from1)
1387 *left = from2;
1388 else
1389 *left = from1;
1390 if (to2 > to1)
1391 {
1392 if (*p_sel == 'e' && from2 - 1 >= to1)
1393 *right = from2 - 1;
1394 else
1395 *right = to2;
1396 }
1397 else
1398 *right = to1;
1399}
1400#endif
1401
1402/*
1403 * skipwhite: skip over ' ' and '\t'.
1404 */
1405 char_u *
1406skipwhite(p)
1407 char_u *p;
1408{
1409 while (vim_iswhite(*p)) /* skip to next non-white */
1410 ++p;
1411 return p;
1412}
1413
1414/*
1415 * skipdigits: skip over digits;
1416 */
1417 char_u *
1418skipdigits(p)
1419 char_u *p;
1420{
1421 while (VIM_ISDIGIT(*p)) /* skip to next non-digit */
1422 ++p;
1423 return p;
1424}
1425
1426/*
1427 * Variant of isdigit() that can handle characters > 0x100.
1428 * We don't use isdigit() here, because on some systems it also considers
1429 * superscript 1 to be a digit.
1430 * Use the VIM_ISDIGIT() macro for simple arguments.
1431 */
1432 int
1433vim_isdigit(c)
1434 int c;
1435{
1436 return (c >= '0' && c <= '9');
1437}
1438
1439/*
1440 * Variant of isxdigit() that can handle characters > 0x100.
1441 * We don't use isxdigit() here, because on some systems it also considers
1442 * superscript 1 to be a digit.
1443 */
1444 int
1445vim_isxdigit(c)
1446 int c;
1447{
1448 return (c >= '0' && c <= '9')
1449 || (c >= 'a' && c <= 'f')
1450 || (c >= 'A' && c <= 'F');
1451}
1452
1453/*
1454 * skiptowhite: skip over text until ' ' or '\t' or NUL.
1455 */
1456 char_u *
1457skiptowhite(p)
1458 char_u *p;
1459{
1460 while (*p != ' ' && *p != '\t' && *p != NUL)
1461 ++p;
1462 return p;
1463}
1464
1465#if defined(FEAT_LISTCMDS) || defined(FEAT_SIGNS) || defined(FEAT_SNIFF) \
1466 || defined(PROTO)
1467/*
1468 * skiptowhite_esc: Like skiptowhite(), but also skip escaped chars
1469 */
1470 char_u *
1471skiptowhite_esc(p)
1472 char_u *p;
1473{
1474 while (*p != ' ' && *p != '\t' && *p != NUL)
1475 {
1476 if ((*p == '\\' || *p == Ctrl_V) && *(p + 1) != NUL)
1477 ++p;
1478 ++p;
1479 }
1480 return p;
1481}
1482#endif
1483
1484/*
1485 * Getdigits: Get a number from a string and skip over it.
1486 * Note: the argument is a pointer to a char_u pointer!
1487 */
1488 long
1489getdigits(pp)
1490 char_u **pp;
1491{
1492 char_u *p;
1493 long retval;
1494
1495 p = *pp;
1496 retval = atol((char *)p);
1497 if (*p == '-') /* skip negative sign */
1498 ++p;
1499 p = skipdigits(p); /* skip to next non-digit */
1500 *pp = p;
1501 return retval;
1502}
1503
1504/*
1505 * Return TRUE if "lbuf" is empty or only contains blanks.
1506 */
1507 int
1508vim_isblankline(lbuf)
1509 char_u *lbuf;
1510{
1511 char_u *p;
1512
1513 p = skipwhite(lbuf);
1514 return (*p == NUL || *p == '\r' || *p == '\n');
1515}
1516
1517/*
1518 * Convert a string into a long and/or unsigned long, taking care of
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00001519 * hexadecimal and octal numbers. Accepts a '-' sign.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001520 * If "hexp" is not NULL, returns a flag to indicate the type of the number:
1521 * 0 decimal
1522 * '0' octal
1523 * 'X' hex
1524 * 'x' hex
1525 * If "len" is not NULL, the length of the number in characters is returned.
1526 * If "nptr" is not NULL, the signed result is returned in it.
1527 * If "unptr" is not NULL, the unsigned result is returned in it.
1528 */
1529 void
1530vim_str2nr(start, hexp, len, dooct, dohex, nptr, unptr)
1531 char_u *start;
1532 int *hexp; /* return: type of number 0 = decimal, 'x'
1533 or 'X' is hex, '0' = octal */
1534 int *len; /* return: detected length of number */
1535 int dooct; /* recognize octal number */
1536 int dohex; /* recognize hex number */
1537 long *nptr; /* return: signed result */
1538 unsigned long *unptr; /* return: unsigned result */
1539{
1540 char_u *ptr = start;
1541 int hex = 0; /* default is decimal */
1542 int negative = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001543 unsigned long un = 0;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001544 int n;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001545
1546 if (ptr[0] == '-')
1547 {
1548 negative = TRUE;
1549 ++ptr;
1550 }
1551
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001552 /* Recognize hex and octal. */
1553 if (ptr[0] == '0' && ptr[1] != '8' && ptr[1] != '9')
Bram Moolenaar071d4272004-06-13 20:20:40 +00001554 {
1555 hex = ptr[1];
1556 if (dohex && (hex == 'X' || hex == 'x') && vim_isxdigit(ptr[2]))
1557 ptr += 2; /* hexadecimal */
1558 else
1559 {
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001560 hex = 0; /* default is decimal */
1561 if (dooct)
1562 {
1563 /* Don't interpret "0", "08" or "0129" as octal. */
1564 for (n = 1; VIM_ISDIGIT(ptr[n]); ++n)
1565 {
1566 if (ptr[n] > '7')
1567 {
1568 hex = 0; /* can't be octal */
1569 break;
1570 }
1571 if (ptr[n] > '0')
1572 hex = '0'; /* assume octal */
1573 }
1574 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001575 }
1576 }
1577
1578 /*
1579 * Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
1580 */
1581 if (hex)
1582 {
1583 if (hex == '0')
1584 {
1585 /* octal */
1586 while ('0' <= *ptr && *ptr <= '7')
1587 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001588 un = 8 * un + (unsigned long)(*ptr - '0');
1589 ++ptr;
1590 }
1591 }
1592 else
1593 {
1594 /* hex */
1595 while (vim_isxdigit(*ptr))
1596 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001597 un = 16 * un + (unsigned long)hex2nr(*ptr);
1598 ++ptr;
1599 }
1600 }
1601 }
1602 else
1603 {
1604 /* decimal */
1605 while (VIM_ISDIGIT(*ptr))
1606 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001607 un = 10 * un + (unsigned long)(*ptr - '0');
1608 ++ptr;
1609 }
1610 }
1611
Bram Moolenaar071d4272004-06-13 20:20:40 +00001612 if (hexp != NULL)
1613 *hexp = hex;
1614 if (len != NULL)
1615 *len = (int)(ptr - start);
1616 if (nptr != NULL)
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +00001617 {
1618 if (negative) /* account for leading '-' for decimal numbers */
1619 *nptr = -(long)un;
1620 else
1621 *nptr = (long)un;
1622 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001623 if (unptr != NULL)
1624 *unptr = un;
1625}
1626
1627/*
1628 * Return the value of a single hex character.
1629 * Only valid when the argument is '0' - '9', 'A' - 'F' or 'a' - 'f'.
1630 */
1631 int
1632hex2nr(c)
1633 int c;
1634{
1635 if (c >= 'a' && c <= 'f')
1636 return c - 'a' + 10;
1637 if (c >= 'A' && c <= 'F')
1638 return c - 'A' + 10;
1639 return c - '0';
1640}
1641
1642#if defined(FEAT_TERMRESPONSE) \
1643 || (defined(FEAT_GUI_GTK) && defined(FEAT_WINDOWS)) || defined(PROTO)
1644/*
1645 * Convert two hex characters to a byte.
1646 * Return -1 if one of the characters is not hex.
1647 */
1648 int
1649hexhex2nr(p)
1650 char_u *p;
1651{
1652 if (!vim_isxdigit(p[0]) || !vim_isxdigit(p[1]))
1653 return -1;
1654 return (hex2nr(p[0]) << 4) + hex2nr(p[1]);
1655}
1656#endif
1657
1658/*
1659 * Return TRUE if "str" starts with a backslash that should be removed.
1660 * For MS-DOS, WIN32 and OS/2 this is only done when the character after the
1661 * backslash is not a normal file name character.
1662 * '$' is a valid file name character, we don't remove the backslash before
1663 * it. This means it is not possible to use an environment variable after a
1664 * backslash. "C:\$VIM\doc" is taken literally, only "$VIM\doc" works.
1665 * Although "\ name" is valid, the backslash in "Program\ files" must be
1666 * removed. Assume a file name doesn't start with a space.
1667 * For multi-byte names, never remove a backslash before a non-ascii
1668 * character, assume that all multi-byte characters are valid file name
1669 * characters.
1670 */
1671 int
1672rem_backslash(str)
1673 char_u *str;
1674{
1675#ifdef BACKSLASH_IN_FILENAME
1676 return (str[0] == '\\'
1677# ifdef FEAT_MBYTE
1678 && str[1] < 0x80
1679# endif
1680 && (str[1] == ' '
1681 || (str[1] != NUL
1682 && str[1] != '*'
1683 && str[1] != '?'
1684 && !vim_isfilec(str[1]))));
1685#else
1686 return (str[0] == '\\' && str[1] != NUL);
1687#endif
1688}
1689
1690/*
1691 * Halve the number of backslashes in a file name argument.
1692 * For MS-DOS we only do this if the character after the backslash
1693 * is not a normal file character.
1694 */
1695 void
1696backslash_halve(p)
1697 char_u *p;
1698{
1699 for ( ; *p; ++p)
1700 if (rem_backslash(p))
1701 STRCPY(p, p + 1);
1702}
1703
1704/*
1705 * backslash_halve() plus save the result in allocated memory.
1706 */
1707 char_u *
1708backslash_halve_save(p)
1709 char_u *p;
1710{
1711 char_u *res;
1712
1713 res = vim_strsave(p);
1714 if (res == NULL)
1715 return p;
1716 backslash_halve(res);
1717 return res;
1718}
1719
1720#if (defined(EBCDIC) && defined(FEAT_POSTSCRIPT)) || defined(PROTO)
1721/*
1722 * Table for EBCDIC to ASCII conversion unashamedly taken from xxd.c!
1723 * The first 64 entries have been added to map control characters defined in
1724 * ascii.h
1725 */
1726static char_u ebcdic2ascii_tab[256] =
1727{
1728 0000, 0001, 0002, 0003, 0004, 0011, 0006, 0177,
1729 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017,
1730 0020, 0021, 0022, 0023, 0024, 0012, 0010, 0027,
1731 0030, 0031, 0032, 0033, 0033, 0035, 0036, 0037,
1732 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
1733 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
1734 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
1735 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
1736 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246,
1737 0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174,
1738 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
1739 0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176,
1740 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267,
1741 0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077,
1742 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301,
1743 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042,
1744 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
1745 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311,
1746 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160,
1747 0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320,
1748 0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170,
1749 0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327,
1750 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
1751 0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347,
1752 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
1753 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355,
1754 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120,
1755 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363,
1756 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130,
1757 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371,
1758 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
1759 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377
1760};
1761
1762/*
1763 * Convert a buffer worth of characters from EBCDIC to ASCII. Only useful if
1764 * wanting 7-bit ASCII characters out the other end.
1765 */
1766 void
1767ebcdic2ascii(buffer, len)
1768 char_u *buffer;
1769 int len;
1770{
1771 int i;
1772
1773 for (i = 0; i < len; i++)
1774 buffer[i] = ebcdic2ascii_tab[buffer[i]];
1775}
1776#endif