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 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 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 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 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 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 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 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 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 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 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 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 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 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 // replace indent in first line with minimal number of 1074 // tabs and spaces, according to current options 1075 (void)set_indent(get_indent(), SIN_CHANGED); 1076 1077 // put cursor on last non-space 1078 State = NORMAL; // don't go past end-of-line 1079 coladvance((colnr_T)MAXCOL); 1080 while (curwin->w_cursor.col && vim_isspace(gchar_cursor())) 1081 dec_cursor(); 1082 1083 // do the formatting, without 'showmode' 1084 State = INSERT; // for open_line() 1085 smd_save = p_smd; 1086 p_smd = FALSE; 1087 insertchar(NUL, INSCHAR_FORMAT 1088 + (do_comments ? INSCHAR_DO_COM : 0) 1089 + (do_comments && do_comments_list 1090 ? INSCHAR_COM_LIST : 0) 1091 + (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent); 1092 State = old_State; 1093 p_smd = smd_save; 1094 second_indent = -1; 1095 // at end of par.: need to set indent of next par. 1096 need_set_indent = is_end_par; 1097 if (is_end_par) 1098 { 1099 // When called with a negative line count, break at the 1100 // end of the paragraph. 1101 if (line_count < 0) 1102 break; 1103 first_par_line = TRUE; 1104 } 1105 force_format = FALSE; 1106 } 1107 1108 // When still in same paragraph, join the lines together. But 1109 // first delete the leader from the second line. 1110 if (!is_end_par) 1111 { 1112 advance = FALSE; 1113 curwin->w_cursor.lnum++; 1114 curwin->w_cursor.col = 0; 1115 if (line_count < 0 && u_save_cursor() == FAIL) 1116 break; 1117 if (next_leader_len > 0) 1118 { 1119 (void)del_bytes((long)next_leader_len, FALSE, FALSE); 1120 mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L, 1121 (long)-next_leader_len, 0); 1122 } 1123 else if (second_indent > 0) // the "leader" for FO_Q_SECOND 1124 { 1125 int indent = getwhitecols_curline(); 1126 1127 if (indent > 0) 1128 { 1129 (void)del_bytes(indent, FALSE, FALSE); 1130 mark_col_adjust(curwin->w_cursor.lnum, 1131 (colnr_T)0, 0L, (long)-indent, 0); 1132 } 1133 } 1134 curwin->w_cursor.lnum--; 1135 if (do_join(2, TRUE, FALSE, FALSE, FALSE) == FAIL) 1136 { 1137 beep_flush(); 1138 break; 1139 } 1140 first_par_line = FALSE; 1141 // If the line is getting long, format it next time 1142 if (STRLEN(ml_get_curline()) > (size_t)max_len) 1143 force_format = TRUE; 1144 else 1145 force_format = FALSE; 1146 } 1147 } 1148 line_breakcheck(); 1149 } 1150 } 1151