xref: /vim-8.2.3635/src/indent.c (revision ed37d9b3)
1 /* vi:set ts=8 sts=4 sw=4 noet:
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 /*
11  * indent.c: Indentation related functions
12  */
13 
14 #include "vim.h"
15 
16 #if defined(FEAT_VARTABS) || defined(PROTO)
17 
18 /*
19  * Set the integer values corresponding to the string setting of 'vartabstop'.
20  * "array" will be set, caller must free it if needed.
21  */
22     int
23 tabstop_set(char_u *var, int **array)
24 {
25     int valcount = 1;
26     int t;
27     char_u *cp;
28 
29     if (var[0] == NUL || (var[0] == '0' && var[1] == NUL))
30     {
31 	*array = NULL;
32 	return TRUE;
33     }
34 
35     for (cp = var; *cp != NUL; ++cp)
36     {
37 	if (cp == var || cp[-1] == ',')
38 	{
39 	    char_u *end;
40 
41 	    if (strtol((char *)cp, (char **)&end, 10) <= 0)
42 	    {
43 		if (cp != end)
44 		    emsg(_(e_positive));
45 		else
46 		    emsg(_(e_invarg));
47 		return FALSE;
48 	    }
49 	}
50 
51 	if (VIM_ISDIGIT(*cp))
52 	    continue;
53 	if (cp[0] == ',' && cp > var && cp[-1] != ',' && cp[1] != NUL)
54 	{
55 	    ++valcount;
56 	    continue;
57 	}
58 	emsg(_(e_invarg));
59 	return FALSE;
60     }
61 
62     *array = ALLOC_MULT(int, valcount + 1);
63     if (*array == NULL)
64 	return FALSE;
65     (*array)[0] = valcount;
66 
67     t = 1;
68     for (cp = var; *cp != NUL;)
69     {
70 	(*array)[t++] = atoi((char *)cp);
71 	while (*cp  != NUL && *cp != ',')
72 	    ++cp;
73 	if (*cp != NUL)
74 	    ++cp;
75     }
76 
77     return TRUE;
78 }
79 
80 /*
81  * Calculate the number of screen spaces a tab will occupy.
82  * If "vts" is set then the tab widths are taken from that array,
83  * otherwise the value of ts is used.
84  */
85     int
86 tabstop_padding(colnr_T col, int ts_arg, int *vts)
87 {
88     int		ts = ts_arg == 0 ? 8 : ts_arg;
89     int		tabcount;
90     colnr_T	tabcol = 0;
91     int		t;
92     int		padding = 0;
93 
94     if (vts == NULL || vts[0] == 0)
95 	return ts - (col % ts);
96 
97     tabcount = vts[0];
98 
99     for (t = 1; t <= tabcount; ++t)
100     {
101 	tabcol += vts[t];
102 	if (tabcol > col)
103 	{
104 	    padding = (int)(tabcol - col);
105 	    break;
106 	}
107     }
108     if (t > tabcount)
109 	padding = vts[tabcount] - (int)((col - tabcol) % vts[tabcount]);
110 
111     return padding;
112 }
113 
114 /*
115  * Find the size of the tab that covers a particular column.
116  */
117     int
118 tabstop_at(colnr_T col, int ts, int *vts)
119 {
120     int		tabcount;
121     colnr_T	tabcol = 0;
122     int		t;
123     int		tab_size = 0;
124 
125     if (vts == 0 || vts[0] == 0)
126 	return ts;
127 
128     tabcount = vts[0];
129     for (t = 1; t <= tabcount; ++t)
130     {
131 	tabcol += vts[t];
132 	if (tabcol > col)
133 	{
134 	    tab_size = vts[t];
135 	    break;
136 	}
137     }
138     if (t > tabcount)
139 	tab_size = vts[tabcount];
140 
141     return tab_size;
142 }
143 
144 /*
145  * Find the column on which a tab starts.
146  */
147     colnr_T
148 tabstop_start(colnr_T col, int ts, int *vts)
149 {
150     int		tabcount;
151     colnr_T	tabcol = 0;
152     int		t;
153     int         excess;
154 
155     if (vts == NULL || vts[0] == 0)
156 	return (col / ts) * ts;
157 
158     tabcount = vts[0];
159     for (t = 1; t <= tabcount; ++t)
160     {
161 	tabcol += vts[t];
162 	if (tabcol > col)
163 	    return tabcol - vts[t];
164     }
165 
166     excess = tabcol % vts[tabcount];
167     return excess + ((col - excess) / vts[tabcount]) * vts[tabcount];
168 }
169 
170 /*
171  * Find the number of tabs and spaces necessary to get from one column
172  * to another.
173  */
174     void
175 tabstop_fromto(
176 	colnr_T start_col,
177 	colnr_T end_col,
178 	int	ts_arg,
179 	int	*vts,
180 	int	*ntabs,
181 	int	*nspcs)
182 {
183     int		spaces = end_col - start_col;
184     colnr_T	tabcol = 0;
185     int		padding = 0;
186     int		tabcount;
187     int		t;
188     int		ts = ts_arg == 0 ? curbuf->b_p_ts : ts_arg;
189 
190     if (vts == NULL || vts[0] == 0)
191     {
192 	int tabs = 0;
193 	int initspc = 0;
194 
195 	initspc = ts - (start_col % ts);
196 	if (spaces >= initspc)
197 	{
198 	    spaces -= initspc;
199 	    tabs++;
200 	}
201 	tabs += spaces / ts;
202 	spaces -= (spaces / ts) * ts;
203 
204 	*ntabs = tabs;
205 	*nspcs = spaces;
206 	return;
207     }
208 
209     // Find the padding needed to reach the next tabstop.
210     tabcount = vts[0];
211     for (t = 1; t <= tabcount; ++t)
212     {
213 	tabcol += vts[t];
214 	if (tabcol > start_col)
215 	{
216 	    padding = (int)(tabcol - start_col);
217 	    break;
218 	}
219     }
220     if (t > tabcount)
221 	padding = vts[tabcount] - (int)((start_col - tabcol) % vts[tabcount]);
222 
223     // If the space needed is less than the padding no tabs can be used.
224     if (spaces < padding)
225     {
226 	*ntabs = 0;
227 	*nspcs = spaces;
228 	return;
229     }
230 
231     *ntabs = 1;
232     spaces -= padding;
233 
234     // At least one tab has been used. See if any more will fit.
235     while (spaces != 0 && ++t <= tabcount)
236     {
237 	padding = vts[t];
238 	if (spaces < padding)
239 	{
240 	    *nspcs = spaces;
241 	    return;
242 	}
243 	++*ntabs;
244 	spaces -= padding;
245     }
246 
247     *ntabs += spaces / vts[tabcount];
248     *nspcs =  spaces % vts[tabcount];
249 }
250 
251 /*
252  * See if two tabstop arrays contain the same values.
253  */
254     static int
255 tabstop_eq(int *ts1, int *ts2)
256 {
257     int		t;
258 
259     if ((ts1 == 0 && ts2) || (ts1 && ts2 == 0))
260 	return FALSE;
261     if (ts1 == ts2)
262 	return TRUE;
263     if (ts1[0] != ts2[0])
264 	return FALSE;
265 
266     for (t = 1; t <= ts1[0]; ++t)
267 	if (ts1[t] != ts2[t])
268 	    return FALSE;
269 
270     return TRUE;
271 }
272 
273 # if defined(FEAT_BEVAL) || defined(PROTO)
274 /*
275  * Copy a tabstop array, allocating space for the new array.
276  */
277     int *
278 tabstop_copy(int *oldts)
279 {
280     int		*newts;
281     int		t;
282 
283     if (oldts == NULL)
284 	return NULL;
285     newts = ALLOC_MULT(int, oldts[0] + 1);
286     if (newts != NULL)
287 	for (t = 0; t <= oldts[0]; ++t)
288 	    newts[t] = oldts[t];
289     return newts;
290 }
291 # endif
292 
293 /*
294  * Return a count of the number of tabstops.
295  */
296     int
297 tabstop_count(int *ts)
298 {
299     return ts != NULL ? ts[0] : 0;
300 }
301 
302 /*
303  * Return the first tabstop, or 8 if there are no tabstops defined.
304  */
305     int
306 tabstop_first(int *ts)
307 {
308     return ts != NULL ? ts[1] : 8;
309 }
310 
311 #endif
312 
313 /*
314  * Return the effective shiftwidth value for current buffer, using the
315  * 'tabstop' value when 'shiftwidth' is zero.
316  */
317     long
318 get_sw_value(buf_T *buf)
319 {
320     return get_sw_value_col(buf, 0);
321 }
322 
323 /*
324  * Idem, using "pos".
325  */
326     static long
327 get_sw_value_pos(buf_T *buf, pos_T *pos)
328 {
329     pos_T save_cursor = curwin->w_cursor;
330     long sw_value;
331 
332     curwin->w_cursor = *pos;
333     sw_value = get_sw_value_col(buf, get_nolist_virtcol());
334     curwin->w_cursor = save_cursor;
335     return sw_value;
336 }
337 
338 /*
339  * Idem, using the first non-black in the current line.
340  */
341     long
342 get_sw_value_indent(buf_T *buf)
343 {
344     pos_T pos = curwin->w_cursor;
345 
346     pos.col = getwhitecols_curline();
347     return get_sw_value_pos(buf, &pos);
348 }
349 
350 /*
351  * Idem, using virtual column "col".
352  */
353     long
354 get_sw_value_col(buf_T *buf, colnr_T col UNUSED)
355 {
356     return buf->b_p_sw ? buf->b_p_sw :
357 #ifdef FEAT_VARTABS
358 	tabstop_at(col, buf->b_p_ts, buf->b_p_vts_array);
359 #else
360 	buf->b_p_ts;
361 #endif
362 }
363 
364 /*
365  * Return the effective softtabstop value for the current buffer, using the
366  * 'shiftwidth' value when 'softtabstop' is negative.
367  */
368     long
369 get_sts_value(void)
370 {
371     return curbuf->b_p_sts < 0 ? get_sw_value(curbuf) : curbuf->b_p_sts;
372 }
373 
374 /*
375  * Count the size (in window cells) of the indent in the current line.
376  */
377     int
378 get_indent(void)
379 {
380 #ifdef FEAT_VARTABS
381     return get_indent_str_vtab(ml_get_curline(), (int)curbuf->b_p_ts,
382 						 curbuf->b_p_vts_array, FALSE);
383 #else
384     return get_indent_str(ml_get_curline(), (int)curbuf->b_p_ts, FALSE);
385 #endif
386 }
387 
388 /*
389  * Count the size (in window cells) of the indent in line "lnum".
390  */
391     int
392 get_indent_lnum(linenr_T lnum)
393 {
394 #ifdef FEAT_VARTABS
395     return get_indent_str_vtab(ml_get(lnum), (int)curbuf->b_p_ts,
396 						 curbuf->b_p_vts_array, FALSE);
397 #else
398     return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts, FALSE);
399 #endif
400 }
401 
402 #if defined(FEAT_FOLDING) || defined(PROTO)
403 /*
404  * Count the size (in window cells) of the indent in line "lnum" of buffer
405  * "buf".
406  */
407     int
408 get_indent_buf(buf_T *buf, linenr_T lnum)
409 {
410 # ifdef FEAT_VARTABS
411     return get_indent_str_vtab(ml_get_buf(buf, lnum, FALSE),
412 			       (int)curbuf->b_p_ts, buf->b_p_vts_array, FALSE);
413 # else
414     return get_indent_str(ml_get_buf(buf, lnum, FALSE), (int)buf->b_p_ts, FALSE);
415 # endif
416 }
417 #endif
418 
419 /*
420  * count the size (in window cells) of the indent in line "ptr", with
421  * 'tabstop' at "ts"
422  */
423     int
424 get_indent_str(
425     char_u	*ptr,
426     int		ts,
427     int		list) // if TRUE, count only screen size for tabs
428 {
429     int		count = 0;
430 
431     for ( ; *ptr; ++ptr)
432     {
433 	if (*ptr == TAB)
434 	{
435 	    if (!list || lcs_tab1)    // count a tab for what it is worth
436 		count += ts - (count % ts);
437 	    else
438 		// In list mode, when tab is not set, count screen char width
439 		// for Tab, displays: ^I
440 		count += ptr2cells(ptr);
441 	}
442 	else if (*ptr == ' ')
443 	    ++count;		// count a space for one
444 	else
445 	    break;
446     }
447     return count;
448 }
449 
450 #ifdef FEAT_VARTABS
451 /*
452  * Count the size (in window cells) of the indent in line "ptr", using
453  * variable tabstops.
454  * if "list" is TRUE, count only screen size for tabs.
455  */
456     int
457 get_indent_str_vtab(char_u *ptr, int ts, int *vts, int list)
458 {
459     int		count = 0;
460 
461     for ( ; *ptr; ++ptr)
462     {
463 	if (*ptr == TAB)    // count a tab for what it is worth
464 	{
465 	    if (!list || lcs_tab1)
466 		count += tabstop_padding(count, ts, vts);
467 	    else
468 		// In list mode, when tab is not set, count screen char width
469 		// for Tab, displays: ^I
470 		count += ptr2cells(ptr);
471 	}
472 	else if (*ptr == ' ')
473 	    ++count;		// count a space for one
474 	else
475 	    break;
476     }
477     return count;
478 }
479 #endif
480 
481 /*
482  * Set the indent of the current line.
483  * Leaves the cursor on the first non-blank in the line.
484  * Caller must take care of undo.
485  * "flags":
486  *	SIN_CHANGED:	call changed_bytes() if the line was changed.
487  *	SIN_INSERT:	insert the indent in front of the line.
488  *	SIN_UNDO:	save line for undo before changing it.
489  * Returns TRUE if the line was changed.
490  */
491     int
492 set_indent(
493     int		size,		    // measured in spaces
494     int		flags)
495 {
496     char_u	*p;
497     char_u	*newline;
498     char_u	*oldline;
499     char_u	*s;
500     int		todo;
501     int		ind_len;	    // measured in characters
502     int		line_len;
503     int		doit = FALSE;
504     int		ind_done = 0;	    // measured in spaces
505 #ifdef FEAT_VARTABS
506     int		ind_col = 0;
507 #endif
508     int		tab_pad;
509     int		retval = FALSE;
510     int		orig_char_len = -1; // number of initial whitespace chars when
511 				    // 'et' and 'pi' are both set
512 
513     // First check if there is anything to do and compute the number of
514     // characters needed for the indent.
515     todo = size;
516     ind_len = 0;
517     p = oldline = ml_get_curline();
518 
519     // Calculate the buffer size for the new indent, and check to see if it
520     // isn't already set
521 
522     // if 'expandtab' isn't set: use TABs; if both 'expandtab' and
523     // 'preserveindent' are set count the number of characters at the
524     // beginning of the line to be copied
525     if (!curbuf->b_p_et || (!(flags & SIN_INSERT) && curbuf->b_p_pi))
526     {
527 	// If 'preserveindent' is set then reuse as much as possible of
528 	// the existing indent structure for the new indent
529 	if (!(flags & SIN_INSERT) && curbuf->b_p_pi)
530 	{
531 	    ind_done = 0;
532 
533 	    // count as many characters as we can use
534 	    while (todo > 0 && VIM_ISWHITE(*p))
535 	    {
536 		if (*p == TAB)
537 		{
538 #ifdef FEAT_VARTABS
539 		    tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
540 							curbuf->b_p_vts_array);
541 #else
542 		    tab_pad = (int)curbuf->b_p_ts
543 					   - (ind_done % (int)curbuf->b_p_ts);
544 #endif
545 		    // stop if this tab will overshoot the target
546 		    if (todo < tab_pad)
547 			break;
548 		    todo -= tab_pad;
549 		    ++ind_len;
550 		    ind_done += tab_pad;
551 		}
552 		else
553 		{
554 		    --todo;
555 		    ++ind_len;
556 		    ++ind_done;
557 		}
558 		++p;
559 	    }
560 
561 #ifdef FEAT_VARTABS
562 	    // These diverge from this point.
563 	    ind_col = ind_done;
564 #endif
565 	    // Set initial number of whitespace chars to copy if we are
566 	    // preserving indent but expandtab is set
567 	    if (curbuf->b_p_et)
568 		orig_char_len = ind_len;
569 
570 	    // Fill to next tabstop with a tab, if possible
571 #ifdef FEAT_VARTABS
572 	    tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
573 						curbuf->b_p_vts_array);
574 #else
575 	    tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
576 #endif
577 	    if (todo >= tab_pad && orig_char_len == -1)
578 	    {
579 		doit = TRUE;
580 		todo -= tab_pad;
581 		++ind_len;
582 		// ind_done += tab_pad;
583 #ifdef FEAT_VARTABS
584 		ind_col += tab_pad;
585 #endif
586 	    }
587 	}
588 
589 	// count tabs required for indent
590 #ifdef FEAT_VARTABS
591 	for (;;)
592 	{
593 	    tab_pad = tabstop_padding(ind_col, curbuf->b_p_ts,
594 							curbuf->b_p_vts_array);
595 	    if (todo < tab_pad)
596 		break;
597 	    if (*p != TAB)
598 		doit = TRUE;
599 	    else
600 		++p;
601 	    todo -= tab_pad;
602 	    ++ind_len;
603 	    ind_col += tab_pad;
604 	}
605 #else
606 	while (todo >= (int)curbuf->b_p_ts)
607 	{
608 	    if (*p != TAB)
609 		doit = TRUE;
610 	    else
611 		++p;
612 	    todo -= (int)curbuf->b_p_ts;
613 	    ++ind_len;
614 	    // ind_done += (int)curbuf->b_p_ts;
615 	}
616 #endif
617     }
618     // count spaces required for indent
619     while (todo > 0)
620     {
621 	if (*p != ' ')
622 	    doit = TRUE;
623 	else
624 	    ++p;
625 	--todo;
626 	++ind_len;
627 	// ++ind_done;
628     }
629 
630     // Return if the indent is OK already.
631     if (!doit && !VIM_ISWHITE(*p) && !(flags & SIN_INSERT))
632 	return FALSE;
633 
634     // Allocate memory for the new line.
635     if (flags & SIN_INSERT)
636 	p = oldline;
637     else
638 	p = skipwhite(p);
639     line_len = (int)STRLEN(p) + 1;
640 
641     // If 'preserveindent' and 'expandtab' are both set keep the original
642     // characters and allocate accordingly.  We will fill the rest with spaces
643     // after the if (!curbuf->b_p_et) below.
644     if (orig_char_len != -1)
645     {
646 	newline = alloc(orig_char_len + size - ind_done + line_len);
647 	if (newline == NULL)
648 	    return FALSE;
649 	todo = size - ind_done;
650 	ind_len = orig_char_len + todo;    // Set total length of indent in
651 					   // characters, which may have been
652 					   // undercounted until now
653 	p = oldline;
654 	s = newline;
655 	while (orig_char_len > 0)
656 	{
657 	    *s++ = *p++;
658 	    orig_char_len--;
659 	}
660 
661 	// Skip over any additional white space (useful when newindent is less
662 	// than old)
663 	while (VIM_ISWHITE(*p))
664 	    ++p;
665 
666     }
667     else
668     {
669 	todo = size;
670 	newline = alloc(ind_len + line_len);
671 	if (newline == NULL)
672 	    return FALSE;
673 	s = newline;
674     }
675 
676     // Put the characters in the new line.
677     // if 'expandtab' isn't set: use TABs
678     if (!curbuf->b_p_et)
679     {
680 	// If 'preserveindent' is set then reuse as much as possible of
681 	// the existing indent structure for the new indent
682 	if (!(flags & SIN_INSERT) && curbuf->b_p_pi)
683 	{
684 	    p = oldline;
685 	    ind_done = 0;
686 
687 	    while (todo > 0 && VIM_ISWHITE(*p))
688 	    {
689 		if (*p == TAB)
690 		{
691 #ifdef FEAT_VARTABS
692 		    tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
693 							curbuf->b_p_vts_array);
694 #else
695 		    tab_pad = (int)curbuf->b_p_ts
696 					   - (ind_done % (int)curbuf->b_p_ts);
697 #endif
698 		    // stop if this tab will overshoot the target
699 		    if (todo < tab_pad)
700 			break;
701 		    todo -= tab_pad;
702 		    ind_done += tab_pad;
703 		}
704 		else
705 		{
706 		    --todo;
707 		    ++ind_done;
708 		}
709 		*s++ = *p++;
710 	    }
711 
712 	    // Fill to next tabstop with a tab, if possible
713 #ifdef FEAT_VARTABS
714 	    tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
715 						curbuf->b_p_vts_array);
716 #else
717 	    tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
718 #endif
719 	    if (todo >= tab_pad)
720 	    {
721 		*s++ = TAB;
722 		todo -= tab_pad;
723 #ifdef FEAT_VARTABS
724 		ind_done += tab_pad;
725 #endif
726 	    }
727 
728 	    p = skipwhite(p);
729 	}
730 
731 #ifdef FEAT_VARTABS
732 	for (;;)
733 	{
734 	    tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
735 							curbuf->b_p_vts_array);
736 	    if (todo < tab_pad)
737 		break;
738 	    *s++ = TAB;
739 	    todo -= tab_pad;
740 	    ind_done += tab_pad;
741 	}
742 #else
743 	while (todo >= (int)curbuf->b_p_ts)
744 	{
745 	    *s++ = TAB;
746 	    todo -= (int)curbuf->b_p_ts;
747 	}
748 #endif
749     }
750     while (todo > 0)
751     {
752 	*s++ = ' ';
753 	--todo;
754     }
755     mch_memmove(s, p, (size_t)line_len);
756 
757     // Replace the line (unless undo fails).
758     if (!(flags & SIN_UNDO) || u_savesub(curwin->w_cursor.lnum) == OK)
759     {
760 	ml_replace(curwin->w_cursor.lnum, newline, FALSE);
761 	if (flags & SIN_CHANGED)
762 	    changed_bytes(curwin->w_cursor.lnum, 0);
763 
764 	// Correct saved cursor position if it is in this line.
765 	if (saved_cursor.lnum == curwin->w_cursor.lnum)
766 	{
767 	    if (saved_cursor.col >= (colnr_T)(p - oldline))
768 		// cursor was after the indent, adjust for the number of
769 		// bytes added/removed
770 		saved_cursor.col += ind_len - (colnr_T)(p - oldline);
771 	    else if (saved_cursor.col >= (colnr_T)(s - newline))
772 		// cursor was in the indent, and is now after it, put it back
773 		// at the start of the indent (replacing spaces with TAB)
774 		saved_cursor.col = (colnr_T)(s - newline);
775 	}
776 #ifdef FEAT_PROP_POPUP
777 	{
778 	    int added = ind_len - (colnr_T)(p - oldline);
779 
780 	    // When increasing indent this behaves like spaces were inserted at
781 	    // the old indent, when decreasing indent it behaves like spaces
782 	    // were deleted at the new indent.
783 	    adjust_prop_columns(curwin->w_cursor.lnum,
784 		 (colnr_T)(added > 0 ? (p - oldline) : ind_len), added, 0);
785 	}
786 #endif
787 	retval = TRUE;
788     }
789     else
790 	vim_free(newline);
791 
792     curwin->w_cursor.col = ind_len;
793     return retval;
794 }
795 
796 /*
797  * Return the indent of the current line after a number.  Return -1 if no
798  * number was found.  Used for 'n' in 'formatoptions': numbered list.
799  * Since a pattern is used it can actually handle more than numbers.
800  */
801     int
802 get_number_indent(linenr_T lnum)
803 {
804     colnr_T	col;
805     pos_T	pos;
806 
807     regmatch_T	regmatch;
808     int		lead_len = 0;	// length of comment leader
809 
810     if (lnum > curbuf->b_ml.ml_line_count)
811 	return -1;
812     pos.lnum = 0;
813 
814     // In format_lines() (i.e. not insert mode), fo+=q is needed too...
815     if ((State & INSERT) || has_format_option(FO_Q_COMS))
816 	lead_len = get_leader_len(ml_get(lnum), NULL, FALSE, TRUE);
817 
818     regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC);
819     if (regmatch.regprog != NULL)
820     {
821 	regmatch.rm_ic = FALSE;
822 
823 	// vim_regexec() expects a pointer to a line.  This lets us
824 	// start matching for the flp beyond any comment leader...
825 	if (vim_regexec(&regmatch, ml_get(lnum) + lead_len, (colnr_T)0))
826 	{
827 	    pos.lnum = lnum;
828 	    pos.col = (colnr_T)(*regmatch.endp - ml_get(lnum));
829 	    pos.coladd = 0;
830 	}
831 	vim_regfree(regmatch.regprog);
832     }
833 
834     if (pos.lnum == 0 || *ml_get_pos(&pos) == NUL)
835 	return -1;
836     getvcol(curwin, &pos, &col, NULL, NULL);
837     return (int)col;
838 }
839 
840 #if defined(FEAT_LINEBREAK) || defined(PROTO)
841 /*
842  * This is called when 'breakindentopt' is changed and when a window is
843  * initialized.
844  */
845     int
846 briopt_check(win_T *wp)
847 {
848     char_u	*p;
849     int		bri_shift = 0;
850     long	bri_min = 20;
851     int		bri_sbr = FALSE;
852 
853     p = wp->w_p_briopt;
854     while (*p != NUL)
855     {
856 	if (STRNCMP(p, "shift:", 6) == 0
857 		 && ((p[6] == '-' && VIM_ISDIGIT(p[7])) || VIM_ISDIGIT(p[6])))
858 	{
859 	    p += 6;
860 	    bri_shift = getdigits(&p);
861 	}
862 	else if (STRNCMP(p, "min:", 4) == 0 && VIM_ISDIGIT(p[4]))
863 	{
864 	    p += 4;
865 	    bri_min = getdigits(&p);
866 	}
867 	else if (STRNCMP(p, "sbr", 3) == 0)
868 	{
869 	    p += 3;
870 	    bri_sbr = TRUE;
871 	}
872 	if (*p != ',' && *p != NUL)
873 	    return FAIL;
874 	if (*p == ',')
875 	    ++p;
876     }
877 
878     wp->w_briopt_shift = bri_shift;
879     wp->w_briopt_min   = bri_min;
880     wp->w_briopt_sbr   = bri_sbr;
881 
882     return OK;
883 }
884 
885 /*
886  * Return appropriate space number for breakindent, taking influencing
887  * parameters into account. Window must be specified, since it is not
888  * necessarily always the current one.
889  */
890     int
891 get_breakindent_win(
892     win_T	*wp,
893     char_u	*line) // start of the line
894 {
895     static int	    prev_indent = 0;  // cached indent value
896     static long	    prev_ts     = 0L; // cached tabstop value
897     static char_u   *prev_line = NULL; // cached pointer to line
898     static varnumber_T prev_tick = 0;   // changedtick of cached value
899 # ifdef FEAT_VARTABS
900     static int      *prev_vts = NULL;    // cached vartabs values
901 # endif
902     int		    bri = 0;
903     // window width minus window margin space, i.e. what rests for text
904     const int	    eff_wwidth = wp->w_width
905 			    - ((wp->w_p_nu || wp->w_p_rnu)
906 				&& (vim_strchr(p_cpo, CPO_NUMCOL) == NULL)
907 						? number_width(wp) + 1 : 0);
908 
909     // used cached indent, unless pointer or 'tabstop' changed
910     if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts
911 	    || prev_tick != CHANGEDTICK(wp->w_buffer)
912 # ifdef FEAT_VARTABS
913 	    || prev_vts != wp->w_buffer->b_p_vts_array
914 # endif
915 	)
916     {
917 	prev_line = line;
918 	prev_ts = wp->w_buffer->b_p_ts;
919 	prev_tick = CHANGEDTICK(wp->w_buffer);
920 # ifdef FEAT_VARTABS
921 	prev_vts = wp->w_buffer->b_p_vts_array;
922 	prev_indent = get_indent_str_vtab(line,
923 				     (int)wp->w_buffer->b_p_ts,
924 				    wp->w_buffer->b_p_vts_array, wp->w_p_list);
925 # else
926 	prev_indent = get_indent_str(line,
927 				     (int)wp->w_buffer->b_p_ts, wp->w_p_list);
928 # endif
929     }
930     bri = prev_indent + wp->w_briopt_shift;
931 
932     // indent minus the length of the showbreak string
933     if (wp->w_briopt_sbr)
934 	bri -= vim_strsize(get_showbreak_value(wp));
935 
936     // Add offset for number column, if 'n' is in 'cpoptions'
937     bri += win_col_off2(wp);
938 
939     // never indent past left window margin
940     if (bri < 0)
941 	bri = 0;
942     // always leave at least bri_min characters on the left,
943     // if text width is sufficient
944     else if (bri > eff_wwidth - wp->w_briopt_min)
945 	bri = (eff_wwidth - wp->w_briopt_min < 0)
946 					   ? 0 : eff_wwidth - wp->w_briopt_min;
947 
948     return bri;
949 }
950 #endif
951 
952 /*
953  * When extra == 0: Return TRUE if the cursor is before or on the first
954  *		    non-blank in the line.
955  * When extra == 1: Return TRUE if the cursor is before the first non-blank in
956  *		    the line.
957  */
958     int
959 inindent(int extra)
960 {
961     char_u	*ptr;
962     colnr_T	col;
963 
964     for (col = 0, ptr = ml_get_curline(); VIM_ISWHITE(*ptr); ++col)
965 	++ptr;
966     if (col >= curwin->w_cursor.col + extra)
967 	return TRUE;
968     else
969 	return FALSE;
970 }
971 
972 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(PROTO)
973 /*
974  * op_reindent - handle reindenting a block of lines.
975  */
976     void
977 op_reindent(oparg_T *oap, int (*how)(void))
978 {
979     long	i;
980     char_u	*l;
981     int		amount;
982     linenr_T	first_changed = 0;
983     linenr_T	last_changed = 0;
984     linenr_T	start_lnum = curwin->w_cursor.lnum;
985 
986     // Don't even try when 'modifiable' is off.
987     if (!curbuf->b_p_ma)
988     {
989 	emsg(_(e_modifiable));
990 	return;
991     }
992 
993     for (i = oap->line_count; --i >= 0 && !got_int; )
994     {
995 	// it's a slow thing to do, so give feedback so there's no worry that
996 	// the computer's just hung.
997 
998 	if (i > 1
999 		&& (i % 50 == 0 || i == oap->line_count - 1)
1000 		&& oap->line_count > p_report)
1001 	    smsg(_("%ld lines to indent... "), i);
1002 
1003 	// Be vi-compatible: For lisp indenting the first line is not
1004 	// indented, unless there is only one line.
1005 # ifdef FEAT_LISP
1006 	if (i != oap->line_count - 1 || oap->line_count == 1
1007 						    || how != get_lisp_indent)
1008 # endif
1009 	{
1010 	    l = skipwhite(ml_get_curline());
1011 	    if (*l == NUL)		    // empty or blank line
1012 		amount = 0;
1013 	    else
1014 		amount = how();		    // get the indent for this line
1015 
1016 	    if (amount >= 0 && set_indent(amount, SIN_UNDO))
1017 	    {
1018 		// did change the indent, call changed_lines() later
1019 		if (first_changed == 0)
1020 		    first_changed = curwin->w_cursor.lnum;
1021 		last_changed = curwin->w_cursor.lnum;
1022 	    }
1023 	}
1024 	++curwin->w_cursor.lnum;
1025 	curwin->w_cursor.col = 0;  // make sure it's valid
1026     }
1027 
1028     // put cursor on first non-blank of indented line
1029     curwin->w_cursor.lnum = start_lnum;
1030     beginline(BL_SOL | BL_FIX);
1031 
1032     // Mark changed lines so that they will be redrawn.  When Visual
1033     // highlighting was present, need to continue until the last line.  When
1034     // there is no change still need to remove the Visual highlighting.
1035     if (last_changed != 0)
1036 	changed_lines(first_changed, 0,
1037 		oap->is_VIsual ? start_lnum + oap->line_count :
1038 		last_changed + 1, 0L);
1039     else if (oap->is_VIsual)
1040 	redraw_curbuf_later(INVERTED);
1041 
1042     if (oap->line_count > p_report)
1043     {
1044 	i = oap->line_count - (i + 1);
1045 	smsg(NGETTEXT("%ld line indented ",
1046 						 "%ld lines indented ", i), i);
1047     }
1048     if (!cmdmod.lockmarks)
1049     {
1050 	// set '[ and '] marks
1051 	curbuf->b_op_start = oap->start;
1052 	curbuf->b_op_end = oap->end;
1053     }
1054 }
1055 #endif // defined(FEAT_LISP) || defined(FEAT_CINDENT)
1056 
1057 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) || defined(PROTO)
1058 /*
1059  * Return TRUE if lines starting with '#' should be left aligned.
1060  */
1061     int
1062 preprocs_left(void)
1063 {
1064     return
1065 # ifdef FEAT_SMARTINDENT
1066 #  ifdef FEAT_CINDENT
1067 	(curbuf->b_p_si && !curbuf->b_p_cin) ||
1068 #  else
1069 	curbuf->b_p_si
1070 #  endif
1071 # endif
1072 # ifdef FEAT_CINDENT
1073 	(curbuf->b_p_cin && in_cinkeys('#', ' ', TRUE)
1074 					   && curbuf->b_ind_hash_comment == 0)
1075 # endif
1076 	;
1077 }
1078 #endif
1079 
1080 #ifdef FEAT_SMARTINDENT
1081 /*
1082  * Try to do some very smart auto-indenting.
1083  * Used when inserting a "normal" character.
1084  */
1085     void
1086 ins_try_si(int c)
1087 {
1088     pos_T	*pos, old_pos;
1089     char_u	*ptr;
1090     int		i;
1091     int		temp;
1092 
1093     // do some very smart indenting when entering '{' or '}'
1094     if (((did_si || can_si_back) && c == '{') || (can_si && c == '}'))
1095     {
1096 	// for '}' set indent equal to indent of line containing matching '{'
1097 	if (c == '}' && (pos = findmatch(NULL, '{')) != NULL)
1098 	{
1099 	    old_pos = curwin->w_cursor;
1100 	    // If the matching '{' has a ')' immediately before it (ignoring
1101 	    // white-space), then line up with the start of the line
1102 	    // containing the matching '(' if there is one.  This handles the
1103 	    // case where an "if (..\n..) {" statement continues over multiple
1104 	    // lines -- webb
1105 	    ptr = ml_get(pos->lnum);
1106 	    i = pos->col;
1107 	    if (i > 0)		// skip blanks before '{'
1108 		while (--i > 0 && VIM_ISWHITE(ptr[i]))
1109 		    ;
1110 	    curwin->w_cursor.lnum = pos->lnum;
1111 	    curwin->w_cursor.col = i;
1112 	    if (ptr[i] == ')' && (pos = findmatch(NULL, '(')) != NULL)
1113 		curwin->w_cursor = *pos;
1114 	    i = get_indent();
1115 	    curwin->w_cursor = old_pos;
1116 	    if (State & VREPLACE_FLAG)
1117 		change_indent(INDENT_SET, i, FALSE, NUL, TRUE);
1118 	    else
1119 		(void)set_indent(i, SIN_CHANGED);
1120 	}
1121 	else if (curwin->w_cursor.col > 0)
1122 	{
1123 	    // when inserting '{' after "O" reduce indent, but not
1124 	    // more than indent of previous line
1125 	    temp = TRUE;
1126 	    if (c == '{' && can_si_back && curwin->w_cursor.lnum > 1)
1127 	    {
1128 		old_pos = curwin->w_cursor;
1129 		i = get_indent();
1130 		while (curwin->w_cursor.lnum > 1)
1131 		{
1132 		    ptr = skipwhite(ml_get(--(curwin->w_cursor.lnum)));
1133 
1134 		    // ignore empty lines and lines starting with '#'.
1135 		    if (*ptr != '#' && *ptr != NUL)
1136 			break;
1137 		}
1138 		if (get_indent() >= i)
1139 		    temp = FALSE;
1140 		curwin->w_cursor = old_pos;
1141 	    }
1142 	    if (temp)
1143 		shift_line(TRUE, FALSE, 1, TRUE);
1144 	}
1145     }
1146 
1147     // set indent of '#' always to 0
1148     if (curwin->w_cursor.col > 0 && can_si && c == '#')
1149     {
1150 	// remember current indent for next line
1151 	old_indent = get_indent();
1152 	(void)set_indent(0, SIN_CHANGED);
1153     }
1154 
1155     // Adjust ai_col, the char at this position can be deleted.
1156     if (ai_col > curwin->w_cursor.col)
1157 	ai_col = curwin->w_cursor.col;
1158 }
1159 #endif
1160 
1161 /*
1162  * Insert an indent (for <Tab> or CTRL-T) or delete an indent (for CTRL-D).
1163  * Keep the cursor on the same character.
1164  * type == INDENT_INC	increase indent (for CTRL-T or <Tab>)
1165  * type == INDENT_DEC	decrease indent (for CTRL-D)
1166  * type == INDENT_SET	set indent to "amount"
1167  * if round is TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec).
1168  */
1169     void
1170 change_indent(
1171     int		type,
1172     int		amount,
1173     int		round,
1174     int		replaced,	// replaced character, put on replace stack
1175     int		call_changed_bytes)	// call changed_bytes()
1176 {
1177     int		vcol;
1178     int		last_vcol;
1179     int		insstart_less;		// reduction for Insstart.col
1180     int		new_cursor_col;
1181     int		i;
1182     char_u	*ptr;
1183     int		save_p_list;
1184     int		start_col;
1185     colnr_T	vc;
1186     colnr_T	orig_col = 0;		// init for GCC
1187     char_u	*new_line, *orig_line = NULL;	// init for GCC
1188 
1189     // VREPLACE mode needs to know what the line was like before changing
1190     if (State & VREPLACE_FLAG)
1191     {
1192 	orig_line = vim_strsave(ml_get_curline());  // Deal with NULL below
1193 	orig_col = curwin->w_cursor.col;
1194     }
1195 
1196     // for the following tricks we don't want list mode
1197     save_p_list = curwin->w_p_list;
1198     curwin->w_p_list = FALSE;
1199     vc = getvcol_nolist(&curwin->w_cursor);
1200     vcol = vc;
1201 
1202     // For Replace mode we need to fix the replace stack later, which is only
1203     // possible when the cursor is in the indent.  Remember the number of
1204     // characters before the cursor if it's possible.
1205     start_col = curwin->w_cursor.col;
1206 
1207     // determine offset from first non-blank
1208     new_cursor_col = curwin->w_cursor.col;
1209     beginline(BL_WHITE);
1210     new_cursor_col -= curwin->w_cursor.col;
1211 
1212     insstart_less = curwin->w_cursor.col;
1213 
1214     // If the cursor is in the indent, compute how many screen columns the
1215     // cursor is to the left of the first non-blank.
1216     if (new_cursor_col < 0)
1217 	vcol = get_indent() - vcol;
1218 
1219     if (new_cursor_col > 0)	    // can't fix replace stack
1220 	start_col = -1;
1221 
1222     // Set the new indent.  The cursor will be put on the first non-blank.
1223     if (type == INDENT_SET)
1224 	(void)set_indent(amount, call_changed_bytes ? SIN_CHANGED : 0);
1225     else
1226     {
1227 	int	save_State = State;
1228 
1229 	// Avoid being called recursively.
1230 	if (State & VREPLACE_FLAG)
1231 	    State = INSERT;
1232 	shift_line(type == INDENT_DEC, round, 1, call_changed_bytes);
1233 	State = save_State;
1234     }
1235     insstart_less -= curwin->w_cursor.col;
1236 
1237     // Try to put cursor on same character.
1238     // If the cursor is at or after the first non-blank in the line,
1239     // compute the cursor column relative to the column of the first
1240     // non-blank character.
1241     // If we are not in insert mode, leave the cursor on the first non-blank.
1242     // If the cursor is before the first non-blank, position it relative
1243     // to the first non-blank, counted in screen columns.
1244     if (new_cursor_col >= 0)
1245     {
1246 	// When changing the indent while the cursor is touching it, reset
1247 	// Insstart_col to 0.
1248 	if (new_cursor_col == 0)
1249 	    insstart_less = MAXCOL;
1250 	new_cursor_col += curwin->w_cursor.col;
1251     }
1252     else if (!(State & INSERT))
1253 	new_cursor_col = curwin->w_cursor.col;
1254     else
1255     {
1256 	// Compute the screen column where the cursor should be.
1257 	vcol = get_indent() - vcol;
1258 	curwin->w_virtcol = (colnr_T)((vcol < 0) ? 0 : vcol);
1259 
1260 	// Advance the cursor until we reach the right screen column.
1261 	vcol = last_vcol = 0;
1262 	new_cursor_col = -1;
1263 	ptr = ml_get_curline();
1264 	while (vcol <= (int)curwin->w_virtcol)
1265 	{
1266 	    last_vcol = vcol;
1267 	    if (has_mbyte && new_cursor_col >= 0)
1268 		new_cursor_col += (*mb_ptr2len)(ptr + new_cursor_col);
1269 	    else
1270 		++new_cursor_col;
1271 	    vcol += lbr_chartabsize(ptr, ptr + new_cursor_col, (colnr_T)vcol);
1272 	}
1273 	vcol = last_vcol;
1274 
1275 	// May need to insert spaces to be able to position the cursor on
1276 	// the right screen column.
1277 	if (vcol != (int)curwin->w_virtcol)
1278 	{
1279 	    curwin->w_cursor.col = (colnr_T)new_cursor_col;
1280 	    i = (int)curwin->w_virtcol - vcol;
1281 	    ptr = alloc(i + 1);
1282 	    if (ptr != NULL)
1283 	    {
1284 		new_cursor_col += i;
1285 		ptr[i] = NUL;
1286 		while (--i >= 0)
1287 		    ptr[i] = ' ';
1288 		ins_str(ptr);
1289 		vim_free(ptr);
1290 	    }
1291 	}
1292 
1293 	// When changing the indent while the cursor is in it, reset
1294 	// Insstart_col to 0.
1295 	insstart_less = MAXCOL;
1296     }
1297 
1298     curwin->w_p_list = save_p_list;
1299 
1300     if (new_cursor_col <= 0)
1301 	curwin->w_cursor.col = 0;
1302     else
1303 	curwin->w_cursor.col = (colnr_T)new_cursor_col;
1304     curwin->w_set_curswant = TRUE;
1305     changed_cline_bef_curs();
1306 
1307     // May have to adjust the start of the insert.
1308     if (State & INSERT)
1309     {
1310 	if (curwin->w_cursor.lnum == Insstart.lnum && Insstart.col != 0)
1311 	{
1312 	    if ((int)Insstart.col <= insstart_less)
1313 		Insstart.col = 0;
1314 	    else
1315 		Insstart.col -= insstart_less;
1316 	}
1317 	if ((int)ai_col <= insstart_less)
1318 	    ai_col = 0;
1319 	else
1320 	    ai_col -= insstart_less;
1321     }
1322 
1323     // For REPLACE mode, may have to fix the replace stack, if it's possible.
1324     // If the number of characters before the cursor decreased, need to pop a
1325     // few characters from the replace stack.
1326     // If the number of characters before the cursor increased, need to push a
1327     // few NULs onto the replace stack.
1328     if (REPLACE_NORMAL(State) && start_col >= 0)
1329     {
1330 	while (start_col > (int)curwin->w_cursor.col)
1331 	{
1332 	    replace_join(0);	    // remove a NUL from the replace stack
1333 	    --start_col;
1334 	}
1335 	while (start_col < (int)curwin->w_cursor.col || replaced)
1336 	{
1337 	    replace_push(NUL);
1338 	    if (replaced)
1339 	    {
1340 		replace_push(replaced);
1341 		replaced = NUL;
1342 	    }
1343 	    ++start_col;
1344 	}
1345     }
1346 
1347     // For VREPLACE mode, we also have to fix the replace stack.  In this case
1348     // it is always possible because we backspace over the whole line and then
1349     // put it back again the way we wanted it.
1350     if (State & VREPLACE_FLAG)
1351     {
1352 	// If orig_line didn't allocate, just return.  At least we did the job,
1353 	// even if you can't backspace.
1354 	if (orig_line == NULL)
1355 	    return;
1356 
1357 	// Save new line
1358 	new_line = vim_strsave(ml_get_curline());
1359 	if (new_line == NULL)
1360 	    return;
1361 
1362 	// We only put back the new line up to the cursor
1363 	new_line[curwin->w_cursor.col] = NUL;
1364 
1365 	// Put back original line
1366 	ml_replace(curwin->w_cursor.lnum, orig_line, FALSE);
1367 	curwin->w_cursor.col = orig_col;
1368 
1369 	// Backspace from cursor to start of line
1370 	backspace_until_column(0);
1371 
1372 	// Insert new stuff into line again
1373 	ins_bytes(new_line);
1374 
1375 	vim_free(new_line);
1376     }
1377 }
1378 
1379 /*
1380  * Copy the indent from ptr to the current line (and fill to size)
1381  * Leaves the cursor on the first non-blank in the line.
1382  * Returns TRUE if the line was changed.
1383  */
1384     int
1385 copy_indent(int size, char_u *src)
1386 {
1387     char_u	*p = NULL;
1388     char_u	*line = NULL;
1389     char_u	*s;
1390     int		todo;
1391     int		ind_len;
1392     int		line_len = 0;
1393     int		tab_pad;
1394     int		ind_done;
1395     int		round;
1396 #ifdef FEAT_VARTABS
1397     int		ind_col;
1398 #endif
1399 
1400     // Round 1: compute the number of characters needed for the indent
1401     // Round 2: copy the characters.
1402     for (round = 1; round <= 2; ++round)
1403     {
1404 	todo = size;
1405 	ind_len = 0;
1406 	ind_done = 0;
1407 #ifdef FEAT_VARTABS
1408 	ind_col = 0;
1409 #endif
1410 	s = src;
1411 
1412 	// Count/copy the usable portion of the source line
1413 	while (todo > 0 && VIM_ISWHITE(*s))
1414 	{
1415 	    if (*s == TAB)
1416 	    {
1417 #ifdef FEAT_VARTABS
1418 		tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
1419 							curbuf->b_p_vts_array);
1420 #else
1421 		tab_pad = (int)curbuf->b_p_ts
1422 					   - (ind_done % (int)curbuf->b_p_ts);
1423 #endif
1424 		// Stop if this tab will overshoot the target
1425 		if (todo < tab_pad)
1426 		    break;
1427 		todo -= tab_pad;
1428 		ind_done += tab_pad;
1429 #ifdef FEAT_VARTABS
1430 		ind_col += tab_pad;
1431 #endif
1432 	    }
1433 	    else
1434 	    {
1435 		--todo;
1436 		++ind_done;
1437 #ifdef FEAT_VARTABS
1438 		++ind_col;
1439 #endif
1440 	    }
1441 	    ++ind_len;
1442 	    if (p != NULL)
1443 		*p++ = *s;
1444 	    ++s;
1445 	}
1446 
1447 	// Fill to next tabstop with a tab, if possible
1448 #ifdef FEAT_VARTABS
1449 	tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts,
1450 							curbuf->b_p_vts_array);
1451 #else
1452 	tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts);
1453 #endif
1454 	if (todo >= tab_pad && !curbuf->b_p_et)
1455 	{
1456 	    todo -= tab_pad;
1457 	    ++ind_len;
1458 #ifdef FEAT_VARTABS
1459 	    ind_col += tab_pad;
1460 #endif
1461 	    if (p != NULL)
1462 		*p++ = TAB;
1463 	}
1464 
1465 	// Add tabs required for indent
1466 	if (!curbuf->b_p_et)
1467 	{
1468 #ifdef FEAT_VARTABS
1469 	    for (;;)
1470 	    {
1471 		tab_pad = tabstop_padding(ind_col, curbuf->b_p_ts,
1472 							curbuf->b_p_vts_array);
1473 		if (todo < tab_pad)
1474 		    break;
1475 		todo -= tab_pad;
1476 		++ind_len;
1477 		ind_col += tab_pad;
1478 		if (p != NULL)
1479 		    *p++ = TAB;
1480 	    }
1481 #else
1482 	    while (todo >= (int)curbuf->b_p_ts)
1483 	    {
1484 		todo -= (int)curbuf->b_p_ts;
1485 		++ind_len;
1486 		if (p != NULL)
1487 		    *p++ = TAB;
1488 	    }
1489 #endif
1490 	}
1491 
1492 	// Count/add spaces required for indent
1493 	while (todo > 0)
1494 	{
1495 	    --todo;
1496 	    ++ind_len;
1497 	    if (p != NULL)
1498 		*p++ = ' ';
1499 	}
1500 
1501 	if (p == NULL)
1502 	{
1503 	    // Allocate memory for the result: the copied indent, new indent
1504 	    // and the rest of the line.
1505 	    line_len = (int)STRLEN(ml_get_curline()) + 1;
1506 	    line = alloc(ind_len + line_len);
1507 	    if (line == NULL)
1508 		return FALSE;
1509 	    p = line;
1510 	}
1511     }
1512 
1513     // Append the original line
1514     mch_memmove(p, ml_get_curline(), (size_t)line_len);
1515 
1516     // Replace the line
1517     ml_replace(curwin->w_cursor.lnum, line, FALSE);
1518 
1519     // Put the cursor after the indent.
1520     curwin->w_cursor.col = ind_len;
1521     return TRUE;
1522 }
1523 
1524 /*
1525  * ":retab".
1526  */
1527     void
1528 ex_retab(exarg_T *eap)
1529 {
1530     linenr_T	lnum;
1531     int		got_tab = FALSE;
1532     long	num_spaces = 0;
1533     long	num_tabs;
1534     long	len;
1535     long	col;
1536     long	vcol;
1537     long	start_col = 0;		// For start of white-space string
1538     long	start_vcol = 0;		// For start of white-space string
1539     long	old_len;
1540     char_u	*ptr;
1541     char_u	*new_line = (char_u *)1; // init to non-NULL
1542     int		did_undo;		// called u_save for current line
1543 #ifdef FEAT_VARTABS
1544     int		*new_vts_array = NULL;
1545     char_u	*new_ts_str;		// string value of tab argument
1546 #else
1547     int		temp;
1548     int		new_ts;
1549 #endif
1550     int		save_list;
1551     linenr_T	first_line = 0;		// first changed line
1552     linenr_T	last_line = 0;		// last changed line
1553 
1554     save_list = curwin->w_p_list;
1555     curwin->w_p_list = 0;	    // don't want list mode here
1556 
1557 #ifdef FEAT_VARTABS
1558     new_ts_str = eap->arg;
1559     if (!tabstop_set(eap->arg, &new_vts_array))
1560 	return;
1561     while (vim_isdigit(*(eap->arg)) || *(eap->arg) == ',')
1562 	++(eap->arg);
1563 
1564     // This ensures that either new_vts_array and new_ts_str are freshly
1565     // allocated, or new_vts_array points to an existing array and new_ts_str
1566     // is null.
1567     if (new_vts_array == NULL)
1568     {
1569 	new_vts_array = curbuf->b_p_vts_array;
1570 	new_ts_str = NULL;
1571     }
1572     else
1573 	new_ts_str = vim_strnsave(new_ts_str, eap->arg - new_ts_str);
1574 #else
1575     new_ts = getdigits(&(eap->arg));
1576     if (new_ts < 0)
1577     {
1578 	emsg(_(e_positive));
1579 	return;
1580     }
1581     if (new_ts == 0)
1582 	new_ts = curbuf->b_p_ts;
1583 #endif
1584     for (lnum = eap->line1; !got_int && lnum <= eap->line2; ++lnum)
1585     {
1586 	ptr = ml_get(lnum);
1587 	col = 0;
1588 	vcol = 0;
1589 	did_undo = FALSE;
1590 	for (;;)
1591 	{
1592 	    if (VIM_ISWHITE(ptr[col]))
1593 	    {
1594 		if (!got_tab && num_spaces == 0)
1595 		{
1596 		    // First consecutive white-space
1597 		    start_vcol = vcol;
1598 		    start_col = col;
1599 		}
1600 		if (ptr[col] == ' ')
1601 		    num_spaces++;
1602 		else
1603 		    got_tab = TRUE;
1604 	    }
1605 	    else
1606 	    {
1607 		if (got_tab || (eap->forceit && num_spaces > 1))
1608 		{
1609 		    // Retabulate this string of white-space
1610 
1611 		    // len is virtual length of white string
1612 		    len = num_spaces = vcol - start_vcol;
1613 		    num_tabs = 0;
1614 		    if (!curbuf->b_p_et)
1615 		    {
1616 #ifdef FEAT_VARTABS
1617 			int t, s;
1618 
1619 			tabstop_fromto(start_vcol, vcol,
1620 					curbuf->b_p_ts, new_vts_array, &t, &s);
1621 			num_tabs = t;
1622 			num_spaces = s;
1623 #else
1624 			temp = new_ts - (start_vcol % new_ts);
1625 			if (num_spaces >= temp)
1626 			{
1627 			    num_spaces -= temp;
1628 			    num_tabs++;
1629 			}
1630 			num_tabs += num_spaces / new_ts;
1631 			num_spaces -= (num_spaces / new_ts) * new_ts;
1632 #endif
1633 		    }
1634 		    if (curbuf->b_p_et || got_tab ||
1635 					(num_spaces + num_tabs < len))
1636 		    {
1637 			if (did_undo == FALSE)
1638 			{
1639 			    did_undo = TRUE;
1640 			    if (u_save((linenr_T)(lnum - 1),
1641 						(linenr_T)(lnum + 1)) == FAIL)
1642 			    {
1643 				new_line = NULL;	// flag out-of-memory
1644 				break;
1645 			    }
1646 			}
1647 
1648 			// len is actual number of white characters used
1649 			len = num_spaces + num_tabs;
1650 			old_len = (long)STRLEN(ptr);
1651 			new_line = alloc(old_len - col + start_col + len + 1);
1652 			if (new_line == NULL)
1653 			    break;
1654 			if (start_col > 0)
1655 			    mch_memmove(new_line, ptr, (size_t)start_col);
1656 			mch_memmove(new_line + start_col + len,
1657 				      ptr + col, (size_t)(old_len - col + 1));
1658 			ptr = new_line + start_col;
1659 			for (col = 0; col < len; col++)
1660 			    ptr[col] = (col < num_tabs) ? '\t' : ' ';
1661 			ml_replace(lnum, new_line, FALSE);
1662 			if (first_line == 0)
1663 			    first_line = lnum;
1664 			last_line = lnum;
1665 			ptr = new_line;
1666 			col = start_col + len;
1667 		    }
1668 		}
1669 		got_tab = FALSE;
1670 		num_spaces = 0;
1671 	    }
1672 	    if (ptr[col] == NUL)
1673 		break;
1674 	    vcol += chartabsize(ptr + col, (colnr_T)vcol);
1675 	    if (has_mbyte)
1676 		col += (*mb_ptr2len)(ptr + col);
1677 	    else
1678 		++col;
1679 	}
1680 	if (new_line == NULL)		    // out of memory
1681 	    break;
1682 	line_breakcheck();
1683     }
1684     if (got_int)
1685 	emsg(_(e_interr));
1686 
1687 #ifdef FEAT_VARTABS
1688     // If a single value was given then it can be considered equal to
1689     // either the value of 'tabstop' or the value of 'vartabstop'.
1690     if (tabstop_count(curbuf->b_p_vts_array) == 0
1691 	&& tabstop_count(new_vts_array) == 1
1692 	&& curbuf->b_p_ts == tabstop_first(new_vts_array))
1693 	; // not changed
1694     else if (tabstop_count(curbuf->b_p_vts_array) > 0
1695         && tabstop_eq(curbuf->b_p_vts_array, new_vts_array))
1696 	; // not changed
1697     else
1698 	redraw_curbuf_later(NOT_VALID);
1699 #else
1700     if (curbuf->b_p_ts != new_ts)
1701 	redraw_curbuf_later(NOT_VALID);
1702 #endif
1703     if (first_line != 0)
1704 	changed_lines(first_line, 0, last_line + 1, 0L);
1705 
1706     curwin->w_p_list = save_list;	// restore 'list'
1707 
1708 #ifdef FEAT_VARTABS
1709     if (new_ts_str != NULL)		// set the new tabstop
1710     {
1711 	// If 'vartabstop' is in use or if the value given to retab has more
1712 	// than one tabstop then update 'vartabstop'.
1713 	int *old_vts_ary = curbuf->b_p_vts_array;
1714 
1715 	if (tabstop_count(old_vts_ary) > 0 || tabstop_count(new_vts_array) > 1)
1716 	{
1717 	    set_string_option_direct((char_u *)"vts", -1, new_ts_str,
1718 							OPT_FREE|OPT_LOCAL, 0);
1719 	    curbuf->b_p_vts_array = new_vts_array;
1720 	    vim_free(old_vts_ary);
1721 	}
1722 	else
1723 	{
1724 	    // 'vartabstop' wasn't in use and a single value was given to
1725 	    // retab then update 'tabstop'.
1726 	    curbuf->b_p_ts = tabstop_first(new_vts_array);
1727 	    vim_free(new_vts_array);
1728 	}
1729 	vim_free(new_ts_str);
1730     }
1731 #else
1732     curbuf->b_p_ts = new_ts;
1733 #endif
1734     coladvance(curwin->w_curswant);
1735 
1736     u_clearline();
1737 }
1738 
1739 #if (defined(FEAT_CINDENT) && defined(FEAT_EVAL)) || defined(PROTO)
1740 /*
1741  * Get indent level from 'indentexpr'.
1742  */
1743     int
1744 get_expr_indent(void)
1745 {
1746     int		indent = -1;
1747     char_u	*inde_copy;
1748     pos_T	save_pos;
1749     colnr_T	save_curswant;
1750     int		save_set_curswant;
1751     int		save_State;
1752     int		use_sandbox = was_set_insecurely((char_u *)"indentexpr",
1753 								   OPT_LOCAL);
1754 
1755     // Save and restore cursor position and curswant, in case it was changed
1756     // via :normal commands
1757     save_pos = curwin->w_cursor;
1758     save_curswant = curwin->w_curswant;
1759     save_set_curswant = curwin->w_set_curswant;
1760     set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum);
1761     if (use_sandbox)
1762 	++sandbox;
1763     ++textwinlock;
1764 
1765     // Need to make a copy, the 'indentexpr' option could be changed while
1766     // evaluating it.
1767     inde_copy = vim_strsave(curbuf->b_p_inde);
1768     if (inde_copy != NULL)
1769     {
1770 	indent = (int)eval_to_number(inde_copy);
1771 	vim_free(inde_copy);
1772     }
1773 
1774     if (use_sandbox)
1775 	--sandbox;
1776     --textwinlock;
1777 
1778     // Restore the cursor position so that 'indentexpr' doesn't need to.
1779     // Pretend to be in Insert mode, allow cursor past end of line for "o"
1780     // command.
1781     save_State = State;
1782     State = INSERT;
1783     curwin->w_cursor = save_pos;
1784     curwin->w_curswant = save_curswant;
1785     curwin->w_set_curswant = save_set_curswant;
1786     check_cursor();
1787     State = save_State;
1788 
1789     // If there is an error, just keep the current indent.
1790     if (indent < 0)
1791 	indent = get_indent();
1792 
1793     return indent;
1794 }
1795 #endif
1796 
1797 #if defined(FEAT_LISP) || defined(PROTO)
1798 
1799     static int
1800 lisp_match(char_u *p)
1801 {
1802     char_u	buf[LSIZE];
1803     int		len;
1804     char_u	*word = *curbuf->b_p_lw != NUL ? curbuf->b_p_lw : p_lispwords;
1805 
1806     while (*word != NUL)
1807     {
1808 	(void)copy_option_part(&word, buf, LSIZE, ",");
1809 	len = (int)STRLEN(buf);
1810 	if (STRNCMP(buf, p, len) == 0 && p[len] == ' ')
1811 	    return TRUE;
1812     }
1813     return FALSE;
1814 }
1815 
1816 /*
1817  * When 'p' is present in 'cpoptions, a Vi compatible method is used.
1818  * The incompatible newer method is quite a bit better at indenting
1819  * code in lisp-like languages than the traditional one; it's still
1820  * mostly heuristics however -- Dirk van Deun, [email protected]
1821  *
1822  * TODO:
1823  * Findmatch() should be adapted for lisp, also to make showmatch
1824  * work correctly: now (v5.3) it seems all C/C++ oriented:
1825  * - it does not recognize the #\( and #\) notations as character literals
1826  * - it doesn't know about comments starting with a semicolon
1827  * - it incorrectly interprets '(' as a character literal
1828  * All this messes up get_lisp_indent in some rare cases.
1829  * Update from Sergey Khorev:
1830  * I tried to fix the first two issues.
1831  */
1832     int
1833 get_lisp_indent(void)
1834 {
1835     pos_T	*pos, realpos, paren;
1836     int		amount;
1837     char_u	*that;
1838     colnr_T	col;
1839     colnr_T	firsttry;
1840     int		parencount, quotecount;
1841     int		vi_lisp;
1842 
1843     // Set vi_lisp to use the vi-compatible method
1844     vi_lisp = (vim_strchr(p_cpo, CPO_LISP) != NULL);
1845 
1846     realpos = curwin->w_cursor;
1847     curwin->w_cursor.col = 0;
1848 
1849     if ((pos = findmatch(NULL, '(')) == NULL)
1850 	pos = findmatch(NULL, '[');
1851     else
1852     {
1853 	paren = *pos;
1854 	pos = findmatch(NULL, '[');
1855 	if (pos == NULL || LT_POSP(pos, &paren))
1856 	    pos = &paren;
1857     }
1858     if (pos != NULL)
1859     {
1860 	// Extra trick: Take the indent of the first previous non-white
1861 	// line that is at the same () level.
1862 	amount = -1;
1863 	parencount = 0;
1864 
1865 	while (--curwin->w_cursor.lnum >= pos->lnum)
1866 	{
1867 	    if (linewhite(curwin->w_cursor.lnum))
1868 		continue;
1869 	    for (that = ml_get_curline(); *that != NUL; ++that)
1870 	    {
1871 		if (*that == ';')
1872 		{
1873 		    while (*(that + 1) != NUL)
1874 			++that;
1875 		    continue;
1876 		}
1877 		if (*that == '\\')
1878 		{
1879 		    if (*(that + 1) != NUL)
1880 			++that;
1881 		    continue;
1882 		}
1883 		if (*that == '"' && *(that + 1) != NUL)
1884 		{
1885 		    while (*++that && *that != '"')
1886 		    {
1887 			// skipping escaped characters in the string
1888 			if (*that == '\\')
1889 			{
1890 			    if (*++that == NUL)
1891 				break;
1892 			    if (that[1] == NUL)
1893 			    {
1894 				++that;
1895 				break;
1896 			    }
1897 			}
1898 		    }
1899 		}
1900 		if (*that == '(' || *that == '[')
1901 		    ++parencount;
1902 		else if (*that == ')' || *that == ']')
1903 		    --parencount;
1904 	    }
1905 	    if (parencount == 0)
1906 	    {
1907 		amount = get_indent();
1908 		break;
1909 	    }
1910 	}
1911 
1912 	if (amount == -1)
1913 	{
1914 	    curwin->w_cursor.lnum = pos->lnum;
1915 	    curwin->w_cursor.col = pos->col;
1916 	    col = pos->col;
1917 
1918 	    that = ml_get_curline();
1919 
1920 	    if (vi_lisp && get_indent() == 0)
1921 		amount = 2;
1922 	    else
1923 	    {
1924 		char_u *line = that;
1925 
1926 		amount = 0;
1927 		while (*that && col)
1928 		{
1929 		    amount += lbr_chartabsize_adv(line, &that, (colnr_T)amount);
1930 		    col--;
1931 		}
1932 
1933 		// Some keywords require "body" indenting rules (the
1934 		// non-standard-lisp ones are Scheme special forms):
1935 		//
1936 		// (let ((a 1))    instead    (let ((a 1))
1937 		//   (...))	      of	   (...))
1938 
1939 		if (!vi_lisp && (*that == '(' || *that == '[')
1940 						      && lisp_match(that + 1))
1941 		    amount += 2;
1942 		else
1943 		{
1944 		    that++;
1945 		    amount++;
1946 		    firsttry = amount;
1947 
1948 		    while (VIM_ISWHITE(*that))
1949 		    {
1950 			amount += lbr_chartabsize(line, that, (colnr_T)amount);
1951 			++that;
1952 		    }
1953 
1954 		    if (*that && *that != ';') // not a comment line
1955 		    {
1956 			// test *that != '(' to accommodate first let/do
1957 			// argument if it is more than one line
1958 			if (!vi_lisp && *that != '(' && *that != '[')
1959 			    firsttry++;
1960 
1961 			parencount = 0;
1962 			quotecount = 0;
1963 
1964 			if (vi_lisp
1965 				|| (*that != '"'
1966 				    && *that != '\''
1967 				    && *that != '#'
1968 				    && (*that < '0' || *that > '9')))
1969 			{
1970 			    while (*that
1971 				    && (!VIM_ISWHITE(*that)
1972 					|| quotecount
1973 					|| parencount)
1974 				    && (!((*that == '(' || *that == '[')
1975 					    && !quotecount
1976 					    && !parencount
1977 					    && vi_lisp)))
1978 			    {
1979 				if (*that == '"')
1980 				    quotecount = !quotecount;
1981 				if ((*that == '(' || *that == '[')
1982 							       && !quotecount)
1983 				    ++parencount;
1984 				if ((*that == ')' || *that == ']')
1985 							       && !quotecount)
1986 				    --parencount;
1987 				if (*that == '\\' && *(that+1) != NUL)
1988 				    amount += lbr_chartabsize_adv(
1989 						line, &that, (colnr_T)amount);
1990 				amount += lbr_chartabsize_adv(
1991 						line, &that, (colnr_T)amount);
1992 			    }
1993 			}
1994 			while (VIM_ISWHITE(*that))
1995 			{
1996 			    amount += lbr_chartabsize(
1997 						 line, that, (colnr_T)amount);
1998 			    that++;
1999 			}
2000 			if (!*that || *that == ';')
2001 			    amount = firsttry;
2002 		    }
2003 		}
2004 	    }
2005 	}
2006     }
2007     else
2008 	amount = 0;	// no matching '(' or '[' found, use zero indent
2009 
2010     curwin->w_cursor = realpos;
2011 
2012     return amount;
2013 }
2014 #endif // FEAT_LISP
2015 
2016 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(PROTO)
2017 /*
2018  * Re-indent the current line, based on the current contents of it and the
2019  * surrounding lines. Fixing the cursor position seems really easy -- I'm very
2020  * confused what all the part that handles Control-T is doing that I'm not.
2021  * "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent.
2022  */
2023 
2024     void
2025 fixthisline(int (*get_the_indent)(void))
2026 {
2027     int amount = get_the_indent();
2028 
2029     if (amount >= 0)
2030     {
2031 	change_indent(INDENT_SET, amount, FALSE, 0, TRUE);
2032 	if (linewhite(curwin->w_cursor.lnum))
2033 	    did_ai = TRUE;	// delete the indent if the line stays empty
2034     }
2035 }
2036 
2037     void
2038 fix_indent(void)
2039 {
2040     if (p_paste)
2041 	return;
2042 # ifdef FEAT_LISP
2043     if (curbuf->b_p_lisp && curbuf->b_p_ai)
2044 	fixthisline(get_lisp_indent);
2045 # endif
2046 # if defined(FEAT_LISP) && defined(FEAT_CINDENT)
2047     else
2048 # endif
2049 # ifdef FEAT_CINDENT
2050 	if (cindent_on())
2051 	    do_c_expr_indent();
2052 # endif
2053 }
2054 #endif
2055 
2056 #if defined(FEAT_EVAL) || defined(PROTO)
2057 /*
2058  * "indent()" function
2059  */
2060     void
2061 f_indent(typval_T *argvars, typval_T *rettv)
2062 {
2063     linenr_T	lnum;
2064 
2065     lnum = tv_get_lnum(argvars);
2066     if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
2067 	rettv->vval.v_number = get_indent_lnum(lnum);
2068     else
2069 	rettv->vval.v_number = -1;
2070 }
2071 
2072 /*
2073  * "lispindent(lnum)" function
2074  */
2075     void
2076 f_lispindent(typval_T *argvars UNUSED, typval_T *rettv)
2077 {
2078 #ifdef FEAT_LISP
2079     pos_T	pos;
2080     linenr_T	lnum;
2081 
2082     pos = curwin->w_cursor;
2083     lnum = tv_get_lnum(argvars);
2084     if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count)
2085     {
2086 	curwin->w_cursor.lnum = lnum;
2087 	rettv->vval.v_number = get_lisp_indent();
2088 	curwin->w_cursor = pos;
2089     }
2090     else
2091 #endif
2092 	rettv->vval.v_number = -1;
2093 }
2094 #endif
2095