comparison src/misc1.c @ 14175:2ad722003b36 v8.1.0105

patch 8.1.0105: all tab stops are the same commit https://github.com/vim/vim/commit/04958cbaf25eea27eceedaa987adfb354ad5f7fd Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jun 23 19:23:02 2018 +0200 patch 8.1.0105: all tab stops are the same Problem: All tab stops are the same. Solution: Add the variable tabstop feature. (Christian Brabandt, closes #2711)
author Christian Brabandt <cb@256bit.org>
date Sat, 23 Jun 2018 19:30:07 +0200
parents 352c2832d17f
children 95030c543411
comparison
equal deleted inserted replaced
14174:d36eedd19166 14175:2ad722003b36
34 * Count the size (in window cells) of the indent in the current line. 34 * Count the size (in window cells) of the indent in the current line.
35 */ 35 */
36 int 36 int
37 get_indent(void) 37 get_indent(void)
38 { 38 {
39 #ifdef FEAT_VARTABS
40 return get_indent_str_vtab(ml_get_curline(), (int)curbuf->b_p_ts,
41 curbuf->b_p_vts_array, FALSE);
42 #else
39 return get_indent_str(ml_get_curline(), (int)curbuf->b_p_ts, FALSE); 43 return get_indent_str(ml_get_curline(), (int)curbuf->b_p_ts, FALSE);
44 #endif
40 } 45 }
41 46
42 /* 47 /*
43 * Count the size (in window cells) of the indent in line "lnum". 48 * Count the size (in window cells) of the indent in line "lnum".
44 */ 49 */
45 int 50 int
46 get_indent_lnum(linenr_T lnum) 51 get_indent_lnum(linenr_T lnum)
47 { 52 {
53 #ifdef FEAT_VARTABS
54 return get_indent_str_vtab(ml_get(lnum), (int)curbuf->b_p_ts,
55 curbuf->b_p_vts_array, FALSE);
56 #else
48 return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts, FALSE); 57 return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts, FALSE);
58 #endif
49 } 59 }
50 60
51 #if defined(FEAT_FOLDING) || defined(PROTO) 61 #if defined(FEAT_FOLDING) || defined(PROTO)
52 /* 62 /*
53 * Count the size (in window cells) of the indent in line "lnum" of buffer 63 * Count the size (in window cells) of the indent in line "lnum" of buffer
54 * "buf". 64 * "buf".
55 */ 65 */
56 int 66 int
57 get_indent_buf(buf_T *buf, linenr_T lnum) 67 get_indent_buf(buf_T *buf, linenr_T lnum)
58 { 68 {
69 #ifdef FEAT_VARTABS
70 return get_indent_str_vtab(ml_get_buf(buf, lnum, FALSE),
71 (int)curbuf->b_p_ts, buf->b_p_vts_array, FALSE);
72 #else
59 return get_indent_str(ml_get_buf(buf, lnum, FALSE), (int)buf->b_p_ts, FALSE); 73 return get_indent_str(ml_get_buf(buf, lnum, FALSE), (int)buf->b_p_ts, FALSE);
74 #endif
60 } 75 }
61 #endif 76 #endif
62 77
63 /* 78 /*
64 * count the size (in window cells) of the indent in line "ptr", with 79 * count the size (in window cells) of the indent in line "ptr", with
88 else 103 else
89 break; 104 break;
90 } 105 }
91 return count; 106 return count;
92 } 107 }
108
109 #ifdef FEAT_VARTABS
110 /*
111 * Count the size (in window cells) of the indent in line "ptr", using
112 * variable tabstops.
113 * if "list" is TRUE, count only screen size for tabs.
114 */
115 int
116 get_indent_str_vtab(char_u *ptr, int ts, int *vts, int list)
117 {
118 int count = 0;
119
120 for ( ; *ptr; ++ptr)
121 {
122 if (*ptr == TAB) /* count a tab for what it is worth */
123 {
124 if (!list || lcs_tab1)
125 count += tabstop_padding(count, ts, vts);
126 else
127 /* In list mode, when tab is not set, count screen char width
128 * for Tab, displays: ^I */
129 count += ptr2cells(ptr);
130 }
131 else if (*ptr == ' ')
132 ++count; /* count a space for one */
133 else
134 break;
135 }
136 return count;
137 }
138 #endif
93 139
94 /* 140 /*
95 * Set the indent of the current line. 141 * Set the indent of the current line.
96 * Leaves the cursor on the first non-blank in the line. 142 * Leaves the cursor on the first non-blank in the line.
97 * Caller must take care of undo. 143 * Caller must take care of undo.
113 int todo; 159 int todo;
114 int ind_len; /* measured in characters */ 160 int ind_len; /* measured in characters */
115 int line_len; 161 int line_len;
116 int doit = FALSE; 162 int doit = FALSE;
117 int ind_done = 0; /* measured in spaces */ 163 int ind_done = 0; /* measured in spaces */
164 #ifdef FEAT_VARTABS
165 int ind_col = 0;
166 #endif
118 int tab_pad; 167 int tab_pad;
119 int retval = FALSE; 168 int retval = FALSE;
120 int orig_char_len = -1; /* number of initial whitespace chars when 169 int orig_char_len = -1; /* number of initial whitespace chars when
121 'et' and 'pi' are both set */ 170 'et' and 'pi' are both set */
122 171
145 /* count as many characters as we can use */ 194 /* count as many characters as we can use */
146 while (todo > 0 && VIM_ISWHITE(*p)) 195 while (todo > 0 && VIM_ISWHITE(*p))
147 { 196 {
148 if (*p == TAB) 197 if (*p == TAB)
149 { 198 {
199 #ifdef FEAT_VARTABS
200 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
201 curbuf->b_p_vts_array);
202 #else
150 tab_pad = (int)curbuf->b_p_ts 203 tab_pad = (int)curbuf->b_p_ts
151 - (ind_done % (int)curbuf->b_p_ts); 204 - (ind_done % (int)curbuf->b_p_ts);
205 #endif
152 /* stop if this tab will overshoot the target */ 206 /* stop if this tab will overshoot the target */
153 if (todo < tab_pad) 207 if (todo < tab_pad)
154 break; 208 break;
155 todo -= tab_pad; 209 todo -= tab_pad;
156 ++ind_len; 210 ++ind_len;
163 ++ind_done; 217 ++ind_done;
164 } 218 }
165 ++p; 219 ++p;
166 } 220 }
167 221
222 #ifdef FEAT_VARTABS
223 /* These diverge from this point. */
224 ind_col = ind_done;
225 #endif
168 /* Set initial number of whitespace chars to copy if we are 226 /* Set initial number of whitespace chars to copy if we are
169 * preserving indent but expandtab is set */ 227 * preserving indent but expandtab is set */
170 if (curbuf->b_p_et) 228 if (curbuf->b_p_et)
171 orig_char_len = ind_len; 229 orig_char_len = ind_len;
172 230
173 /* Fill to next tabstop with a tab, if possible */ 231 /* Fill to next tabstop with a tab, if possible */
232 #ifdef FEAT_VARTABS
233 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
234 curbuf->b_p_vts_array);
235 #else
174 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); 236 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
237 #endif
175 if (todo >= tab_pad && orig_char_len == -1) 238 if (todo >= tab_pad && orig_char_len == -1)
176 { 239 {
177 doit = TRUE; 240 doit = TRUE;
178 todo -= tab_pad; 241 todo -= tab_pad;
179 ++ind_len; 242 ++ind_len;
180 /* ind_done += tab_pad; */ 243 /* ind_done += tab_pad; */
244 #ifdef FEAT_VARTABS
245 ind_col += tab_pad;
246 #endif
181 } 247 }
182 } 248 }
183 249
184 /* count tabs required for indent */ 250 /* count tabs required for indent */
251 #ifdef FEAT_VARTABS
252 for (;;)
253 {
254 tab_pad = tabstop_padding(ind_col, curbuf->b_p_ts,
255 curbuf->b_p_vts_array);
256 if (todo < tab_pad)
257 break;
258 if (*p != TAB)
259 doit = TRUE;
260 else
261 ++p;
262 todo -= tab_pad;
263 ++ind_len;
264 ind_col += tab_pad;
265 }
266 #else
185 while (todo >= (int)curbuf->b_p_ts) 267 while (todo >= (int)curbuf->b_p_ts)
186 { 268 {
187 if (*p != TAB) 269 if (*p != TAB)
188 doit = TRUE; 270 doit = TRUE;
189 else 271 else
190 ++p; 272 ++p;
191 todo -= (int)curbuf->b_p_ts; 273 todo -= (int)curbuf->b_p_ts;
192 ++ind_len; 274 ++ind_len;
193 /* ind_done += (int)curbuf->b_p_ts; */ 275 /* ind_done += (int)curbuf->b_p_ts; */
194 } 276 }
277 #endif
195 } 278 }
196 /* count spaces required for indent */ 279 /* count spaces required for indent */
197 while (todo > 0) 280 while (todo > 0)
198 { 281 {
199 if (*p != ' ') 282 if (*p != ' ')
264 347
265 while (todo > 0 && VIM_ISWHITE(*p)) 348 while (todo > 0 && VIM_ISWHITE(*p))
266 { 349 {
267 if (*p == TAB) 350 if (*p == TAB)
268 { 351 {
352 #ifdef FEAT_VARTABS
353 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
354 curbuf->b_p_vts_array);
355 #else
269 tab_pad = (int)curbuf->b_p_ts 356 tab_pad = (int)curbuf->b_p_ts
270 - (ind_done % (int)curbuf->b_p_ts); 357 - (ind_done % (int)curbuf->b_p_ts);
358 #endif
271 /* stop if this tab will overshoot the target */ 359 /* stop if this tab will overshoot the target */
272 if (todo < tab_pad) 360 if (todo < tab_pad)
273 break; 361 break;
274 todo -= tab_pad; 362 todo -= tab_pad;
275 ind_done += tab_pad; 363 ind_done += tab_pad;
281 } 369 }
282 *s++ = *p++; 370 *s++ = *p++;
283 } 371 }
284 372
285 /* Fill to next tabstop with a tab, if possible */ 373 /* Fill to next tabstop with a tab, if possible */
374 #ifdef FEAT_VARTABS
375 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
376 curbuf->b_p_vts_array);
377 #else
286 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); 378 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
379 #endif
287 if (todo >= tab_pad) 380 if (todo >= tab_pad)
288 { 381 {
289 *s++ = TAB; 382 *s++ = TAB;
290 todo -= tab_pad; 383 todo -= tab_pad;
384 #ifdef FEAT_VARTABS
385 ind_done += tab_pad;
386 #endif
291 } 387 }
292 388
293 p = skipwhite(p); 389 p = skipwhite(p);
294 } 390 }
295 391
392 #ifdef FEAT_VARTABS
393 for (;;)
394 {
395 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
396 curbuf->b_p_vts_array);
397 if (todo < tab_pad)
398 break;
399 *s++ = TAB;
400 todo -= tab_pad;
401 ind_done += tab_pad;
402 }
403 #else
296 while (todo >= (int)curbuf->b_p_ts) 404 while (todo >= (int)curbuf->b_p_ts)
297 { 405 {
298 *s++ = TAB; 406 *s++ = TAB;
299 todo -= (int)curbuf->b_p_ts; 407 todo -= (int)curbuf->b_p_ts;
300 } 408 }
409 #endif
301 } 410 }
302 while (todo > 0) 411 while (todo > 0)
303 { 412 {
304 *s++ = ' '; 413 *s++ = ' ';
305 --todo; 414 --todo;
348 int ind_len; 457 int ind_len;
349 int line_len = 0; 458 int line_len = 0;
350 int tab_pad; 459 int tab_pad;
351 int ind_done; 460 int ind_done;
352 int round; 461 int round;
462 #ifdef FEAT_VARTABS
463 int ind_col;
464 #endif
353 465
354 /* Round 1: compute the number of characters needed for the indent 466 /* Round 1: compute the number of characters needed for the indent
355 * Round 2: copy the characters. */ 467 * Round 2: copy the characters. */
356 for (round = 1; round <= 2; ++round) 468 for (round = 1; round <= 2; ++round)
357 { 469 {
358 todo = size; 470 todo = size;
359 ind_len = 0; 471 ind_len = 0;
360 ind_done = 0; 472 ind_done = 0;
473 #ifdef FEAT_VARTABS
474 ind_col = 0;
475 #endif
361 s = src; 476 s = src;
362 477
363 /* Count/copy the usable portion of the source line */ 478 /* Count/copy the usable portion of the source line */
364 while (todo > 0 && VIM_ISWHITE(*s)) 479 while (todo > 0 && VIM_ISWHITE(*s))
365 { 480 {
366 if (*s == TAB) 481 if (*s == TAB)
367 { 482 {
483 #ifdef FEAT_VARTABS
484 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
485 curbuf->b_p_vts_array);
486 #else
368 tab_pad = (int)curbuf->b_p_ts 487 tab_pad = (int)curbuf->b_p_ts
369 - (ind_done % (int)curbuf->b_p_ts); 488 - (ind_done % (int)curbuf->b_p_ts);
489 #endif
370 /* Stop if this tab will overshoot the target */ 490 /* Stop if this tab will overshoot the target */
371 if (todo < tab_pad) 491 if (todo < tab_pad)
372 break; 492 break;
373 todo -= tab_pad; 493 todo -= tab_pad;
374 ind_done += tab_pad; 494 ind_done += tab_pad;
495 #ifdef FEAT_VARTABS
496 ind_col += tab_pad;
497 #endif
375 } 498 }
376 else 499 else
377 { 500 {
378 --todo; 501 --todo;
379 ++ind_done; 502 ++ind_done;
503 #ifdef FEAT_VARTABS
504 ++ind_col;
505 #endif
380 } 506 }
381 ++ind_len; 507 ++ind_len;
382 if (p != NULL) 508 if (p != NULL)
383 *p++ = *s; 509 *p++ = *s;
384 ++s; 510 ++s;
385 } 511 }
386 512
387 /* Fill to next tabstop with a tab, if possible */ 513 /* Fill to next tabstop with a tab, if possible */
514 #ifdef FEAT_VARTABS
515 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
516 curbuf->b_p_vts_array);
517 #else
388 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); 518 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
519 #endif
389 if (todo >= tab_pad && !curbuf->b_p_et) 520 if (todo >= tab_pad && !curbuf->b_p_et)
390 { 521 {
391 todo -= tab_pad; 522 todo -= tab_pad;
392 ++ind_len; 523 ++ind_len;
524 #ifdef FEAT_VARTABS
525 ind_col += tab_pad;
526 #endif
393 if (p != NULL) 527 if (p != NULL)
394 *p++ = TAB; 528 *p++ = TAB;
395 } 529 }
396 530
397 /* Add tabs required for indent */ 531 /* Add tabs required for indent */
398 while (todo >= (int)curbuf->b_p_ts && !curbuf->b_p_et) 532 if (!curbuf->b_p_et)
399 { 533 {
400 todo -= (int)curbuf->b_p_ts; 534 #ifdef FEAT_VARTABS
401 ++ind_len; 535 for (;;)
402 if (p != NULL) 536 {
403 *p++ = TAB; 537 tab_pad = tabstop_padding(ind_col, curbuf->b_p_ts,
538 curbuf->b_p_vts_array);
539 if (todo < tab_pad)
540 break;
541 todo -= tab_pad;
542 ++ind_len;
543 ind_col += tab_pad;
544 if (p != NULL)
545 *p++ = TAB;
546 }
547 #else
548 while (todo >= (int)curbuf->b_p_ts)
549 {
550 todo -= (int)curbuf->b_p_ts;
551 ++ind_len;
552 if (p != NULL)
553 *p++ = TAB;
554 }
555 #endif
404 } 556 }
405 557
406 /* Count/add spaces required for indent */ 558 /* Count/add spaces required for indent */
407 while (todo > 0) 559 while (todo > 0)
408 { 560 {
495 { 647 {
496 static int prev_indent = 0; /* cached indent value */ 648 static int prev_indent = 0; /* cached indent value */
497 static long prev_ts = 0L; /* cached tabstop value */ 649 static long prev_ts = 0L; /* cached tabstop value */
498 static char_u *prev_line = NULL; /* cached pointer to line */ 650 static char_u *prev_line = NULL; /* cached pointer to line */
499 static varnumber_T prev_tick = 0; /* changedtick of cached value */ 651 static varnumber_T prev_tick = 0; /* changedtick of cached value */
652 #ifdef FEAT_VARTABS
653 static int *prev_vts = NULL; /* cached vartabs values */
654 #endif
500 int bri = 0; 655 int bri = 0;
501 /* window width minus window margin space, i.e. what rests for text */ 656 /* window width minus window margin space, i.e. what rests for text */
502 const int eff_wwidth = wp->w_width 657 const int eff_wwidth = wp->w_width
503 - ((wp->w_p_nu || wp->w_p_rnu) 658 - ((wp->w_p_nu || wp->w_p_rnu)
504 && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL) 659 && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL)
505 ? number_width(wp) + 1 : 0); 660 ? number_width(wp) + 1 : 0);
506 661
507 /* used cached indent, unless pointer or 'tabstop' changed */ 662 /* used cached indent, unless pointer or 'tabstop' changed */
508 if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts 663 if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts
509 || prev_tick != CHANGEDTICK(wp->w_buffer)) 664 || prev_tick != CHANGEDTICK(wp->w_buffer)
665 #ifdef FEAT_VARTABS
666 || prev_vts != wp->w_buffer->b_p_vts_array
667 #endif
668 )
510 { 669 {
511 prev_line = line; 670 prev_line = line;
512 prev_ts = wp->w_buffer->b_p_ts; 671 prev_ts = wp->w_buffer->b_p_ts;
513 prev_tick = CHANGEDTICK(wp->w_buffer); 672 prev_tick = CHANGEDTICK(wp->w_buffer);
673 #ifdef FEAT_VARTABS
674 prev_vts = wp->w_buffer->b_p_vts_array;
675 prev_indent = get_indent_str_vtab(line,
676 (int)wp->w_buffer->b_p_ts,
677 wp->w_buffer->b_p_vts_array, wp->w_p_list);
678 #else
514 prev_indent = get_indent_str(line, 679 prev_indent = get_indent_str(line,
515 (int)wp->w_buffer->b_p_ts, wp->w_p_list); 680 (int)wp->w_buffer->b_p_ts, wp->w_p_list);
681 #endif
516 } 682 }
517 bri = prev_indent + wp->w_p_brishift; 683 bri = prev_indent + wp->w_p_brishift;
518 684
519 /* indent minus the length of the showbreak string */ 685 /* indent minus the length of the showbreak string */
520 if (wp->w_p_brisbr) 686 if (wp->w_p_brisbr)
739 ) 905 )
740 { 906 {
741 /* 907 /*
742 * count white space on current line 908 * count white space on current line
743 */ 909 */
910 #ifdef FEAT_VARTABS
911 newindent = get_indent_str_vtab(saved_line, curbuf->b_p_ts,
912 curbuf->b_p_vts_array, FALSE);
913 #else
744 newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts, FALSE); 914 newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts, FALSE);
915 #endif
745 if (newindent == 0 && !(flags & OPENLINE_COM_LIST)) 916 if (newindent == 0 && !(flags & OPENLINE_COM_LIST))
746 newindent = second_line_indent; /* for ^^D command in insert mode */ 917 newindent = second_line_indent; /* for ^^D command in insert mode */
747 918
748 #ifdef FEAT_SMARTINDENT 919 #ifdef FEAT_SMARTINDENT
749 /* 920 /*
1262 if (curbuf->b_p_ai 1433 if (curbuf->b_p_ai
1263 #ifdef FEAT_SMARTINDENT 1434 #ifdef FEAT_SMARTINDENT
1264 || do_si 1435 || do_si
1265 #endif 1436 #endif
1266 ) 1437 )
1267 newindent = get_indent_str(leader, (int)curbuf->b_p_ts, FALSE); 1438 #ifdef FEAT_VARTABS
1439 newindent = get_indent_str_vtab(leader, curbuf->b_p_ts,
1440 curbuf->b_p_vts_array, FALSE);
1441 #else
1442 newindent = get_indent_str(leader,
1443 (int)curbuf->b_p_ts, FALSE);
1444 #endif
1268 1445
1269 /* Add the indent offset */ 1446 /* Add the indent offset */
1270 if (newindent + off < 0) 1447 if (newindent + off < 0)
1271 { 1448 {
1272 off = -newindent; 1449 off = -newindent;