Mercurial > vim
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; |