xref: /vim-8.2.3635/src/textformat.c (revision 818ff25c)
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  * textformat.c: text formatting functions
12  */
13 
14 #include "vim.h"
15 
16 static int	did_add_space = FALSE;	// auto_format() added an extra space
17 					// under the cursor
18 
19 #define WHITECHAR(cc) (VIM_ISWHITE(cc) && (!enc_utf8 || !utf_iscomposing(utf_ptr2char(ml_get_cursor() + 1))))
20 
21 /*
22  * Return TRUE if format option 'x' is in effect.
23  * Take care of no formatting when 'paste' is set.
24  */
25     int
has_format_option(int x)26 has_format_option(int x)
27 {
28     if (p_paste)
29 	return FALSE;
30     return (vim_strchr(curbuf->b_p_fo, x) != NULL);
31 }
32 
33 /*
34  * Format text at the current insert position.
35  *
36  * If the INSCHAR_COM_LIST flag is present, then the value of second_indent
37  * will be the comment leader length sent to open_line().
38  */
39     void
internal_format(int textwidth,int second_indent,int flags,int format_only,int c)40 internal_format(
41     int		textwidth,
42     int		second_indent,
43     int		flags,
44     int		format_only,
45     int		c) // character to be inserted (can be NUL)
46 {
47     int		cc;
48     int		skip_pos;
49     int		save_char = NUL;
50     int		haveto_redraw = FALSE;
51     int		fo_ins_blank = has_format_option(FO_INS_BLANK);
52     int		fo_multibyte = has_format_option(FO_MBYTE_BREAK);
53     int		fo_rigor_tw  = has_format_option(FO_RIGOROUS_TW);
54     int		fo_white_par = has_format_option(FO_WHITE_PAR);
55     int		first_line = TRUE;
56     colnr_T	leader_len;
57     int		no_leader = FALSE;
58     int		do_comments = (flags & INSCHAR_DO_COM);
59 #ifdef FEAT_LINEBREAK
60     int		has_lbr = curwin->w_p_lbr;
61 
62     // make sure win_lbr_chartabsize() counts correctly
63     curwin->w_p_lbr = FALSE;
64 #endif
65 
66     // When 'ai' is off we don't want a space under the cursor to be
67     // deleted.  Replace it with an 'x' temporarily.
68     if (!curbuf->b_p_ai && !(State & VREPLACE_FLAG))
69     {
70 	cc = gchar_cursor();
71 	if (VIM_ISWHITE(cc))
72 	{
73 	    save_char = cc;
74 	    pchar_cursor('x');
75 	}
76     }
77 
78     // Repeat breaking lines, until the current line is not too long.
79     while (!got_int)
80     {
81 	int	startcol;		// Cursor column at entry
82 	int	wantcol;		// column at textwidth border
83 	int	foundcol;		// column for start of spaces
84 	int	end_foundcol = 0;	// column for start of word
85 	colnr_T	len;
86 	colnr_T	virtcol;
87 	int	orig_col = 0;
88 	char_u	*saved_text = NULL;
89 	colnr_T	col;
90 	colnr_T	end_col;
91 	int	wcc;			// counter for whitespace chars
92 
93 	virtcol = get_nolist_virtcol()
94 		+ char2cells(c != NUL ? c : gchar_cursor());
95 	if (virtcol <= (colnr_T)textwidth)
96 	    break;
97 
98 	if (no_leader)
99 	    do_comments = FALSE;
100 	else if (!(flags & INSCHAR_FORMAT)
101 				       && has_format_option(FO_WRAP_COMS))
102 	    do_comments = TRUE;
103 
104 	// Don't break until after the comment leader
105 	if (do_comments)
106 	    leader_len = get_leader_len(ml_get_curline(), NULL, FALSE, TRUE);
107 	else
108 	    leader_len = 0;
109 
110 	// If the line doesn't start with a comment leader, then don't
111 	// start one in a following broken line.  Avoids that a %word
112 	// moved to the start of the next line causes all following lines
113 	// to start with %.
114 	if (leader_len == 0)
115 	    no_leader = TRUE;
116 	if (!(flags & INSCHAR_FORMAT)
117 		&& leader_len == 0
118 		&& !has_format_option(FO_WRAP))
119 
120 	    break;
121 	if ((startcol = curwin->w_cursor.col) == 0)
122 	    break;
123 
124 	// find column of textwidth border
125 	coladvance((colnr_T)textwidth);
126 	wantcol = curwin->w_cursor.col;
127 
128 	curwin->w_cursor.col = startcol;
129 	foundcol = 0;
130 	skip_pos = 0;
131 
132 	// Find position to break at.
133 	// Stop at first entered white when 'formatoptions' has 'v'
134 	while ((!fo_ins_blank && !has_format_option(FO_INS_VI))
135 		    || (flags & INSCHAR_FORMAT)
136 		    || curwin->w_cursor.lnum != Insstart.lnum
137 		    || curwin->w_cursor.col >= Insstart.col)
138 	{
139 	    if (curwin->w_cursor.col == startcol && c != NUL)
140 		cc = c;
141 	    else
142 		cc = gchar_cursor();
143 	    if (WHITECHAR(cc))
144 	    {
145 		// remember position of blank just before text
146 		end_col = curwin->w_cursor.col;
147 
148 		// find start of sequence of blanks
149 		wcc = 0;
150 		while (curwin->w_cursor.col > 0 && WHITECHAR(cc))
151 		{
152 		    dec_cursor();
153 		    cc = gchar_cursor();
154 
155 		    // Increment count of how many whitespace chars in this
156 		    // group; we only need to know if it's more than one.
157 		    if (wcc < 2)
158 		        wcc++;
159 		}
160 		if (curwin->w_cursor.col == 0 && WHITECHAR(cc))
161 		    break;		// only spaces in front of text
162 
163 		// Don't break after a period when 'formatoptions' has 'p' and
164 		// there are less than two spaces.
165 		if (has_format_option(FO_PERIOD_ABBR) && cc == '.' && wcc < 2)
166 		    continue;
167 
168 		// Don't break until after the comment leader
169 		if (curwin->w_cursor.col < leader_len)
170 		    break;
171 		if (has_format_option(FO_ONE_LETTER))
172 		{
173 		    // do not break after one-letter words
174 		    if (curwin->w_cursor.col == 0)
175 			break;	// one-letter word at begin
176 		    // do not break "#a b" when 'tw' is 2
177 		    if (curwin->w_cursor.col <= leader_len)
178 			break;
179 		    col = curwin->w_cursor.col;
180 		    dec_cursor();
181 		    cc = gchar_cursor();
182 
183 		    if (WHITECHAR(cc))
184 			continue;	// one-letter, continue
185 		    curwin->w_cursor.col = col;
186 		}
187 
188 		inc_cursor();
189 
190 		end_foundcol = end_col + 1;
191 		foundcol = curwin->w_cursor.col;
192 		if (curwin->w_cursor.col <= (colnr_T)wantcol)
193 		    break;
194 	    }
195 	    else if ((cc >= 0x100 || !utf_allow_break_before(cc)) && fo_multibyte)
196 	    {
197 		int ncc;
198 		int allow_break;
199 
200 		// Break after or before a multi-byte character.
201 		if (curwin->w_cursor.col != startcol)
202 		{
203 		    // Don't break until after the comment leader
204 		    if (curwin->w_cursor.col < leader_len)
205 			break;
206 		    col = curwin->w_cursor.col;
207 		    inc_cursor();
208 		    ncc = gchar_cursor();
209 
210 		    allow_break =
211 			(enc_utf8 && utf_allow_break(cc, ncc))
212 			|| enc_dbcs;
213 
214 		    // If we have already checked this position, skip!
215 		    if (curwin->w_cursor.col != skip_pos && allow_break)
216 		    {
217 			foundcol = curwin->w_cursor.col;
218 			end_foundcol = foundcol;
219 			if (curwin->w_cursor.col <= (colnr_T)wantcol)
220 			    break;
221 		    }
222 		    curwin->w_cursor.col = col;
223 		}
224 
225 		if (curwin->w_cursor.col == 0)
226 		    break;
227 
228 		ncc = cc;
229 		col = curwin->w_cursor.col;
230 
231 		dec_cursor();
232 		cc = gchar_cursor();
233 
234 		if (WHITECHAR(cc))
235 		    continue;		// break with space
236 		// Don't break until after the comment leader.
237 		if (curwin->w_cursor.col < leader_len)
238 		    break;
239 
240 		curwin->w_cursor.col = col;
241 		skip_pos = curwin->w_cursor.col;
242 
243 		allow_break =
244 		    (enc_utf8 && utf_allow_break(cc, ncc))
245 		    || enc_dbcs;
246 
247 		// Must handle this to respect line break prohibition.
248 		if (allow_break)
249 		{
250 		    foundcol = curwin->w_cursor.col;
251 		    end_foundcol = foundcol;
252 		}
253 		if (curwin->w_cursor.col <= (colnr_T)wantcol)
254 		{
255 		    int ncc_allow_break =
256 			 (enc_utf8 && utf_allow_break_before(ncc)) || enc_dbcs;
257 
258 		    if (allow_break)
259 			break;
260 		    if (!ncc_allow_break && !fo_rigor_tw)
261 		    {
262 			// Enable at most 1 punct hang outside of textwidth.
263 			if (curwin->w_cursor.col == startcol)
264 			{
265 			    // We are inserting a non-breakable char, postpone
266 			    // line break check to next insert.
267 			    end_foundcol = foundcol = 0;
268 			    break;
269 			}
270 
271 			// Neither cc nor ncc is NUL if we are here, so
272 			// it's safe to inc_cursor.
273 			col = curwin->w_cursor.col;
274 
275 			inc_cursor();
276 			cc  = ncc;
277 			ncc = gchar_cursor();
278 			// handle insert
279 			ncc = (ncc != NUL) ? ncc : c;
280 
281 			allow_break =
282 				(enc_utf8 && utf_allow_break(cc, ncc))
283 				|| enc_dbcs;
284 
285 			if (allow_break)
286 			{
287 			    // Break only when we are not at end of line.
288 			    end_foundcol = foundcol =
289 				      ncc == NUL? 0 : curwin->w_cursor.col;
290 			    break;
291 			}
292 			curwin->w_cursor.col = col;
293 		    }
294 		}
295 	    }
296 	    if (curwin->w_cursor.col == 0)
297 		break;
298 	    dec_cursor();
299 	}
300 
301 	if (foundcol == 0)		// no spaces, cannot break line
302 	{
303 	    curwin->w_cursor.col = startcol;
304 	    break;
305 	}
306 
307 	// Going to break the line, remove any "$" now.
308 	undisplay_dollar();
309 
310 	// Offset between cursor position and line break is used by replace
311 	// stack functions.  VREPLACE does not use this, and backspaces
312 	// over the text instead.
313 	if (State & VREPLACE_FLAG)
314 	    orig_col = startcol;	// Will start backspacing from here
315 	else
316 	    replace_offset = startcol - end_foundcol;
317 
318 	// adjust startcol for spaces that will be deleted and
319 	// characters that will remain on top line
320 	curwin->w_cursor.col = foundcol;
321 	while ((cc = gchar_cursor(), WHITECHAR(cc))
322 		    && (!fo_white_par || curwin->w_cursor.col < startcol))
323 	    inc_cursor();
324 	startcol -= curwin->w_cursor.col;
325 	if (startcol < 0)
326 	    startcol = 0;
327 
328 	if (State & VREPLACE_FLAG)
329 	{
330 	    // In VREPLACE mode, we will backspace over the text to be
331 	    // wrapped, so save a copy now to put on the next line.
332 	    saved_text = vim_strsave(ml_get_cursor());
333 	    curwin->w_cursor.col = orig_col;
334 	    if (saved_text == NULL)
335 		break;	// Can't do it, out of memory
336 	    saved_text[startcol] = NUL;
337 
338 	    // Backspace over characters that will move to the next line
339 	    if (!fo_white_par)
340 		backspace_until_column(foundcol);
341 	}
342 	else
343 	{
344 	    // put cursor after pos. to break line
345 	    if (!fo_white_par)
346 		curwin->w_cursor.col = foundcol;
347 	}
348 
349 	// Split the line just before the margin.
350 	// Only insert/delete lines, but don't really redraw the window.
351 	open_line(FORWARD, OPENLINE_DELSPACES + OPENLINE_MARKFIX
352 		+ (fo_white_par ? OPENLINE_KEEPTRAIL : 0)
353 		+ (do_comments ? OPENLINE_DO_COM : 0)
354 		+ ((flags & INSCHAR_COM_LIST) ? OPENLINE_COM_LIST : 0)
355 		, ((flags & INSCHAR_COM_LIST) ? second_indent : old_indent));
356 	if (!(flags & INSCHAR_COM_LIST))
357 	    old_indent = 0;
358 
359 	replace_offset = 0;
360 	if (first_line)
361 	{
362 	    if (!(flags & INSCHAR_COM_LIST))
363 	    {
364 		// This section is for auto-wrap of numeric lists.  When not
365 		// in insert mode (i.e. format_lines()), the INSCHAR_COM_LIST
366 		// flag will be set and open_line() will handle it (as seen
367 		// above).  The code here (and in get_number_indent()) will
368 		// recognize comments if needed...
369 		if (second_indent < 0 && has_format_option(FO_Q_NUMBER))
370 		    second_indent =
371 				 get_number_indent(curwin->w_cursor.lnum - 1);
372 		if (second_indent >= 0)
373 		{
374 		    if (State & VREPLACE_FLAG)
375 			change_indent(INDENT_SET, second_indent,
376 							    FALSE, NUL, TRUE);
377 		    else
378 			if (leader_len > 0 && second_indent - leader_len > 0)
379 		    {
380 			int i;
381 			int padding = second_indent - leader_len;
382 
383 			// We started at the first_line of a numbered list
384 			// that has a comment.  the open_line() function has
385 			// inserted the proper comment leader and positioned
386 			// the cursor at the end of the split line.  Now we
387 			// add the additional whitespace needed after the
388 			// comment leader for the numbered list.
389 			for (i = 0; i < padding; i++)
390 			    ins_str((char_u *)" ");
391 		    }
392 		    else
393 		    {
394 			(void)set_indent(second_indent, SIN_CHANGED);
395 		    }
396 		}
397 	    }
398 	    first_line = FALSE;
399 	}
400 
401 	if (State & VREPLACE_FLAG)
402 	{
403 	    // In VREPLACE mode we have backspaced over the text to be
404 	    // moved, now we re-insert it into the new line.
405 	    ins_bytes(saved_text);
406 	    vim_free(saved_text);
407 	}
408 	else
409 	{
410 	    // Check if cursor is not past the NUL off the line, cindent
411 	    // may have added or removed indent.
412 	    curwin->w_cursor.col += startcol;
413 	    len = (colnr_T)STRLEN(ml_get_curline());
414 	    if (curwin->w_cursor.col > len)
415 		curwin->w_cursor.col = len;
416 	}
417 
418 	haveto_redraw = TRUE;
419 #ifdef FEAT_CINDENT
420 	set_can_cindent(TRUE);
421 #endif
422 	// moved the cursor, don't autoindent or cindent now
423 	did_ai = FALSE;
424 #ifdef FEAT_SMARTINDENT
425 	did_si = FALSE;
426 	can_si = FALSE;
427 	can_si_back = FALSE;
428 #endif
429 	line_breakcheck();
430     }
431 
432     if (save_char != NUL)		// put back space after cursor
433 	pchar_cursor(save_char);
434 
435 #ifdef FEAT_LINEBREAK
436     curwin->w_p_lbr = has_lbr;
437 #endif
438     if (!format_only && haveto_redraw)
439     {
440 	update_topline();
441 	redraw_curbuf_later(VALID);
442     }
443 }
444 
445 /*
446  * Blank lines, and lines containing only the comment leader, are left
447  * untouched by the formatting.  The function returns TRUE in this
448  * case.  It also returns TRUE when a line starts with the end of a comment
449  * ('e' in comment flags), so that this line is skipped, and not joined to the
450  * previous line.  A new paragraph starts after a blank line, or when the
451  * comment leader changes -- webb.
452  */
453     static int
fmt_check_par(linenr_T lnum,int * leader_len,char_u ** leader_flags,int do_comments)454 fmt_check_par(
455     linenr_T	lnum,
456     int		*leader_len,
457     char_u	**leader_flags,
458     int		do_comments)
459 {
460     char_u	*flags = NULL;	    // init for GCC
461     char_u	*ptr;
462 
463     ptr = ml_get(lnum);
464     if (do_comments)
465 	*leader_len = get_leader_len(ptr, leader_flags, FALSE, TRUE);
466     else
467 	*leader_len = 0;
468 
469     if (*leader_len > 0)
470     {
471 	// Search for 'e' flag in comment leader flags.
472 	flags = *leader_flags;
473 	while (*flags && *flags != ':' && *flags != COM_END)
474 	    ++flags;
475     }
476 
477     return (*skipwhite(ptr + *leader_len) == NUL
478 	    || (*leader_len > 0 && *flags == COM_END)
479 	    || startPS(lnum, NUL, FALSE));
480 }
481 
482 /*
483  * Return TRUE if line "lnum" ends in a white character.
484  */
485     static int
ends_in_white(linenr_T lnum)486 ends_in_white(linenr_T lnum)
487 {
488     char_u	*s = ml_get(lnum);
489     size_t	l;
490 
491     if (*s == NUL)
492 	return FALSE;
493     // Don't use STRLEN() inside VIM_ISWHITE(), SAS/C complains: "macro
494     // invocation may call function multiple times".
495     l = STRLEN(s) - 1;
496     return VIM_ISWHITE(s[l]);
497 }
498 
499 /*
500  * Return TRUE if the two comment leaders given are the same.  "lnum" is
501  * the first line.  White-space is ignored.  Note that the whole of
502  * 'leader1' must match 'leader2_len' characters from 'leader2' -- webb
503  */
504     static int
same_leader(linenr_T lnum,int leader1_len,char_u * leader1_flags,int leader2_len,char_u * leader2_flags)505 same_leader(
506     linenr_T lnum,
507     int	    leader1_len,
508     char_u  *leader1_flags,
509     int	    leader2_len,
510     char_u  *leader2_flags)
511 {
512     int	    idx1 = 0, idx2 = 0;
513     char_u  *p;
514     char_u  *line1;
515     char_u  *line2;
516 
517     if (leader1_len == 0)
518 	return (leader2_len == 0);
519 
520     // If first leader has 'f' flag, the lines can be joined only if the
521     // second line does not have a leader.
522     // If first leader has 'e' flag, the lines can never be joined.
523     // If fist leader has 's' flag, the lines can only be joined if there is
524     // some text after it and the second line has the 'm' flag.
525     if (leader1_flags != NULL)
526     {
527 	for (p = leader1_flags; *p && *p != ':'; ++p)
528 	{
529 	    if (*p == COM_FIRST)
530 		return (leader2_len == 0);
531 	    if (*p == COM_END)
532 		return FALSE;
533 	    if (*p == COM_START)
534 	    {
535 		if (*(ml_get(lnum) + leader1_len) == NUL)
536 		    return FALSE;
537 		if (leader2_flags == NULL || leader2_len == 0)
538 		    return FALSE;
539 		for (p = leader2_flags; *p && *p != ':'; ++p)
540 		    if (*p == COM_MIDDLE)
541 			return TRUE;
542 		return FALSE;
543 	    }
544 	}
545     }
546 
547     // Get current line and next line, compare the leaders.
548     // The first line has to be saved, only one line can be locked at a time.
549     line1 = vim_strsave(ml_get(lnum));
550     if (line1 != NULL)
551     {
552 	for (idx1 = 0; VIM_ISWHITE(line1[idx1]); ++idx1)
553 	    ;
554 	line2 = ml_get(lnum + 1);
555 	for (idx2 = 0; idx2 < leader2_len; ++idx2)
556 	{
557 	    if (!VIM_ISWHITE(line2[idx2]))
558 	    {
559 		if (line1[idx1++] != line2[idx2])
560 		    break;
561 	    }
562 	    else
563 		while (VIM_ISWHITE(line1[idx1]))
564 		    ++idx1;
565 	}
566 	vim_free(line1);
567     }
568     return (idx2 == leader2_len && idx1 == leader1_len);
569 }
570 
571 /*
572  * Return TRUE when a paragraph starts in line "lnum".  Return FALSE when the
573  * previous line is in the same paragraph.  Used for auto-formatting.
574  */
575     static int
paragraph_start(linenr_T lnum)576 paragraph_start(linenr_T lnum)
577 {
578     char_u	*p;
579     int		leader_len = 0;		// leader len of current line
580     char_u	*leader_flags = NULL;	// flags for leader of current line
581     int		next_leader_len;	// leader len of next line
582     char_u	*next_leader_flags;	// flags for leader of next line
583     int		do_comments;		// format comments
584 
585     if (lnum <= 1)
586 	return TRUE;		// start of the file
587 
588     p = ml_get(lnum - 1);
589     if (*p == NUL)
590 	return TRUE;		// after empty line
591 
592     do_comments = has_format_option(FO_Q_COMS);
593     if (fmt_check_par(lnum - 1, &leader_len, &leader_flags, do_comments))
594 	return TRUE;		// after non-paragraph line
595 
596     if (fmt_check_par(lnum, &next_leader_len, &next_leader_flags, do_comments))
597 	return TRUE;		// "lnum" is not a paragraph line
598 
599     if (has_format_option(FO_WHITE_PAR) && !ends_in_white(lnum - 1))
600 	return TRUE;		// missing trailing space in previous line.
601 
602     if (has_format_option(FO_Q_NUMBER) && (get_number_indent(lnum) > 0))
603 	return TRUE;		// numbered item starts in "lnum".
604 
605     if (!same_leader(lnum - 1, leader_len, leader_flags,
606 					  next_leader_len, next_leader_flags))
607 	return TRUE;		// change of comment leader.
608 
609     return FALSE;
610 }
611 
612 /*
613  * Called after inserting or deleting text: When 'formatoptions' includes the
614  * 'a' flag format from the current line until the end of the paragraph.
615  * Keep the cursor at the same position relative to the text.
616  * The caller must have saved the cursor line for undo, following ones will be
617  * saved here.
618  */
619     void
auto_format(int trailblank,int prev_line)620 auto_format(
621     int		trailblank,	// when TRUE also format with trailing blank
622     int		prev_line)	// may start in previous line
623 {
624     pos_T	pos;
625     colnr_T	len;
626     char_u	*old;
627     char_u	*new, *pnew;
628     int		wasatend;
629     int		cc;
630 
631     if (!has_format_option(FO_AUTO))
632 	return;
633 
634     pos = curwin->w_cursor;
635     old = ml_get_curline();
636 
637     // may remove added space
638     check_auto_format(FALSE);
639 
640     // Don't format in Insert mode when the cursor is on a trailing blank, the
641     // user might insert normal text next.  Also skip formatting when "1" is
642     // in 'formatoptions' and there is a single character before the cursor.
643     // Otherwise the line would be broken and when typing another non-white
644     // next they are not joined back together.
645     wasatend = (pos.col == (colnr_T)STRLEN(old));
646     if (*old != NUL && !trailblank && wasatend)
647     {
648 	dec_cursor();
649 	cc = gchar_cursor();
650 	if (!WHITECHAR(cc) && curwin->w_cursor.col > 0
651 					  && has_format_option(FO_ONE_LETTER))
652 	    dec_cursor();
653 	cc = gchar_cursor();
654 	if (WHITECHAR(cc))
655 	{
656 	    curwin->w_cursor = pos;
657 	    return;
658 	}
659 	curwin->w_cursor = pos;
660     }
661 
662     // With the 'c' flag in 'formatoptions' and 't' missing: only format
663     // comments.
664     if (has_format_option(FO_WRAP_COMS) && !has_format_option(FO_WRAP)
665 				&& get_leader_len(old, NULL, FALSE, TRUE) == 0)
666 	return;
667 
668     // May start formatting in a previous line, so that after "x" a word is
669     // moved to the previous line if it fits there now.  Only when this is not
670     // the start of a paragraph.
671     if (prev_line && !paragraph_start(curwin->w_cursor.lnum))
672     {
673 	--curwin->w_cursor.lnum;
674 	if (u_save_cursor() == FAIL)
675 	    return;
676     }
677 
678     // Do the formatting and restore the cursor position.  "saved_cursor" will
679     // be adjusted for the text formatting.
680     saved_cursor = pos;
681     format_lines((linenr_T)-1, FALSE);
682     curwin->w_cursor = saved_cursor;
683     saved_cursor.lnum = 0;
684 
685     if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
686     {
687 	// "cannot happen"
688 	curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
689 	coladvance((colnr_T)MAXCOL);
690     }
691     else
692 	check_cursor_col();
693 
694     // Insert mode: If the cursor is now after the end of the line while it
695     // previously wasn't, the line was broken.  Because of the rule above we
696     // need to add a space when 'w' is in 'formatoptions' to keep a paragraph
697     // formatted.
698     if (!wasatend && has_format_option(FO_WHITE_PAR))
699     {
700 	new = ml_get_curline();
701 	len = (colnr_T)STRLEN(new);
702 	if (curwin->w_cursor.col == len)
703 	{
704 	    pnew = vim_strnsave(new, len + 2);
705 	    pnew[len] = ' ';
706 	    pnew[len + 1] = NUL;
707 	    ml_replace(curwin->w_cursor.lnum, pnew, FALSE);
708 	    // remove the space later
709 	    did_add_space = TRUE;
710 	}
711 	else
712 	    // may remove added space
713 	    check_auto_format(FALSE);
714     }
715 
716     check_cursor();
717 }
718 
719 /*
720  * When an extra space was added to continue a paragraph for auto-formatting,
721  * delete it now.  The space must be under the cursor, just after the insert
722  * position.
723  */
724     void
check_auto_format(int end_insert)725 check_auto_format(
726     int		end_insert)	    // TRUE when ending Insert mode
727 {
728     int		c = ' ';
729     int		cc;
730 
731     if (did_add_space)
732     {
733 	cc = gchar_cursor();
734 	if (!WHITECHAR(cc))
735 	    // Somehow the space was removed already.
736 	    did_add_space = FALSE;
737 	else
738 	{
739 	    if (!end_insert)
740 	    {
741 		inc_cursor();
742 		c = gchar_cursor();
743 		dec_cursor();
744 	    }
745 	    if (c != NUL)
746 	    {
747 		// The space is no longer at the end of the line, delete it.
748 		del_char(FALSE);
749 		did_add_space = FALSE;
750 	    }
751 	}
752     }
753 }
754 
755 /*
756  * Find out textwidth to be used for formatting:
757  *	if 'textwidth' option is set, use it
758  *	else if 'wrapmargin' option is set, use curwin->w_width - 'wrapmargin'
759  *	if invalid value, use 0.
760  *	Set default to window width (maximum 79) for "gq" operator.
761  */
762     int
comp_textwidth(int ff)763 comp_textwidth(
764     int		ff)	// force formatting (for "gq" command)
765 {
766     int		textwidth;
767 
768     textwidth = curbuf->b_p_tw;
769     if (textwidth == 0 && curbuf->b_p_wm)
770     {
771 	// The width is the window width minus 'wrapmargin' minus all the
772 	// things that add to the margin.
773 	textwidth = curwin->w_width - curbuf->b_p_wm;
774 #ifdef FEAT_CMDWIN
775 	if (cmdwin_type != 0)
776 	    textwidth -= 1;
777 #endif
778 #ifdef FEAT_FOLDING
779 	textwidth -= curwin->w_p_fdc;
780 #endif
781 #ifdef FEAT_SIGNS
782 	if (signcolumn_on(curwin))
783 	    textwidth -= 1;
784 #endif
785 	if (curwin->w_p_nu || curwin->w_p_rnu)
786 	    textwidth -= 8;
787     }
788     if (textwidth < 0)
789 	textwidth = 0;
790     if (ff && textwidth == 0)
791     {
792 	textwidth = curwin->w_width - 1;
793 	if (textwidth > 79)
794 	    textwidth = 79;
795     }
796     return textwidth;
797 }
798 
799 /*
800  * Implementation of the format operator 'gq'.
801  */
802     void
op_format(oparg_T * oap,int keep_cursor)803 op_format(
804     oparg_T	*oap,
805     int		keep_cursor)		// keep cursor on same text char
806 {
807     long	old_line_count = curbuf->b_ml.ml_line_count;
808 
809     // Place the cursor where the "gq" or "gw" command was given, so that "u"
810     // can put it back there.
811     curwin->w_cursor = oap->cursor_start;
812 
813     if (u_save((linenr_T)(oap->start.lnum - 1),
814 				       (linenr_T)(oap->end.lnum + 1)) == FAIL)
815 	return;
816     curwin->w_cursor = oap->start;
817 
818     if (oap->is_VIsual)
819 	// When there is no change: need to remove the Visual selection
820 	redraw_curbuf_later(INVERTED);
821 
822     if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0)
823 	// Set '[ mark at the start of the formatted area
824 	curbuf->b_op_start = oap->start;
825 
826     // For "gw" remember the cursor position and put it back below (adjusted
827     // for joined and split lines).
828     if (keep_cursor)
829 	saved_cursor = oap->cursor_start;
830 
831     format_lines(oap->line_count, keep_cursor);
832 
833     // Leave the cursor at the first non-blank of the last formatted line.
834     // If the cursor was moved one line back (e.g. with "Q}") go to the next
835     // line, so "." will do the next lines.
836     if (oap->end_adjusted && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
837 	++curwin->w_cursor.lnum;
838     beginline(BL_WHITE | BL_FIX);
839     old_line_count = curbuf->b_ml.ml_line_count - old_line_count;
840     msgmore(old_line_count);
841 
842     if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0)
843 	// put '] mark on the end of the formatted area
844 	curbuf->b_op_end = curwin->w_cursor;
845 
846     if (keep_cursor)
847     {
848 	curwin->w_cursor = saved_cursor;
849 	saved_cursor.lnum = 0;
850     }
851 
852     if (oap->is_VIsual)
853     {
854 	win_T	*wp;
855 
856 	FOR_ALL_WINDOWS(wp)
857 	{
858 	    if (wp->w_old_cursor_lnum != 0)
859 	    {
860 		// When lines have been inserted or deleted, adjust the end of
861 		// the Visual area to be redrawn.
862 		if (wp->w_old_cursor_lnum > wp->w_old_visual_lnum)
863 		    wp->w_old_cursor_lnum += old_line_count;
864 		else
865 		    wp->w_old_visual_lnum += old_line_count;
866 	    }
867 	}
868     }
869 }
870 
871 #if defined(FEAT_EVAL) || defined(PROTO)
872 /*
873  * Implementation of the format operator 'gq' for when using 'formatexpr'.
874  */
875     void
op_formatexpr(oparg_T * oap)876 op_formatexpr(oparg_T *oap)
877 {
878     if (oap->is_VIsual)
879 	// When there is no change: need to remove the Visual selection
880 	redraw_curbuf_later(INVERTED);
881 
882     if (fex_format(oap->start.lnum, oap->line_count, NUL) != 0)
883 	// As documented: when 'formatexpr' returns non-zero fall back to
884 	// internal formatting.
885 	op_format(oap, FALSE);
886 }
887 
888     int
fex_format(linenr_T lnum,long count,int c)889 fex_format(
890     linenr_T	lnum,
891     long	count,
892     int		c)	// character to be inserted
893 {
894     int		use_sandbox = was_set_insecurely((char_u *)"formatexpr",
895 								   OPT_LOCAL);
896     int		r;
897     char_u	*fex;
898 
899     // Set v:lnum to the first line number and v:count to the number of lines.
900     // Set v:char to the character to be inserted (can be NUL).
901     set_vim_var_nr(VV_LNUM, lnum);
902     set_vim_var_nr(VV_COUNT, count);
903     set_vim_var_char(c);
904 
905     // Make a copy, the option could be changed while calling it.
906     fex = vim_strsave(curbuf->b_p_fex);
907     if (fex == NULL)
908 	return 0;
909 
910     // Evaluate the function.
911     if (use_sandbox)
912 	++sandbox;
913     r = (int)eval_to_number(fex);
914     if (use_sandbox)
915 	--sandbox;
916 
917     set_vim_var_string(VV_CHAR, NULL, -1);
918     vim_free(fex);
919 
920     return r;
921 }
922 #endif
923 
924 /*
925  * Format "line_count" lines, starting at the cursor position.
926  * When "line_count" is negative, format until the end of the paragraph.
927  * Lines after the cursor line are saved for undo, caller must have saved the
928  * first line.
929  */
930     void
format_lines(linenr_T line_count,int avoid_fex)931 format_lines(
932     linenr_T	line_count,
933     int		avoid_fex)		// don't use 'formatexpr'
934 {
935     int		max_len;
936     int		is_not_par;		// current line not part of parag.
937     int		next_is_not_par;	// next line not part of paragraph
938     int		is_end_par;		// at end of paragraph
939     int		prev_is_end_par = FALSE;// prev. line not part of parag.
940     int		next_is_start_par = FALSE;
941     int		leader_len = 0;		// leader len of current line
942     int		next_leader_len;	// leader len of next line
943     char_u	*leader_flags = NULL;	// flags for leader of current line
944     char_u	*next_leader_flags;	// flags for leader of next line
945     int		do_comments;		// format comments
946     int		do_comments_list = 0;	// format comments with 'n' or '2'
947     int		advance = TRUE;
948     int		second_indent = -1;	// indent for second line (comment
949 					// aware)
950     int		do_second_indent;
951     int		do_number_indent;
952     int		do_trail_white;
953     int		first_par_line = TRUE;
954     int		smd_save;
955     long	count;
956     int		need_set_indent = TRUE;	// set indent of next paragraph
957     int		force_format = FALSE;
958     int		old_State = State;
959 
960     // length of a line to force formatting: 3 * 'tw'
961     max_len = comp_textwidth(TRUE) * 3;
962 
963     // check for 'q', '2' and '1' in 'formatoptions'
964     do_comments = has_format_option(FO_Q_COMS);
965     do_second_indent = has_format_option(FO_Q_SECOND);
966     do_number_indent = has_format_option(FO_Q_NUMBER);
967     do_trail_white = has_format_option(FO_WHITE_PAR);
968 
969     // Get info about the previous and current line.
970     if (curwin->w_cursor.lnum > 1)
971 	is_not_par = fmt_check_par(curwin->w_cursor.lnum - 1
972 				, &leader_len, &leader_flags, do_comments);
973     else
974 	is_not_par = TRUE;
975     next_is_not_par = fmt_check_par(curwin->w_cursor.lnum
976 			  , &next_leader_len, &next_leader_flags, do_comments);
977     is_end_par = (is_not_par || next_is_not_par);
978     if (!is_end_par && do_trail_white)
979 	is_end_par = !ends_in_white(curwin->w_cursor.lnum - 1);
980 
981     curwin->w_cursor.lnum--;
982     for (count = line_count; count != 0 && !got_int; --count)
983     {
984 	// Advance to next paragraph.
985 	if (advance)
986 	{
987 	    curwin->w_cursor.lnum++;
988 	    prev_is_end_par = is_end_par;
989 	    is_not_par = next_is_not_par;
990 	    leader_len = next_leader_len;
991 	    leader_flags = next_leader_flags;
992 	}
993 
994 	// The last line to be formatted.
995 	if (count == 1 || curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
996 	{
997 	    next_is_not_par = TRUE;
998 	    next_leader_len = 0;
999 	    next_leader_flags = NULL;
1000 	}
1001 	else
1002 	{
1003 	    next_is_not_par = fmt_check_par(curwin->w_cursor.lnum + 1
1004 			  , &next_leader_len, &next_leader_flags, do_comments);
1005 	    if (do_number_indent)
1006 		next_is_start_par =
1007 			   (get_number_indent(curwin->w_cursor.lnum + 1) > 0);
1008 	}
1009 	advance = TRUE;
1010 	is_end_par = (is_not_par || next_is_not_par || next_is_start_par);
1011 	if (!is_end_par && do_trail_white)
1012 	    is_end_par = !ends_in_white(curwin->w_cursor.lnum);
1013 
1014 	// Skip lines that are not in a paragraph.
1015 	if (is_not_par)
1016 	{
1017 	    if (line_count < 0)
1018 		break;
1019 	}
1020 	else
1021 	{
1022 	    // For the first line of a paragraph, check indent of second line.
1023 	    // Don't do this for comments and empty lines.
1024 	    if (first_par_line
1025 		    && (do_second_indent || do_number_indent)
1026 		    && prev_is_end_par
1027 		    && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
1028 	    {
1029 		if (do_second_indent && !LINEEMPTY(curwin->w_cursor.lnum + 1))
1030 		{
1031 		    if (leader_len == 0 && next_leader_len == 0)
1032 		    {
1033 			// no comment found
1034 			second_indent =
1035 				   get_indent_lnum(curwin->w_cursor.lnum + 1);
1036 		    }
1037 		    else
1038 		    {
1039 			second_indent = next_leader_len;
1040 			do_comments_list = 1;
1041 		    }
1042 		}
1043 		else if (do_number_indent)
1044 		{
1045 		    if (leader_len == 0 && next_leader_len == 0)
1046 		    {
1047 			// no comment found
1048 			second_indent =
1049 				     get_number_indent(curwin->w_cursor.lnum);
1050 		    }
1051 		    else
1052 		    {
1053 			// get_number_indent() is now "comment aware"...
1054 			second_indent =
1055 				     get_number_indent(curwin->w_cursor.lnum);
1056 			do_comments_list = 1;
1057 		    }
1058 		}
1059 	    }
1060 
1061 	    // When the comment leader changes, it's the end of the paragraph.
1062 	    if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count
1063 		    || !same_leader(curwin->w_cursor.lnum,
1064 					leader_len, leader_flags,
1065 					   next_leader_len, next_leader_flags))
1066 		is_end_par = TRUE;
1067 
1068 	    // If we have got to the end of a paragraph, or the line is
1069 	    // getting long, format it.
1070 	    if (is_end_par || force_format)
1071 	    {
1072 		if (need_set_indent)
1073 		{
1074 		    int		indent = 0; // amount of indent needed
1075 
1076 		    // replace indent in first line with minimal number of
1077 		    // tabs and spaces, according to current options
1078 # ifdef FEAT_LISP
1079 		    if (curbuf->b_p_lisp)
1080 			indent = get_lisp_indent();
1081 		    else
1082 # endif
1083 		    {
1084 #ifdef FEAT_CINDENT
1085 			if (cindent_on())
1086 			{
1087 			    indent =
1088 # ifdef FEAT_EVAL
1089 				 *curbuf->b_p_inde != NUL ? get_expr_indent() :
1090 # endif
1091 				 get_c_indent();
1092 			}
1093 			else
1094 #endif
1095 			    indent = get_indent();
1096 		    }
1097 		    (void)set_indent(indent, SIN_CHANGED);
1098 		}
1099 
1100 		// put cursor on last non-space
1101 		State = NORMAL;	// don't go past end-of-line
1102 		coladvance((colnr_T)MAXCOL);
1103 		while (curwin->w_cursor.col && vim_isspace(gchar_cursor()))
1104 		    dec_cursor();
1105 
1106 		// do the formatting, without 'showmode'
1107 		State = INSERT;	// for open_line()
1108 		smd_save = p_smd;
1109 		p_smd = FALSE;
1110 		insertchar(NUL, INSCHAR_FORMAT
1111 			+ (do_comments ? INSCHAR_DO_COM : 0)
1112 			+ (do_comments && do_comments_list
1113 						       ? INSCHAR_COM_LIST : 0)
1114 			+ (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent);
1115 		State = old_State;
1116 		p_smd = smd_save;
1117 		second_indent = -1;
1118 		// at end of par.: need to set indent of next par.
1119 		need_set_indent = is_end_par;
1120 		if (is_end_par)
1121 		{
1122 		    // When called with a negative line count, break at the
1123 		    // end of the paragraph.
1124 		    if (line_count < 0)
1125 			break;
1126 		    first_par_line = TRUE;
1127 		}
1128 		force_format = FALSE;
1129 	    }
1130 
1131 	    // When still in same paragraph, join the lines together.  But
1132 	    // first delete the leader from the second line.
1133 	    if (!is_end_par)
1134 	    {
1135 		advance = FALSE;
1136 		curwin->w_cursor.lnum++;
1137 		curwin->w_cursor.col = 0;
1138 		if (line_count < 0 && u_save_cursor() == FAIL)
1139 		    break;
1140 		if (next_leader_len > 0)
1141 		{
1142 		    (void)del_bytes((long)next_leader_len, FALSE, FALSE);
1143 		    mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L,
1144 						    (long)-next_leader_len, 0);
1145 		}
1146 		else if (second_indent > 0)  // the "leader" for FO_Q_SECOND
1147 		{
1148 		    int indent = getwhitecols_curline();
1149 
1150 		    if (indent > 0)
1151 		    {
1152 			(void)del_bytes(indent, FALSE, FALSE);
1153 			mark_col_adjust(curwin->w_cursor.lnum,
1154 					       (colnr_T)0, 0L, (long)-indent, 0);
1155 		    }
1156 		}
1157 		curwin->w_cursor.lnum--;
1158 		if (do_join(2, TRUE, FALSE, FALSE, FALSE) == FAIL)
1159 		{
1160 		    beep_flush();
1161 		    break;
1162 		}
1163 		first_par_line = FALSE;
1164 		// If the line is getting long, format it next time
1165 		if (STRLEN(ml_get_curline()) > (size_t)max_len)
1166 		    force_format = TRUE;
1167 		else
1168 		    force_format = FALSE;
1169 	    }
1170 	}
1171 	line_breakcheck();
1172     }
1173 }
1174