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