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 * change.c: functions related to changing text 12 */ 13 14 #include "vim.h" 15 16 /* 17 * If the file is readonly, give a warning message with the first change. 18 * Don't do this for autocommands. 19 * Doesn't use emsg(), because it flushes the macro buffer. 20 * If we have undone all changes b_changed will be FALSE, but "b_did_warn" 21 * will be TRUE. 22 * "col" is the column for the message; non-zero when in insert mode and 23 * 'showmode' is on. 24 * Careful: may trigger autocommands that reload the buffer. 25 */ 26 void 27 change_warning(int col) 28 { 29 static char *w_readonly = N_("W10: Warning: Changing a readonly file"); 30 31 if (curbuf->b_did_warn == FALSE 32 && curbufIsChanged() == 0 33 && !autocmd_busy 34 && curbuf->b_p_ro) 35 { 36 ++curbuf_lock; 37 apply_autocmds(EVENT_FILECHANGEDRO, NULL, NULL, FALSE, curbuf); 38 --curbuf_lock; 39 if (!curbuf->b_p_ro) 40 return; 41 42 // Do what msg() does, but with a column offset if the warning should 43 // be after the mode message. 44 msg_start(); 45 if (msg_row == Rows - 1) 46 msg_col = col; 47 msg_source(HL_ATTR(HLF_W)); 48 msg_puts_attr(_(w_readonly), HL_ATTR(HLF_W) | MSG_HIST); 49 #ifdef FEAT_EVAL 50 set_vim_var_string(VV_WARNINGMSG, (char_u *)_(w_readonly), -1); 51 #endif 52 msg_clr_eos(); 53 (void)msg_end(); 54 if (msg_silent == 0 && !silent_mode 55 #ifdef FEAT_EVAL 56 && time_for_testing != 1 57 #endif 58 ) 59 { 60 out_flush(); 61 ui_delay(1002L, TRUE); // give the user time to think about it 62 } 63 curbuf->b_did_warn = TRUE; 64 redraw_cmdline = FALSE; // don't redraw and erase the message 65 if (msg_row < Rows - 1) 66 showmode(); 67 } 68 } 69 70 /* 71 * Call this function when something in the current buffer is changed. 72 * 73 * Most often called through changed_bytes() and changed_lines(), which also 74 * mark the area of the display to be redrawn. 75 * 76 * Careful: may trigger autocommands that reload the buffer. 77 */ 78 void 79 changed(void) 80 { 81 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) 82 if (p_imst == IM_ON_THE_SPOT) 83 { 84 // The text of the preediting area is inserted, but this doesn't 85 // mean a change of the buffer yet. That is delayed until the 86 // text is committed. (this means preedit becomes empty) 87 if (im_is_preediting() && !xim_changed_while_preediting) 88 return; 89 xim_changed_while_preediting = FALSE; 90 } 91 #endif 92 93 if (!curbuf->b_changed) 94 { 95 int save_msg_scroll = msg_scroll; 96 97 // Give a warning about changing a read-only file. This may also 98 // check-out the file, thus change "curbuf"! 99 change_warning(0); 100 101 // Create a swap file if that is wanted. 102 // Don't do this for "nofile" and "nowrite" buffer types. 103 if (curbuf->b_may_swap 104 #ifdef FEAT_QUICKFIX 105 && !bt_dontwrite(curbuf) 106 #endif 107 ) 108 { 109 int save_need_wait_return = need_wait_return; 110 111 need_wait_return = FALSE; 112 ml_open_file(curbuf); 113 114 // The ml_open_file() can cause an ATTENTION message. 115 // Wait two seconds, to make sure the user reads this unexpected 116 // message. Since we could be anywhere, call wait_return() now, 117 // and don't let the emsg() set msg_scroll. 118 if (need_wait_return && emsg_silent == 0) 119 { 120 out_flush(); 121 ui_delay(2002L, TRUE); 122 wait_return(TRUE); 123 msg_scroll = save_msg_scroll; 124 } 125 else 126 need_wait_return = save_need_wait_return; 127 } 128 changed_internal(); 129 } 130 ++CHANGEDTICK(curbuf); 131 132 #ifdef FEAT_SEARCH_EXTRA 133 // If a pattern is highlighted, the position may now be invalid. 134 highlight_match = FALSE; 135 #endif 136 } 137 138 /* 139 * Internal part of changed(), no user interaction. 140 * Also used for recovery. 141 */ 142 void 143 changed_internal(void) 144 { 145 curbuf->b_changed = TRUE; 146 ml_setflags(curbuf); 147 check_status(curbuf); 148 redraw_tabline = TRUE; 149 #ifdef FEAT_TITLE 150 need_maketitle = TRUE; // set window title later 151 #endif 152 } 153 154 #ifdef FEAT_EVAL 155 static long next_listener_id = 0; 156 157 /* 158 * Check if the change at "lnum" is above or overlaps with an existing 159 * change. If above then flush changes and invoke listeners. 160 * Returns TRUE if the change was merged. 161 */ 162 static int 163 check_recorded_changes( 164 buf_T *buf, 165 linenr_T lnum, 166 linenr_T lnume, 167 long xtra) 168 { 169 if (buf->b_recorded_changes != NULL && xtra != 0) 170 { 171 listitem_T *li; 172 linenr_T prev_lnum; 173 linenr_T prev_lnume; 174 175 FOR_ALL_LIST_ITEMS(buf->b_recorded_changes, li) 176 { 177 prev_lnum = (linenr_T)dict_get_number( 178 li->li_tv.vval.v_dict, (char_u *)"lnum"); 179 prev_lnume = (linenr_T)dict_get_number( 180 li->li_tv.vval.v_dict, (char_u *)"end"); 181 if (prev_lnum >= lnum || prev_lnum > lnume || prev_lnume >= lnum) 182 { 183 // the current change is going to make the line number in 184 // the older change invalid, flush now 185 invoke_listeners(curbuf); 186 break; 187 } 188 } 189 } 190 return FALSE; 191 } 192 193 /* 194 * Record a change for listeners added with listener_add(). 195 * Always for the current buffer. 196 */ 197 static void 198 may_record_change( 199 linenr_T lnum, 200 colnr_T col, 201 linenr_T lnume, 202 long xtra) 203 { 204 dict_T *dict; 205 206 if (curbuf->b_listener == NULL) 207 return; 208 209 // If the new change is going to change the line numbers in already listed 210 // changes, then flush. 211 if (check_recorded_changes(curbuf, lnum, lnume, xtra)) 212 return; 213 214 if (curbuf->b_recorded_changes == NULL) 215 { 216 curbuf->b_recorded_changes = list_alloc(); 217 if (curbuf->b_recorded_changes == NULL) // out of memory 218 return; 219 ++curbuf->b_recorded_changes->lv_refcount; 220 curbuf->b_recorded_changes->lv_lock = VAR_FIXED; 221 } 222 223 dict = dict_alloc(); 224 if (dict == NULL) 225 return; 226 dict_add_number(dict, "lnum", (varnumber_T)lnum); 227 dict_add_number(dict, "end", (varnumber_T)lnume); 228 dict_add_number(dict, "added", (varnumber_T)xtra); 229 dict_add_number(dict, "col", (varnumber_T)col + 1); 230 231 list_append_dict(curbuf->b_recorded_changes, dict); 232 } 233 234 /* 235 * listener_add() function 236 */ 237 void 238 f_listener_add(typval_T *argvars, typval_T *rettv) 239 { 240 callback_T callback; 241 listener_T *lnr; 242 buf_T *buf = curbuf; 243 244 callback = get_callback(&argvars[0]); 245 if (callback.cb_name == NULL) 246 return; 247 248 if (argvars[1].v_type != VAR_UNKNOWN) 249 { 250 buf = get_buf_arg(&argvars[1]); 251 if (buf == NULL) 252 { 253 free_callback(&callback); 254 return; 255 } 256 } 257 258 lnr = ALLOC_CLEAR_ONE(listener_T); 259 if (lnr == NULL) 260 { 261 free_callback(&callback); 262 return; 263 } 264 lnr->lr_next = buf->b_listener; 265 buf->b_listener = lnr; 266 267 set_callback(&lnr->lr_callback, &callback); 268 269 lnr->lr_id = ++next_listener_id; 270 rettv->vval.v_number = lnr->lr_id; 271 } 272 273 /* 274 * listener_flush() function 275 */ 276 void 277 f_listener_flush(typval_T *argvars, typval_T *rettv UNUSED) 278 { 279 buf_T *buf = curbuf; 280 281 if (argvars[0].v_type != VAR_UNKNOWN) 282 { 283 buf = get_buf_arg(&argvars[0]); 284 if (buf == NULL) 285 return; 286 } 287 invoke_listeners(buf); 288 } 289 290 /* 291 * listener_remove() function 292 */ 293 void 294 f_listener_remove(typval_T *argvars, typval_T *rettv) 295 { 296 listener_T *lnr; 297 listener_T *next; 298 listener_T *prev; 299 int id = tv_get_number(argvars); 300 buf_T *buf; 301 302 FOR_ALL_BUFFERS(buf) 303 { 304 prev = NULL; 305 for (lnr = buf->b_listener; lnr != NULL; lnr = next) 306 { 307 next = lnr->lr_next; 308 if (lnr->lr_id == id) 309 { 310 if (prev != NULL) 311 prev->lr_next = lnr->lr_next; 312 else 313 buf->b_listener = lnr->lr_next; 314 free_callback(&lnr->lr_callback); 315 vim_free(lnr); 316 rettv->vval.v_number = 1; 317 return; 318 } 319 prev = lnr; 320 } 321 } 322 } 323 324 /* 325 * Called before inserting a line above "lnum"/"lnum3" or deleting line "lnum" 326 * to "lnume". 327 */ 328 void 329 may_invoke_listeners(buf_T *buf, linenr_T lnum, linenr_T lnume, int added) 330 { 331 check_recorded_changes(buf, lnum, lnume, added); 332 } 333 334 /* 335 * Called when a sequence of changes is done: invoke listeners added with 336 * listener_add(). 337 */ 338 void 339 invoke_listeners(buf_T *buf) 340 { 341 listener_T *lnr; 342 typval_T rettv; 343 typval_T argv[6]; 344 listitem_T *li; 345 linenr_T start = MAXLNUM; 346 linenr_T end = 0; 347 linenr_T added = 0; 348 int save_updating_screen = updating_screen; 349 static int recursive = FALSE; 350 351 if (buf->b_recorded_changes == NULL // nothing changed 352 || buf->b_listener == NULL // no listeners 353 || recursive) // already busy 354 return; 355 recursive = TRUE; 356 357 // Block messages on channels from being handled, so that they don't make 358 // text changes here. 359 ++updating_screen; 360 361 argv[0].v_type = VAR_NUMBER; 362 argv[0].vval.v_number = buf->b_fnum; // a:bufnr 363 364 FOR_ALL_LIST_ITEMS(buf->b_recorded_changes, li) 365 { 366 varnumber_T lnum; 367 368 lnum = dict_get_number(li->li_tv.vval.v_dict, (char_u *)"lnum"); 369 if (start > lnum) 370 start = lnum; 371 lnum = dict_get_number(li->li_tv.vval.v_dict, (char_u *)"end"); 372 if (end < lnum) 373 end = lnum; 374 added += dict_get_number(li->li_tv.vval.v_dict, (char_u *)"added"); 375 } 376 argv[1].v_type = VAR_NUMBER; 377 argv[1].vval.v_number = start; 378 argv[2].v_type = VAR_NUMBER; 379 argv[2].vval.v_number = end; 380 argv[3].v_type = VAR_NUMBER; 381 argv[3].vval.v_number = added; 382 383 argv[4].v_type = VAR_LIST; 384 argv[4].vval.v_list = buf->b_recorded_changes; 385 ++textwinlock; 386 387 for (lnr = buf->b_listener; lnr != NULL; lnr = lnr->lr_next) 388 { 389 call_callback(&lnr->lr_callback, -1, &rettv, 5, argv); 390 clear_tv(&rettv); 391 } 392 393 --textwinlock; 394 list_unref(buf->b_recorded_changes); 395 buf->b_recorded_changes = NULL; 396 397 if (save_updating_screen) 398 updating_screen = TRUE; 399 else 400 after_updating_screen(TRUE); 401 recursive = FALSE; 402 } 403 404 /* 405 * Remove all listeners associated with "buf". 406 */ 407 void 408 remove_listeners(buf_T *buf) 409 { 410 listener_T *lnr; 411 listener_T *next; 412 413 for (lnr = buf->b_listener; lnr != NULL; lnr = next) 414 { 415 next = lnr->lr_next; 416 free_callback(&lnr->lr_callback); 417 vim_free(lnr); 418 } 419 buf->b_listener = NULL; 420 } 421 #endif 422 423 /* 424 * Common code for when a change was made. 425 * See changed_lines() for the arguments. 426 * Careful: may trigger autocommands that reload the buffer. 427 */ 428 static void 429 changed_common( 430 linenr_T lnum, 431 colnr_T col, 432 linenr_T lnume, 433 long xtra) 434 { 435 win_T *wp; 436 tabpage_T *tp; 437 int i; 438 #ifdef FEAT_JUMPLIST 439 int cols; 440 pos_T *p; 441 int add; 442 #endif 443 444 // mark the buffer as modified 445 changed(); 446 447 #ifdef FEAT_EVAL 448 may_record_change(lnum, col, lnume, xtra); 449 #endif 450 #ifdef FEAT_DIFF 451 if (curwin->w_p_diff && diff_internal()) 452 curtab->tp_diff_update = TRUE; 453 #endif 454 455 // set the '. mark 456 if (!cmdmod.keepjumps) 457 { 458 curbuf->b_last_change.lnum = lnum; 459 curbuf->b_last_change.col = col; 460 461 #ifdef FEAT_JUMPLIST 462 // Create a new entry if a new undo-able change was started or we 463 // don't have an entry yet. 464 if (curbuf->b_new_change || curbuf->b_changelistlen == 0) 465 { 466 if (curbuf->b_changelistlen == 0) 467 add = TRUE; 468 else 469 { 470 // Don't create a new entry when the line number is the same 471 // as the last one and the column is not too far away. Avoids 472 // creating many entries for typing "xxxxx". 473 p = &curbuf->b_changelist[curbuf->b_changelistlen - 1]; 474 if (p->lnum != lnum) 475 add = TRUE; 476 else 477 { 478 cols = comp_textwidth(FALSE); 479 if (cols == 0) 480 cols = 79; 481 add = (p->col + cols < col || col + cols < p->col); 482 } 483 } 484 if (add) 485 { 486 // This is the first of a new sequence of undo-able changes 487 // and it's at some distance of the last change. Use a new 488 // position in the changelist. 489 curbuf->b_new_change = FALSE; 490 491 if (curbuf->b_changelistlen == JUMPLISTSIZE) 492 { 493 // changelist is full: remove oldest entry 494 curbuf->b_changelistlen = JUMPLISTSIZE - 1; 495 mch_memmove(curbuf->b_changelist, curbuf->b_changelist + 1, 496 sizeof(pos_T) * (JUMPLISTSIZE - 1)); 497 FOR_ALL_TAB_WINDOWS(tp, wp) 498 { 499 // Correct position in changelist for other windows on 500 // this buffer. 501 if (wp->w_buffer == curbuf && wp->w_changelistidx > 0) 502 --wp->w_changelistidx; 503 } 504 } 505 FOR_ALL_TAB_WINDOWS(tp, wp) 506 { 507 // For other windows, if the position in the changelist is 508 // at the end it stays at the end. 509 if (wp->w_buffer == curbuf 510 && wp->w_changelistidx == curbuf->b_changelistlen) 511 ++wp->w_changelistidx; 512 } 513 ++curbuf->b_changelistlen; 514 } 515 } 516 curbuf->b_changelist[curbuf->b_changelistlen - 1] = 517 curbuf->b_last_change; 518 // The current window is always after the last change, so that "g," 519 // takes you back to it. 520 curwin->w_changelistidx = curbuf->b_changelistlen; 521 #endif 522 } 523 524 FOR_ALL_TAB_WINDOWS(tp, wp) 525 { 526 if (wp->w_buffer == curbuf) 527 { 528 // Mark this window to be redrawn later. 529 if (wp->w_redr_type < VALID) 530 wp->w_redr_type = VALID; 531 532 // Check if a change in the buffer has invalidated the cached 533 // values for the cursor. 534 #ifdef FEAT_FOLDING 535 // Update the folds for this window. Can't postpone this, because 536 // a following operator might work on the whole fold: ">>dd". 537 foldUpdate(wp, lnum, lnume + xtra - 1); 538 539 // The change may cause lines above or below the change to become 540 // included in a fold. Set lnum/lnume to the first/last line that 541 // might be displayed differently. 542 // Set w_cline_folded here as an efficient way to update it when 543 // inserting lines just above a closed fold. 544 i = hasFoldingWin(wp, lnum, &lnum, NULL, FALSE, NULL); 545 if (wp->w_cursor.lnum == lnum) 546 wp->w_cline_folded = i; 547 i = hasFoldingWin(wp, lnume, NULL, &lnume, FALSE, NULL); 548 if (wp->w_cursor.lnum == lnume) 549 wp->w_cline_folded = i; 550 551 // If the changed line is in a range of previously folded lines, 552 // compare with the first line in that range. 553 if (wp->w_cursor.lnum <= lnum) 554 { 555 i = find_wl_entry(wp, lnum); 556 if (i >= 0 && wp->w_cursor.lnum > wp->w_lines[i].wl_lnum) 557 changed_line_abv_curs_win(wp); 558 } 559 #endif 560 if (wp->w_cursor.lnum > lnum) 561 changed_line_abv_curs_win(wp); 562 else if (wp->w_cursor.lnum == lnum && wp->w_cursor.col >= col) 563 changed_cline_bef_curs_win(wp); 564 if (wp->w_botline >= lnum) 565 { 566 // Assume that botline doesn't change (inserted lines make 567 // other lines scroll down below botline). 568 approximate_botline_win(wp); 569 } 570 571 // Check if any w_lines[] entries have become invalid. 572 // For entries below the change: Correct the lnums for 573 // inserted/deleted lines. Makes it possible to stop displaying 574 // after the change. 575 for (i = 0; i < wp->w_lines_valid; ++i) 576 if (wp->w_lines[i].wl_valid) 577 { 578 if (wp->w_lines[i].wl_lnum >= lnum) 579 { 580 if (wp->w_lines[i].wl_lnum < lnume) 581 { 582 // line included in change 583 wp->w_lines[i].wl_valid = FALSE; 584 } 585 else if (xtra != 0) 586 { 587 // line below change 588 wp->w_lines[i].wl_lnum += xtra; 589 #ifdef FEAT_FOLDING 590 wp->w_lines[i].wl_lastlnum += xtra; 591 #endif 592 } 593 } 594 #ifdef FEAT_FOLDING 595 else if (wp->w_lines[i].wl_lastlnum >= lnum) 596 { 597 // change somewhere inside this range of folded lines, 598 // may need to be redrawn 599 wp->w_lines[i].wl_valid = FALSE; 600 } 601 #endif 602 } 603 604 #ifdef FEAT_FOLDING 605 // Take care of side effects for setting w_topline when folds have 606 // changed. Esp. when the buffer was changed in another window. 607 if (hasAnyFolding(wp)) 608 set_topline(wp, wp->w_topline); 609 #endif 610 // Relative numbering may require updating more. 611 if (wp->w_p_rnu) 612 redraw_win_later(wp, SOME_VALID); 613 #ifdef FEAT_SYN_HL 614 // Cursor line highlighting probably need to be updated with 615 // "VALID" if it's below the change. 616 // If the cursor line is inside the change we need to redraw more. 617 if (wp->w_p_cul) 618 { 619 if (xtra == 0) 620 redraw_win_later(wp, VALID); 621 else if (lnum <= wp->w_last_cursorline) 622 redraw_win_later(wp, SOME_VALID); 623 } 624 #endif 625 } 626 } 627 628 // Call update_screen() later, which checks out what needs to be redrawn, 629 // since it notices b_mod_set and then uses b_mod_*. 630 if (must_redraw < VALID) 631 must_redraw = VALID; 632 633 // when the cursor line is changed always trigger CursorMoved 634 if (lnum <= curwin->w_cursor.lnum 635 && lnume + (xtra < 0 ? -xtra : xtra) > curwin->w_cursor.lnum) 636 last_cursormoved.lnum = 0; 637 } 638 639 static void 640 changedOneline(buf_T *buf, linenr_T lnum) 641 { 642 if (buf->b_mod_set) 643 { 644 // find the maximum area that must be redisplayed 645 if (lnum < buf->b_mod_top) 646 buf->b_mod_top = lnum; 647 else if (lnum >= buf->b_mod_bot) 648 buf->b_mod_bot = lnum + 1; 649 } 650 else 651 { 652 // set the area that must be redisplayed to one line 653 buf->b_mod_set = TRUE; 654 buf->b_mod_top = lnum; 655 buf->b_mod_bot = lnum + 1; 656 buf->b_mod_xlines = 0; 657 } 658 } 659 660 /* 661 * Changed bytes within a single line for the current buffer. 662 * - marks the windows on this buffer to be redisplayed 663 * - marks the buffer changed by calling changed() 664 * - invalidates cached values 665 * Careful: may trigger autocommands that reload the buffer. 666 */ 667 void 668 changed_bytes(linenr_T lnum, colnr_T col) 669 { 670 changedOneline(curbuf, lnum); 671 changed_common(lnum, col, lnum + 1, 0L); 672 673 #ifdef FEAT_DIFF 674 // Diff highlighting in other diff windows may need to be updated too. 675 if (curwin->w_p_diff) 676 { 677 win_T *wp; 678 linenr_T wlnum; 679 680 FOR_ALL_WINDOWS(wp) 681 if (wp->w_p_diff && wp != curwin) 682 { 683 redraw_win_later(wp, VALID); 684 wlnum = diff_lnum_win(lnum, wp); 685 if (wlnum > 0) 686 changedOneline(wp->w_buffer, wlnum); 687 } 688 } 689 #endif 690 } 691 692 /* 693 * Like changed_bytes() but also adjust text properties for "added" bytes. 694 * When "added" is negative text was deleted. 695 */ 696 static void 697 inserted_bytes(linenr_T lnum, colnr_T col, int added UNUSED) 698 { 699 #ifdef FEAT_PROP_POPUP 700 if (curbuf->b_has_textprop && added != 0) 701 adjust_prop_columns(lnum, col, added, 0); 702 #endif 703 704 changed_bytes(lnum, col); 705 } 706 707 /* 708 * Appended "count" lines below line "lnum" in the current buffer. 709 * Must be called AFTER the change and after mark_adjust(). 710 * Takes care of marking the buffer to be redrawn and sets the changed flag. 711 */ 712 void 713 appended_lines(linenr_T lnum, long count) 714 { 715 changed_lines(lnum + 1, 0, lnum + 1, count); 716 } 717 718 /* 719 * Like appended_lines(), but adjust marks first. 720 */ 721 void 722 appended_lines_mark(linenr_T lnum, long count) 723 { 724 // Skip mark_adjust when adding a line after the last one, there can't 725 // be marks there. But it's still needed in diff mode. 726 if (lnum + count < curbuf->b_ml.ml_line_count 727 #ifdef FEAT_DIFF 728 || curwin->w_p_diff 729 #endif 730 ) 731 mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L); 732 changed_lines(lnum + 1, 0, lnum + 1, count); 733 } 734 735 /* 736 * Deleted "count" lines at line "lnum" in the current buffer. 737 * Must be called AFTER the change and after mark_adjust(). 738 * Takes care of marking the buffer to be redrawn and sets the changed flag. 739 */ 740 void 741 deleted_lines(linenr_T lnum, long count) 742 { 743 changed_lines(lnum, 0, lnum + count, -count); 744 } 745 746 /* 747 * Like deleted_lines(), but adjust marks first. 748 * Make sure the cursor is on a valid line before calling, a GUI callback may 749 * be triggered to display the cursor. 750 */ 751 void 752 deleted_lines_mark(linenr_T lnum, long count) 753 { 754 mark_adjust(lnum, (linenr_T)(lnum + count - 1), (long)MAXLNUM, -count); 755 changed_lines(lnum, 0, lnum + count, -count); 756 } 757 758 /* 759 * Marks the area to be redrawn after a change. 760 */ 761 static void 762 changed_lines_buf( 763 buf_T *buf, 764 linenr_T lnum, // first line with change 765 linenr_T lnume, // line below last changed line 766 long xtra) // number of extra lines (negative when deleting) 767 { 768 if (buf->b_mod_set) 769 { 770 // find the maximum area that must be redisplayed 771 if (lnum < buf->b_mod_top) 772 buf->b_mod_top = lnum; 773 if (lnum < buf->b_mod_bot) 774 { 775 // adjust old bot position for xtra lines 776 buf->b_mod_bot += xtra; 777 if (buf->b_mod_bot < lnum) 778 buf->b_mod_bot = lnum; 779 } 780 if (lnume + xtra > buf->b_mod_bot) 781 buf->b_mod_bot = lnume + xtra; 782 buf->b_mod_xlines += xtra; 783 } 784 else 785 { 786 // set the area that must be redisplayed 787 buf->b_mod_set = TRUE; 788 buf->b_mod_top = lnum; 789 buf->b_mod_bot = lnume + xtra; 790 buf->b_mod_xlines = xtra; 791 } 792 } 793 794 /* 795 * Changed lines for the current buffer. 796 * Must be called AFTER the change and after mark_adjust(). 797 * - mark the buffer changed by calling changed() 798 * - mark the windows on this buffer to be redisplayed 799 * - invalidate cached values 800 * "lnum" is the first line that needs displaying, "lnume" the first line 801 * below the changed lines (BEFORE the change). 802 * When only inserting lines, "lnum" and "lnume" are equal. 803 * Takes care of calling changed() and updating b_mod_*. 804 * Careful: may trigger autocommands that reload the buffer. 805 */ 806 void 807 changed_lines( 808 linenr_T lnum, // first line with change 809 colnr_T col, // column in first line with change 810 linenr_T lnume, // line below last changed line 811 long xtra) // number of extra lines (negative when deleting) 812 { 813 changed_lines_buf(curbuf, lnum, lnume, xtra); 814 815 #ifdef FEAT_DIFF 816 if (xtra == 0 && curwin->w_p_diff && !diff_internal()) 817 { 818 // When the number of lines doesn't change then mark_adjust() isn't 819 // called and other diff buffers still need to be marked for 820 // displaying. 821 win_T *wp; 822 linenr_T wlnum; 823 824 FOR_ALL_WINDOWS(wp) 825 if (wp->w_p_diff && wp != curwin) 826 { 827 redraw_win_later(wp, VALID); 828 wlnum = diff_lnum_win(lnum, wp); 829 if (wlnum > 0) 830 changed_lines_buf(wp->w_buffer, wlnum, 831 lnume - lnum + wlnum, 0L); 832 } 833 } 834 #endif 835 836 changed_common(lnum, col, lnume, xtra); 837 } 838 839 /* 840 * Called when the changed flag must be reset for buffer "buf". 841 * When "ff" is TRUE also reset 'fileformat'. 842 * When "always_inc_changedtick" is TRUE b:changedtick is incremented also when 843 * the changed flag was off. 844 */ 845 void 846 unchanged(buf_T *buf, int ff, int always_inc_changedtick) 847 { 848 if (buf->b_changed || (ff && file_ff_differs(buf, FALSE))) 849 { 850 buf->b_changed = 0; 851 ml_setflags(buf); 852 if (ff) 853 save_file_ff(buf); 854 check_status(buf); 855 redraw_tabline = TRUE; 856 #ifdef FEAT_TITLE 857 need_maketitle = TRUE; // set window title later 858 #endif 859 ++CHANGEDTICK(buf); 860 } 861 else if (always_inc_changedtick) 862 ++CHANGEDTICK(buf); 863 #ifdef FEAT_NETBEANS_INTG 864 netbeans_unmodified(buf); 865 #endif 866 } 867 868 /* 869 * Save the current values of 'fileformat' and 'fileencoding', so that we know 870 * the file must be considered changed when the value is different. 871 */ 872 void 873 save_file_ff(buf_T *buf) 874 { 875 buf->b_start_ffc = *buf->b_p_ff; 876 buf->b_start_eol = buf->b_p_eol; 877 buf->b_start_bomb = buf->b_p_bomb; 878 879 // Only use free/alloc when necessary, they take time. 880 if (buf->b_start_fenc == NULL 881 || STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0) 882 { 883 vim_free(buf->b_start_fenc); 884 buf->b_start_fenc = vim_strsave(buf->b_p_fenc); 885 } 886 } 887 888 /* 889 * Return TRUE if 'fileformat' and/or 'fileencoding' has a different value 890 * from when editing started (save_file_ff() called). 891 * Also when 'endofline' was changed and 'binary' is set, or when 'bomb' was 892 * changed and 'binary' is not set. 893 * Also when 'endofline' was changed and 'fixeol' is not set. 894 * When "ignore_empty" is true don't consider a new, empty buffer to be 895 * changed. 896 */ 897 int 898 file_ff_differs(buf_T *buf, int ignore_empty) 899 { 900 // In a buffer that was never loaded the options are not valid. 901 if (buf->b_flags & BF_NEVERLOADED) 902 return FALSE; 903 if (ignore_empty 904 && (buf->b_flags & BF_NEW) 905 && buf->b_ml.ml_line_count == 1 906 && *ml_get_buf(buf, (linenr_T)1, FALSE) == NUL) 907 return FALSE; 908 if (buf->b_start_ffc != *buf->b_p_ff) 909 return TRUE; 910 if ((buf->b_p_bin || !buf->b_p_fixeol) && buf->b_start_eol != buf->b_p_eol) 911 return TRUE; 912 if (!buf->b_p_bin && buf->b_start_bomb != buf->b_p_bomb) 913 return TRUE; 914 if (buf->b_start_fenc == NULL) 915 return (*buf->b_p_fenc != NUL); 916 return (STRCMP(buf->b_start_fenc, buf->b_p_fenc) != 0); 917 } 918 919 /* 920 * Insert string "p" at the cursor position. Stops at a NUL byte. 921 * Handles Replace mode and multi-byte characters. 922 */ 923 void 924 ins_bytes(char_u *p) 925 { 926 ins_bytes_len(p, (int)STRLEN(p)); 927 } 928 929 /* 930 * Insert string "p" with length "len" at the cursor position. 931 * Handles Replace mode and multi-byte characters. 932 */ 933 void 934 ins_bytes_len(char_u *p, int len) 935 { 936 int i; 937 int n; 938 939 if (has_mbyte) 940 for (i = 0; i < len; i += n) 941 { 942 if (enc_utf8) 943 // avoid reading past p[len] 944 n = utfc_ptr2len_len(p + i, len - i); 945 else 946 n = (*mb_ptr2len)(p + i); 947 ins_char_bytes(p + i, n); 948 } 949 else 950 for (i = 0; i < len; ++i) 951 ins_char(p[i]); 952 } 953 954 /* 955 * Insert or replace a single character at the cursor position. 956 * When in REPLACE or VREPLACE mode, replace any existing character. 957 * Caller must have prepared for undo. 958 * For multi-byte characters we get the whole character, the caller must 959 * convert bytes to a character. 960 */ 961 void 962 ins_char(int c) 963 { 964 char_u buf[MB_MAXBYTES + 1]; 965 int n = (*mb_char2bytes)(c, buf); 966 967 // When "c" is 0x100, 0x200, etc. we don't want to insert a NUL byte. 968 // Happens for CTRL-Vu9900. 969 if (buf[0] == 0) 970 buf[0] = '\n'; 971 972 ins_char_bytes(buf, n); 973 } 974 975 void 976 ins_char_bytes(char_u *buf, int charlen) 977 { 978 int c = buf[0]; 979 int newlen; // nr of bytes inserted 980 int oldlen; // nr of bytes deleted (0 when not replacing) 981 char_u *p; 982 char_u *newp; 983 char_u *oldp; 984 int linelen; // length of old line including NUL 985 colnr_T col; 986 linenr_T lnum = curwin->w_cursor.lnum; 987 int i; 988 989 // Break tabs if needed. 990 if (virtual_active() && curwin->w_cursor.coladd > 0) 991 coladvance_force(getviscol()); 992 993 col = curwin->w_cursor.col; 994 oldp = ml_get(lnum); 995 linelen = (int)STRLEN(oldp) + 1; 996 997 // The lengths default to the values for when not replacing. 998 oldlen = 0; 999 newlen = charlen; 1000 1001 if (State & REPLACE_FLAG) 1002 { 1003 if (State & VREPLACE_FLAG) 1004 { 1005 colnr_T new_vcol = 0; // init for GCC 1006 colnr_T vcol; 1007 int old_list; 1008 1009 // Disable 'list' temporarily, unless 'cpo' contains the 'L' flag. 1010 // Returns the old value of list, so when finished, 1011 // curwin->w_p_list should be set back to this. 1012 old_list = curwin->w_p_list; 1013 if (old_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL) 1014 curwin->w_p_list = FALSE; 1015 1016 // In virtual replace mode each character may replace one or more 1017 // characters (zero if it's a TAB). Count the number of bytes to 1018 // be deleted to make room for the new character, counting screen 1019 // cells. May result in adding spaces to fill a gap. 1020 getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL); 1021 new_vcol = vcol + chartabsize(buf, vcol); 1022 while (oldp[col + oldlen] != NUL && vcol < new_vcol) 1023 { 1024 vcol += chartabsize(oldp + col + oldlen, vcol); 1025 // Don't need to remove a TAB that takes us to the right 1026 // position. 1027 if (vcol > new_vcol && oldp[col + oldlen] == TAB) 1028 break; 1029 oldlen += (*mb_ptr2len)(oldp + col + oldlen); 1030 // Deleted a bit too much, insert spaces. 1031 if (vcol > new_vcol) 1032 newlen += vcol - new_vcol; 1033 } 1034 curwin->w_p_list = old_list; 1035 } 1036 else if (oldp[col] != NUL) 1037 { 1038 // normal replace 1039 oldlen = (*mb_ptr2len)(oldp + col); 1040 } 1041 1042 1043 // Push the replaced bytes onto the replace stack, so that they can be 1044 // put back when BS is used. The bytes of a multi-byte character are 1045 // done the other way around, so that the first byte is popped off 1046 // first (it tells the byte length of the character). 1047 replace_push(NUL); 1048 for (i = 0; i < oldlen; ++i) 1049 { 1050 if (has_mbyte) 1051 i += replace_push_mb(oldp + col + i) - 1; 1052 else 1053 replace_push(oldp[col + i]); 1054 } 1055 } 1056 1057 newp = alloc(linelen + newlen - oldlen); 1058 if (newp == NULL) 1059 return; 1060 1061 // Copy bytes before the cursor. 1062 if (col > 0) 1063 mch_memmove(newp, oldp, (size_t)col); 1064 1065 // Copy bytes after the changed character(s). 1066 p = newp + col; 1067 if (linelen > col + oldlen) 1068 mch_memmove(p + newlen, oldp + col + oldlen, 1069 (size_t)(linelen - col - oldlen)); 1070 1071 // Insert or overwrite the new character. 1072 mch_memmove(p, buf, charlen); 1073 i = charlen; 1074 1075 // Fill with spaces when necessary. 1076 while (i < newlen) 1077 p[i++] = ' '; 1078 1079 // Replace the line in the buffer. 1080 ml_replace(lnum, newp, FALSE); 1081 1082 // mark the buffer as changed and prepare for displaying 1083 inserted_bytes(lnum, col, newlen - oldlen); 1084 1085 // If we're in Insert or Replace mode and 'showmatch' is set, then briefly 1086 // show the match for right parens and braces. 1087 if (p_sm && (State & INSERT) 1088 && msg_silent == 0 1089 && !ins_compl_active()) 1090 { 1091 if (has_mbyte) 1092 showmatch(mb_ptr2char(buf)); 1093 else 1094 showmatch(c); 1095 } 1096 1097 #ifdef FEAT_RIGHTLEFT 1098 if (!p_ri || (State & REPLACE_FLAG)) 1099 #endif 1100 { 1101 // Normal insert: move cursor right 1102 curwin->w_cursor.col += charlen; 1103 } 1104 1105 // TODO: should try to update w_row here, to avoid recomputing it later. 1106 } 1107 1108 /* 1109 * Insert a string at the cursor position. 1110 * Note: Does NOT handle Replace mode. 1111 * Caller must have prepared for undo. 1112 */ 1113 void 1114 ins_str(char_u *s) 1115 { 1116 char_u *oldp, *newp; 1117 int newlen = (int)STRLEN(s); 1118 int oldlen; 1119 colnr_T col; 1120 linenr_T lnum = curwin->w_cursor.lnum; 1121 1122 if (virtual_active() && curwin->w_cursor.coladd > 0) 1123 coladvance_force(getviscol()); 1124 1125 col = curwin->w_cursor.col; 1126 oldp = ml_get(lnum); 1127 oldlen = (int)STRLEN(oldp); 1128 1129 newp = alloc(oldlen + newlen + 1); 1130 if (newp == NULL) 1131 return; 1132 if (col > 0) 1133 mch_memmove(newp, oldp, (size_t)col); 1134 mch_memmove(newp + col, s, (size_t)newlen); 1135 mch_memmove(newp + col + newlen, oldp + col, (size_t)(oldlen - col + 1)); 1136 ml_replace(lnum, newp, FALSE); 1137 inserted_bytes(lnum, col, newlen); 1138 curwin->w_cursor.col += newlen; 1139 } 1140 1141 /* 1142 * Delete one character under the cursor. 1143 * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line. 1144 * Caller must have prepared for undo. 1145 * 1146 * return FAIL for failure, OK otherwise 1147 */ 1148 int 1149 del_char(int fixpos) 1150 { 1151 if (has_mbyte) 1152 { 1153 // Make sure the cursor is at the start of a character. 1154 mb_adjust_cursor(); 1155 if (*ml_get_cursor() == NUL) 1156 return FAIL; 1157 return del_chars(1L, fixpos); 1158 } 1159 return del_bytes(1L, fixpos, TRUE); 1160 } 1161 1162 /* 1163 * Like del_bytes(), but delete characters instead of bytes. 1164 */ 1165 int 1166 del_chars(long count, int fixpos) 1167 { 1168 long bytes = 0; 1169 long i; 1170 char_u *p; 1171 int l; 1172 1173 p = ml_get_cursor(); 1174 for (i = 0; i < count && *p != NUL; ++i) 1175 { 1176 l = (*mb_ptr2len)(p); 1177 bytes += l; 1178 p += l; 1179 } 1180 return del_bytes(bytes, fixpos, TRUE); 1181 } 1182 1183 /* 1184 * Delete "count" bytes under the cursor. 1185 * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line. 1186 * Caller must have prepared for undo. 1187 * 1188 * Return FAIL for failure, OK otherwise. 1189 */ 1190 int 1191 del_bytes( 1192 long count, 1193 int fixpos_arg, 1194 int use_delcombine UNUSED) // 'delcombine' option applies 1195 { 1196 char_u *oldp, *newp; 1197 colnr_T oldlen; 1198 colnr_T newlen; 1199 linenr_T lnum = curwin->w_cursor.lnum; 1200 colnr_T col = curwin->w_cursor.col; 1201 int alloc_newp; 1202 long movelen; 1203 int fixpos = fixpos_arg; 1204 1205 oldp = ml_get(lnum); 1206 oldlen = (int)STRLEN(oldp); 1207 1208 // Can't do anything when the cursor is on the NUL after the line. 1209 if (col >= oldlen) 1210 return FAIL; 1211 1212 // If "count" is zero there is nothing to do. 1213 if (count == 0) 1214 return OK; 1215 1216 // If "count" is negative the caller must be doing something wrong. 1217 if (count < 1) 1218 { 1219 siemsg("E292: Invalid count for del_bytes(): %ld", count); 1220 return FAIL; 1221 } 1222 1223 // If 'delcombine' is set and deleting (less than) one character, only 1224 // delete the last combining character. 1225 if (p_deco && use_delcombine && enc_utf8 1226 && utfc_ptr2len(oldp + col) >= count) 1227 { 1228 int cc[MAX_MCO]; 1229 int n; 1230 1231 (void)utfc_ptr2char(oldp + col, cc); 1232 if (cc[0] != NUL) 1233 { 1234 // Find the last composing char, there can be several. 1235 n = col; 1236 do 1237 { 1238 col = n; 1239 count = utf_ptr2len(oldp + n); 1240 n += count; 1241 } while (UTF_COMPOSINGLIKE(oldp + col, oldp + n)); 1242 fixpos = 0; 1243 } 1244 } 1245 1246 // When count is too big, reduce it. 1247 movelen = (long)oldlen - (long)col - count + 1; // includes trailing NUL 1248 if (movelen <= 1) 1249 { 1250 // If we just took off the last character of a non-blank line, and 1251 // fixpos is TRUE, we don't want to end up positioned at the NUL, 1252 // unless "restart_edit" is set or 'virtualedit' contains "onemore". 1253 if (col > 0 && fixpos && restart_edit == 0 1254 && (ve_flags & VE_ONEMORE) == 0) 1255 { 1256 --curwin->w_cursor.col; 1257 curwin->w_cursor.coladd = 0; 1258 if (has_mbyte) 1259 curwin->w_cursor.col -= 1260 (*mb_head_off)(oldp, oldp + curwin->w_cursor.col); 1261 } 1262 count = oldlen - col; 1263 movelen = 1; 1264 } 1265 newlen = oldlen - count; 1266 1267 // If the old line has been allocated the deletion can be done in the 1268 // existing line. Otherwise a new line has to be allocated 1269 // Can't do this when using Netbeans, because we would need to invoke 1270 // netbeans_removed(), which deallocates the line. Let ml_replace() take 1271 // care of notifying Netbeans. 1272 #ifdef FEAT_NETBEANS_INTG 1273 if (netbeans_active()) 1274 alloc_newp = TRUE; 1275 else 1276 #endif 1277 alloc_newp = !ml_line_alloced(); // check if oldp was allocated 1278 if (!alloc_newp) 1279 newp = oldp; // use same allocated memory 1280 else 1281 { // need to allocate a new line 1282 newp = alloc(newlen + 1); 1283 if (newp == NULL) 1284 return FAIL; 1285 mch_memmove(newp, oldp, (size_t)col); 1286 } 1287 mch_memmove(newp + col, oldp + col + count, (size_t)movelen); 1288 if (alloc_newp) 1289 ml_replace(lnum, newp, FALSE); 1290 #ifdef FEAT_PROP_POPUP 1291 else 1292 { 1293 // Also move any following text properties. 1294 if (oldlen + 1 < curbuf->b_ml.ml_line_len) 1295 mch_memmove(newp + newlen + 1, oldp + oldlen + 1, 1296 (size_t)curbuf->b_ml.ml_line_len - oldlen - 1); 1297 curbuf->b_ml.ml_line_len -= count; 1298 } 1299 #endif 1300 1301 // mark the buffer as changed and prepare for displaying 1302 inserted_bytes(lnum, col, -count); 1303 1304 return OK; 1305 } 1306 1307 /* 1308 * open_line: Add a new line below or above the current line. 1309 * 1310 * For VREPLACE mode, we only add a new line when we get to the end of the 1311 * file, otherwise we just start replacing the next line. 1312 * 1313 * Caller must take care of undo. Since VREPLACE may affect any number of 1314 * lines however, it may call u_save_cursor() again when starting to change a 1315 * new line. 1316 * "flags": OPENLINE_DELSPACES delete spaces after cursor 1317 * OPENLINE_DO_COM format comments 1318 * OPENLINE_KEEPTRAIL keep trailing spaces 1319 * OPENLINE_MARKFIX adjust mark positions after the line break 1320 * OPENLINE_COM_LIST format comments with list or 2nd line indent 1321 * 1322 * "second_line_indent": indent for after ^^D in Insert mode or if flag 1323 * OPENLINE_COM_LIST 1324 * 1325 * Return OK for success, FAIL for failure 1326 */ 1327 int 1328 open_line( 1329 int dir, // FORWARD or BACKWARD 1330 int flags, 1331 int second_line_indent) 1332 { 1333 char_u *saved_line; // copy of the original line 1334 char_u *next_line = NULL; // copy of the next line 1335 char_u *p_extra = NULL; // what goes to next line 1336 int less_cols = 0; // less columns for mark in new line 1337 int less_cols_off = 0; // columns to skip for mark adjust 1338 pos_T old_cursor; // old cursor position 1339 int newcol = 0; // new cursor column 1340 int newindent = 0; // auto-indent of the new line 1341 int n; 1342 int trunc_line = FALSE; // truncate current line afterwards 1343 int retval = FAIL; // return value 1344 int extra_len = 0; // length of p_extra string 1345 int lead_len; // length of comment leader 1346 char_u *lead_flags; // position in 'comments' for comment leader 1347 char_u *leader = NULL; // copy of comment leader 1348 char_u *allocated = NULL; // allocated memory 1349 char_u *p; 1350 int saved_char = NUL; // init for GCC 1351 pos_T *pos; 1352 #ifdef FEAT_SMARTINDENT 1353 int do_si = (!p_paste && curbuf->b_p_si 1354 # ifdef FEAT_CINDENT 1355 && !curbuf->b_p_cin 1356 # endif 1357 # ifdef FEAT_EVAL 1358 && *curbuf->b_p_inde == NUL 1359 # endif 1360 ); 1361 int no_si = FALSE; // reset did_si afterwards 1362 int first_char = NUL; // init for GCC 1363 #endif 1364 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) 1365 int vreplace_mode; 1366 #endif 1367 int did_append; // appended a new line 1368 int saved_pi = curbuf->b_p_pi; // copy of preserveindent setting 1369 1370 // make a copy of the current line so we can mess with it 1371 saved_line = vim_strsave(ml_get_curline()); 1372 if (saved_line == NULL) // out of memory! 1373 return FALSE; 1374 1375 if (State & VREPLACE_FLAG) 1376 { 1377 // With VREPLACE we make a copy of the next line, which we will be 1378 // starting to replace. First make the new line empty and let vim play 1379 // with the indenting and comment leader to its heart's content. Then 1380 // we grab what it ended up putting on the new line, put back the 1381 // original line, and call ins_char() to put each new character onto 1382 // the line, replacing what was there before and pushing the right 1383 // stuff onto the replace stack. -- webb. 1384 if (curwin->w_cursor.lnum < orig_line_count) 1385 next_line = vim_strsave(ml_get(curwin->w_cursor.lnum + 1)); 1386 else 1387 next_line = vim_strsave((char_u *)""); 1388 if (next_line == NULL) // out of memory! 1389 goto theend; 1390 1391 // In VREPLACE mode, a NL replaces the rest of the line, and starts 1392 // replacing the next line, so push all of the characters left on the 1393 // line onto the replace stack. We'll push any other characters that 1394 // might be replaced at the start of the next line (due to autoindent 1395 // etc) a bit later. 1396 replace_push(NUL); // Call twice because BS over NL expects it 1397 replace_push(NUL); 1398 p = saved_line + curwin->w_cursor.col; 1399 while (*p != NUL) 1400 { 1401 if (has_mbyte) 1402 p += replace_push_mb(p); 1403 else 1404 replace_push(*p++); 1405 } 1406 saved_line[curwin->w_cursor.col] = NUL; 1407 } 1408 1409 if ((State & INSERT) && !(State & VREPLACE_FLAG)) 1410 { 1411 p_extra = saved_line + curwin->w_cursor.col; 1412 #ifdef FEAT_SMARTINDENT 1413 if (do_si) // need first char after new line break 1414 { 1415 p = skipwhite(p_extra); 1416 first_char = *p; 1417 } 1418 #endif 1419 extra_len = (int)STRLEN(p_extra); 1420 saved_char = *p_extra; 1421 *p_extra = NUL; 1422 } 1423 1424 u_clearline(); // cannot do "U" command when adding lines 1425 #ifdef FEAT_SMARTINDENT 1426 did_si = FALSE; 1427 #endif 1428 ai_col = 0; 1429 1430 // If we just did an auto-indent, then we didn't type anything on 1431 // the prior line, and it should be truncated. Do this even if 'ai' is not 1432 // set because automatically inserting a comment leader also sets did_ai. 1433 if (dir == FORWARD && did_ai) 1434 trunc_line = TRUE; 1435 1436 // If 'autoindent' and/or 'smartindent' is set, try to figure out what 1437 // indent to use for the new line. 1438 if (curbuf->b_p_ai 1439 #ifdef FEAT_SMARTINDENT 1440 || do_si 1441 #endif 1442 ) 1443 { 1444 // count white space on current line 1445 #ifdef FEAT_VARTABS 1446 newindent = get_indent_str_vtab(saved_line, curbuf->b_p_ts, 1447 curbuf->b_p_vts_array, FALSE); 1448 #else 1449 newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts, FALSE); 1450 #endif 1451 if (newindent == 0 && !(flags & OPENLINE_COM_LIST)) 1452 newindent = second_line_indent; // for ^^D command in insert mode 1453 1454 #ifdef FEAT_SMARTINDENT 1455 // Do smart indenting. 1456 // In insert/replace mode (only when dir == FORWARD) 1457 // we may move some text to the next line. If it starts with '{' 1458 // don't add an indent. Fixes inserting a NL before '{' in line 1459 // "if (condition) {" 1460 if (!trunc_line && do_si && *saved_line != NUL 1461 && (p_extra == NULL || first_char != '{')) 1462 { 1463 char_u *ptr; 1464 char_u last_char; 1465 1466 old_cursor = curwin->w_cursor; 1467 ptr = saved_line; 1468 if (flags & OPENLINE_DO_COM) 1469 lead_len = get_leader_len(ptr, NULL, FALSE, TRUE); 1470 else 1471 lead_len = 0; 1472 if (dir == FORWARD) 1473 { 1474 // Skip preprocessor directives, unless they are 1475 // recognised as comments. 1476 if ( lead_len == 0 && ptr[0] == '#') 1477 { 1478 while (ptr[0] == '#' && curwin->w_cursor.lnum > 1) 1479 ptr = ml_get(--curwin->w_cursor.lnum); 1480 newindent = get_indent(); 1481 } 1482 if (flags & OPENLINE_DO_COM) 1483 lead_len = get_leader_len(ptr, NULL, FALSE, TRUE); 1484 else 1485 lead_len = 0; 1486 if (lead_len > 0) 1487 { 1488 // This case gets the following right: 1489 // /* 1490 // * A comment (read '\' as '/'). 1491 // */ 1492 // #define IN_THE_WAY 1493 // This should line up here; 1494 p = skipwhite(ptr); 1495 if (p[0] == '/' && p[1] == '*') 1496 p++; 1497 if (p[0] == '*') 1498 { 1499 for (p++; *p; p++) 1500 { 1501 if (p[0] == '/' && p[-1] == '*') 1502 { 1503 // End of C comment, indent should line up 1504 // with the line containing the start of 1505 // the comment 1506 curwin->w_cursor.col = (colnr_T)(p - ptr); 1507 if ((pos = findmatch(NULL, NUL)) != NULL) 1508 { 1509 curwin->w_cursor.lnum = pos->lnum; 1510 newindent = get_indent(); 1511 } 1512 } 1513 } 1514 } 1515 } 1516 else // Not a comment line 1517 { 1518 // Find last non-blank in line 1519 p = ptr + STRLEN(ptr) - 1; 1520 while (p > ptr && VIM_ISWHITE(*p)) 1521 --p; 1522 last_char = *p; 1523 1524 // find the character just before the '{' or ';' 1525 if (last_char == '{' || last_char == ';') 1526 { 1527 if (p > ptr) 1528 --p; 1529 while (p > ptr && VIM_ISWHITE(*p)) 1530 --p; 1531 } 1532 // Try to catch lines that are split over multiple 1533 // lines. eg: 1534 // if (condition && 1535 // condition) { 1536 // Should line up here! 1537 // } 1538 if (*p == ')') 1539 { 1540 curwin->w_cursor.col = (colnr_T)(p - ptr); 1541 if ((pos = findmatch(NULL, '(')) != NULL) 1542 { 1543 curwin->w_cursor.lnum = pos->lnum; 1544 newindent = get_indent(); 1545 ptr = ml_get_curline(); 1546 } 1547 } 1548 // If last character is '{' do indent, without 1549 // checking for "if" and the like. 1550 if (last_char == '{') 1551 { 1552 did_si = TRUE; // do indent 1553 no_si = TRUE; // don't delete it when '{' typed 1554 } 1555 // Look for "if" and the like, use 'cinwords'. 1556 // Don't do this if the previous line ended in ';' or 1557 // '}'. 1558 else if (last_char != ';' && last_char != '}' 1559 && cin_is_cinword(ptr)) 1560 did_si = TRUE; 1561 } 1562 } 1563 else // dir == BACKWARD 1564 { 1565 // Skip preprocessor directives, unless they are 1566 // recognised as comments. 1567 if (lead_len == 0 && ptr[0] == '#') 1568 { 1569 int was_backslashed = FALSE; 1570 1571 while ((ptr[0] == '#' || was_backslashed) && 1572 curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) 1573 { 1574 if (*ptr && ptr[STRLEN(ptr) - 1] == '\\') 1575 was_backslashed = TRUE; 1576 else 1577 was_backslashed = FALSE; 1578 ptr = ml_get(++curwin->w_cursor.lnum); 1579 } 1580 if (was_backslashed) 1581 newindent = 0; // Got to end of file 1582 else 1583 newindent = get_indent(); 1584 } 1585 p = skipwhite(ptr); 1586 if (*p == '}') // if line starts with '}': do indent 1587 did_si = TRUE; 1588 else // can delete indent when '{' typed 1589 can_si_back = TRUE; 1590 } 1591 curwin->w_cursor = old_cursor; 1592 } 1593 if (do_si) 1594 can_si = TRUE; 1595 #endif // FEAT_SMARTINDENT 1596 1597 did_ai = TRUE; 1598 } 1599 1600 // Find out if the current line starts with a comment leader. 1601 // This may then be inserted in front of the new line. 1602 end_comment_pending = NUL; 1603 if (flags & OPENLINE_DO_COM) 1604 lead_len = get_leader_len(saved_line, &lead_flags, 1605 dir == BACKWARD, TRUE); 1606 else 1607 lead_len = 0; 1608 if (lead_len > 0) 1609 { 1610 char_u *lead_repl = NULL; // replaces comment leader 1611 int lead_repl_len = 0; // length of *lead_repl 1612 char_u lead_middle[COM_MAX_LEN]; // middle-comment string 1613 char_u lead_end[COM_MAX_LEN]; // end-comment string 1614 char_u *comment_end = NULL; // where lead_end has been found 1615 int extra_space = FALSE; // append extra space 1616 int current_flag; 1617 int require_blank = FALSE; // requires blank after middle 1618 char_u *p2; 1619 1620 // If the comment leader has the start, middle or end flag, it may not 1621 // be used or may be replaced with the middle leader. 1622 for (p = lead_flags; *p && *p != ':'; ++p) 1623 { 1624 if (*p == COM_BLANK) 1625 { 1626 require_blank = TRUE; 1627 continue; 1628 } 1629 if (*p == COM_START || *p == COM_MIDDLE) 1630 { 1631 current_flag = *p; 1632 if (*p == COM_START) 1633 { 1634 // Doing "O" on a start of comment does not insert leader. 1635 if (dir == BACKWARD) 1636 { 1637 lead_len = 0; 1638 break; 1639 } 1640 1641 // find start of middle part 1642 (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ","); 1643 require_blank = FALSE; 1644 } 1645 1646 // Isolate the strings of the middle and end leader. 1647 while (*p && p[-1] != ':') // find end of middle flags 1648 { 1649 if (*p == COM_BLANK) 1650 require_blank = TRUE; 1651 ++p; 1652 } 1653 (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ","); 1654 1655 while (*p && p[-1] != ':') // find end of end flags 1656 { 1657 // Check whether we allow automatic ending of comments 1658 if (*p == COM_AUTO_END) 1659 end_comment_pending = -1; // means we want to set it 1660 ++p; 1661 } 1662 n = copy_option_part(&p, lead_end, COM_MAX_LEN, ","); 1663 1664 if (end_comment_pending == -1) // we can set it now 1665 end_comment_pending = lead_end[n - 1]; 1666 1667 // If the end of the comment is in the same line, don't use 1668 // the comment leader. 1669 if (dir == FORWARD) 1670 { 1671 for (p = saved_line + lead_len; *p; ++p) 1672 if (STRNCMP(p, lead_end, n) == 0) 1673 { 1674 comment_end = p; 1675 lead_len = 0; 1676 break; 1677 } 1678 } 1679 1680 // Doing "o" on a start of comment inserts the middle leader. 1681 if (lead_len > 0) 1682 { 1683 if (current_flag == COM_START) 1684 { 1685 lead_repl = lead_middle; 1686 lead_repl_len = (int)STRLEN(lead_middle); 1687 } 1688 1689 // If we have hit RETURN immediately after the start 1690 // comment leader, then put a space after the middle 1691 // comment leader on the next line. 1692 if (!VIM_ISWHITE(saved_line[lead_len - 1]) 1693 && ((p_extra != NULL 1694 && (int)curwin->w_cursor.col == lead_len) 1695 || (p_extra == NULL 1696 && saved_line[lead_len] == NUL) 1697 || require_blank)) 1698 extra_space = TRUE; 1699 } 1700 break; 1701 } 1702 if (*p == COM_END) 1703 { 1704 // Doing "o" on the end of a comment does not insert leader. 1705 // Remember where the end is, might want to use it to find the 1706 // start (for C-comments). 1707 if (dir == FORWARD) 1708 { 1709 comment_end = skipwhite(saved_line); 1710 lead_len = 0; 1711 break; 1712 } 1713 1714 // Doing "O" on the end of a comment inserts the middle leader. 1715 // Find the string for the middle leader, searching backwards. 1716 while (p > curbuf->b_p_com && *p != ',') 1717 --p; 1718 for (lead_repl = p; lead_repl > curbuf->b_p_com 1719 && lead_repl[-1] != ':'; --lead_repl) 1720 ; 1721 lead_repl_len = (int)(p - lead_repl); 1722 1723 // We can probably always add an extra space when doing "O" on 1724 // the comment-end 1725 extra_space = TRUE; 1726 1727 // Check whether we allow automatic ending of comments 1728 for (p2 = p; *p2 && *p2 != ':'; p2++) 1729 { 1730 if (*p2 == COM_AUTO_END) 1731 end_comment_pending = -1; // means we want to set it 1732 } 1733 if (end_comment_pending == -1) 1734 { 1735 // Find last character in end-comment string 1736 while (*p2 && *p2 != ',') 1737 p2++; 1738 end_comment_pending = p2[-1]; 1739 } 1740 break; 1741 } 1742 if (*p == COM_FIRST) 1743 { 1744 // Comment leader for first line only: Don't repeat leader 1745 // when using "O", blank out leader when using "o". 1746 if (dir == BACKWARD) 1747 lead_len = 0; 1748 else 1749 { 1750 lead_repl = (char_u *)""; 1751 lead_repl_len = 0; 1752 } 1753 break; 1754 } 1755 } 1756 if (lead_len) 1757 { 1758 // allocate buffer (may concatenate p_extra later) 1759 leader = alloc(lead_len + lead_repl_len + extra_space + extra_len 1760 + (second_line_indent > 0 ? second_line_indent : 0) + 1); 1761 allocated = leader; // remember to free it later 1762 1763 if (leader == NULL) 1764 lead_len = 0; 1765 else 1766 { 1767 vim_strncpy(leader, saved_line, lead_len); 1768 1769 // Replace leader with lead_repl, right or left adjusted 1770 if (lead_repl != NULL) 1771 { 1772 int c = 0; 1773 int off = 0; 1774 1775 for (p = lead_flags; *p != NUL && *p != ':'; ) 1776 { 1777 if (*p == COM_RIGHT || *p == COM_LEFT) 1778 c = *p++; 1779 else if (VIM_ISDIGIT(*p) || *p == '-') 1780 off = getdigits(&p); 1781 else 1782 ++p; 1783 } 1784 if (c == COM_RIGHT) // right adjusted leader 1785 { 1786 // find last non-white in the leader to line up with 1787 for (p = leader + lead_len - 1; p > leader 1788 && VIM_ISWHITE(*p); --p) 1789 ; 1790 ++p; 1791 1792 // Compute the length of the replaced characters in 1793 // screen characters, not bytes. 1794 { 1795 int repl_size = vim_strnsize(lead_repl, 1796 lead_repl_len); 1797 int old_size = 0; 1798 char_u *endp = p; 1799 int l; 1800 1801 while (old_size < repl_size && p > leader) 1802 { 1803 MB_PTR_BACK(leader, p); 1804 old_size += ptr2cells(p); 1805 } 1806 l = lead_repl_len - (int)(endp - p); 1807 if (l != 0) 1808 mch_memmove(endp + l, endp, 1809 (size_t)((leader + lead_len) - endp)); 1810 lead_len += l; 1811 } 1812 mch_memmove(p, lead_repl, (size_t)lead_repl_len); 1813 if (p + lead_repl_len > leader + lead_len) 1814 p[lead_repl_len] = NUL; 1815 1816 // blank-out any other chars from the old leader. 1817 while (--p >= leader) 1818 { 1819 int l = mb_head_off(leader, p); 1820 1821 if (l > 1) 1822 { 1823 p -= l; 1824 if (ptr2cells(p) > 1) 1825 { 1826 p[1] = ' '; 1827 --l; 1828 } 1829 mch_memmove(p + 1, p + l + 1, 1830 (size_t)((leader + lead_len) - (p + l + 1))); 1831 lead_len -= l; 1832 *p = ' '; 1833 } 1834 else if (!VIM_ISWHITE(*p)) 1835 *p = ' '; 1836 } 1837 } 1838 else // left adjusted leader 1839 { 1840 p = skipwhite(leader); 1841 1842 // Compute the length of the replaced characters in 1843 // screen characters, not bytes. Move the part that is 1844 // not to be overwritten. 1845 { 1846 int repl_size = vim_strnsize(lead_repl, 1847 lead_repl_len); 1848 int i; 1849 int l; 1850 1851 for (i = 0; i < lead_len && p[i] != NUL; i += l) 1852 { 1853 l = (*mb_ptr2len)(p + i); 1854 if (vim_strnsize(p, i + l) > repl_size) 1855 break; 1856 } 1857 if (i != lead_repl_len) 1858 { 1859 mch_memmove(p + lead_repl_len, p + i, 1860 (size_t)(lead_len - i - (p - leader))); 1861 lead_len += lead_repl_len - i; 1862 } 1863 } 1864 mch_memmove(p, lead_repl, (size_t)lead_repl_len); 1865 1866 // Replace any remaining non-white chars in the old 1867 // leader by spaces. Keep Tabs, the indent must 1868 // remain the same. 1869 for (p += lead_repl_len; p < leader + lead_len; ++p) 1870 if (!VIM_ISWHITE(*p)) 1871 { 1872 // Don't put a space before a TAB. 1873 if (p + 1 < leader + lead_len && p[1] == TAB) 1874 { 1875 --lead_len; 1876 mch_memmove(p, p + 1, 1877 (leader + lead_len) - p); 1878 } 1879 else 1880 { 1881 int l = (*mb_ptr2len)(p); 1882 1883 if (l > 1) 1884 { 1885 if (ptr2cells(p) > 1) 1886 { 1887 // Replace a double-wide char with 1888 // two spaces 1889 --l; 1890 *p++ = ' '; 1891 } 1892 mch_memmove(p + 1, p + l, 1893 (leader + lead_len) - p); 1894 lead_len -= l - 1; 1895 } 1896 *p = ' '; 1897 } 1898 } 1899 *p = NUL; 1900 } 1901 1902 // Recompute the indent, it may have changed. 1903 if (curbuf->b_p_ai 1904 #ifdef FEAT_SMARTINDENT 1905 || do_si 1906 #endif 1907 ) 1908 #ifdef FEAT_VARTABS 1909 newindent = get_indent_str_vtab(leader, curbuf->b_p_ts, 1910 curbuf->b_p_vts_array, FALSE); 1911 #else 1912 newindent = get_indent_str(leader, 1913 (int)curbuf->b_p_ts, FALSE); 1914 #endif 1915 1916 // Add the indent offset 1917 if (newindent + off < 0) 1918 { 1919 off = -newindent; 1920 newindent = 0; 1921 } 1922 else 1923 newindent += off; 1924 1925 // Correct trailing spaces for the shift, so that 1926 // alignment remains equal. 1927 while (off > 0 && lead_len > 0 1928 && leader[lead_len - 1] == ' ') 1929 { 1930 // Don't do it when there is a tab before the space 1931 if (vim_strchr(skipwhite(leader), '\t') != NULL) 1932 break; 1933 --lead_len; 1934 --off; 1935 } 1936 1937 // If the leader ends in white space, don't add an 1938 // extra space 1939 if (lead_len > 0 && VIM_ISWHITE(leader[lead_len - 1])) 1940 extra_space = FALSE; 1941 leader[lead_len] = NUL; 1942 } 1943 1944 if (extra_space) 1945 { 1946 leader[lead_len++] = ' '; 1947 leader[lead_len] = NUL; 1948 } 1949 1950 newcol = lead_len; 1951 1952 // if a new indent will be set below, remove the indent that 1953 // is in the comment leader 1954 if (newindent 1955 #ifdef FEAT_SMARTINDENT 1956 || did_si 1957 #endif 1958 ) 1959 { 1960 while (lead_len && VIM_ISWHITE(*leader)) 1961 { 1962 --lead_len; 1963 --newcol; 1964 ++leader; 1965 } 1966 } 1967 1968 } 1969 #ifdef FEAT_SMARTINDENT 1970 did_si = can_si = FALSE; 1971 #endif 1972 } 1973 else if (comment_end != NULL) 1974 { 1975 // We have finished a comment, so we don't use the leader. 1976 // If this was a C-comment and 'ai' or 'si' is set do a normal 1977 // indent to align with the line containing the start of the 1978 // comment. 1979 if (comment_end[0] == '*' && comment_end[1] == '/' && 1980 (curbuf->b_p_ai 1981 #ifdef FEAT_SMARTINDENT 1982 || do_si 1983 #endif 1984 )) 1985 { 1986 old_cursor = curwin->w_cursor; 1987 curwin->w_cursor.col = (colnr_T)(comment_end - saved_line); 1988 if ((pos = findmatch(NULL, NUL)) != NULL) 1989 { 1990 curwin->w_cursor.lnum = pos->lnum; 1991 newindent = get_indent(); 1992 } 1993 curwin->w_cursor = old_cursor; 1994 } 1995 } 1996 } 1997 1998 // (State == INSERT || State == REPLACE), only when dir == FORWARD 1999 if (p_extra != NULL) 2000 { 2001 *p_extra = saved_char; // restore char that NUL replaced 2002 2003 // When 'ai' set or "flags" has OPENLINE_DELSPACES, skip to the first 2004 // non-blank. 2005 // 2006 // When in REPLACE mode, put the deleted blanks on the replace stack, 2007 // preceded by a NUL, so they can be put back when a BS is entered. 2008 if (REPLACE_NORMAL(State)) 2009 replace_push(NUL); // end of extra blanks 2010 if (curbuf->b_p_ai || (flags & OPENLINE_DELSPACES)) 2011 { 2012 while ((*p_extra == ' ' || *p_extra == '\t') 2013 && (!enc_utf8 2014 || !utf_iscomposing(utf_ptr2char(p_extra + 1)))) 2015 { 2016 if (REPLACE_NORMAL(State)) 2017 replace_push(*p_extra); 2018 ++p_extra; 2019 ++less_cols_off; 2020 } 2021 } 2022 2023 // columns for marks adjusted for removed columns 2024 less_cols = (int)(p_extra - saved_line); 2025 } 2026 2027 if (p_extra == NULL) 2028 p_extra = (char_u *)""; // append empty line 2029 2030 // concatenate leader and p_extra, if there is a leader 2031 if (lead_len) 2032 { 2033 if (flags & OPENLINE_COM_LIST && second_line_indent > 0) 2034 { 2035 int i; 2036 int padding = second_line_indent 2037 - (newindent + (int)STRLEN(leader)); 2038 2039 // Here whitespace is inserted after the comment char. 2040 // Below, set_indent(newindent, SIN_INSERT) will insert the 2041 // whitespace needed before the comment char. 2042 for (i = 0; i < padding; i++) 2043 { 2044 STRCAT(leader, " "); 2045 less_cols--; 2046 newcol++; 2047 } 2048 } 2049 STRCAT(leader, p_extra); 2050 p_extra = leader; 2051 did_ai = TRUE; // So truncating blanks works with comments 2052 less_cols -= lead_len; 2053 } 2054 else 2055 end_comment_pending = NUL; // turns out there was no leader 2056 2057 old_cursor = curwin->w_cursor; 2058 if (dir == BACKWARD) 2059 --curwin->w_cursor.lnum; 2060 if (!(State & VREPLACE_FLAG) || old_cursor.lnum >= orig_line_count) 2061 { 2062 if (ml_append(curwin->w_cursor.lnum, p_extra, (colnr_T)0, FALSE) 2063 == FAIL) 2064 goto theend; 2065 // Postpone calling changed_lines(), because it would mess up folding 2066 // with markers. 2067 // Skip mark_adjust when adding a line after the last one, there can't 2068 // be marks there. But still needed in diff mode. 2069 if (curwin->w_cursor.lnum + 1 < curbuf->b_ml.ml_line_count 2070 #ifdef FEAT_DIFF 2071 || curwin->w_p_diff 2072 #endif 2073 ) 2074 mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L); 2075 did_append = TRUE; 2076 #ifdef FEAT_PROP_POPUP 2077 if ((State & INSERT) && !(State & VREPLACE_FLAG)) 2078 // properties after the split move to the next line 2079 adjust_props_for_split(curwin->w_cursor.lnum, curwin->w_cursor.lnum, 2080 curwin->w_cursor.col + 1, 0); 2081 #endif 2082 } 2083 else 2084 { 2085 // In VREPLACE mode we are starting to replace the next line. 2086 curwin->w_cursor.lnum++; 2087 if (curwin->w_cursor.lnum >= Insstart.lnum + vr_lines_changed) 2088 { 2089 // In case we NL to a new line, BS to the previous one, and NL 2090 // again, we don't want to save the new line for undo twice. 2091 (void)u_save_cursor(); // errors are ignored! 2092 vr_lines_changed++; 2093 } 2094 ml_replace(curwin->w_cursor.lnum, p_extra, TRUE); 2095 changed_bytes(curwin->w_cursor.lnum, 0); 2096 curwin->w_cursor.lnum--; 2097 did_append = FALSE; 2098 } 2099 2100 if (newindent 2101 #ifdef FEAT_SMARTINDENT 2102 || did_si 2103 #endif 2104 ) 2105 { 2106 ++curwin->w_cursor.lnum; 2107 #ifdef FEAT_SMARTINDENT 2108 if (did_si) 2109 { 2110 int sw = (int)get_sw_value(curbuf); 2111 2112 if (p_sr) 2113 newindent -= newindent % sw; 2114 newindent += sw; 2115 } 2116 #endif 2117 // Copy the indent 2118 if (curbuf->b_p_ci) 2119 { 2120 (void)copy_indent(newindent, saved_line); 2121 2122 // Set the 'preserveindent' option so that any further screwing 2123 // with the line doesn't entirely destroy our efforts to preserve 2124 // it. It gets restored at the function end. 2125 curbuf->b_p_pi = TRUE; 2126 } 2127 else 2128 (void)set_indent(newindent, SIN_INSERT); 2129 less_cols -= curwin->w_cursor.col; 2130 2131 ai_col = curwin->w_cursor.col; 2132 2133 // In REPLACE mode, for each character in the new indent, there must 2134 // be a NUL on the replace stack, for when it is deleted with BS 2135 if (REPLACE_NORMAL(State)) 2136 for (n = 0; n < (int)curwin->w_cursor.col; ++n) 2137 replace_push(NUL); 2138 newcol += curwin->w_cursor.col; 2139 #ifdef FEAT_SMARTINDENT 2140 if (no_si) 2141 did_si = FALSE; 2142 #endif 2143 } 2144 2145 // In REPLACE mode, for each character in the extra leader, there must be 2146 // a NUL on the replace stack, for when it is deleted with BS. 2147 if (REPLACE_NORMAL(State)) 2148 while (lead_len-- > 0) 2149 replace_push(NUL); 2150 2151 curwin->w_cursor = old_cursor; 2152 2153 if (dir == FORWARD) 2154 { 2155 if (trunc_line || (State & INSERT)) 2156 { 2157 // truncate current line at cursor 2158 saved_line[curwin->w_cursor.col] = NUL; 2159 // Remove trailing white space, unless OPENLINE_KEEPTRAIL used. 2160 if (trunc_line && !(flags & OPENLINE_KEEPTRAIL)) 2161 truncate_spaces(saved_line); 2162 ml_replace(curwin->w_cursor.lnum, saved_line, FALSE); 2163 saved_line = NULL; 2164 if (did_append) 2165 { 2166 changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col, 2167 curwin->w_cursor.lnum + 1, 1L); 2168 did_append = FALSE; 2169 2170 // Move marks after the line break to the new line. 2171 if (flags & OPENLINE_MARKFIX) 2172 mark_col_adjust(curwin->w_cursor.lnum, 2173 curwin->w_cursor.col + less_cols_off, 2174 1L, (long)-less_cols, 0); 2175 } 2176 else 2177 changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); 2178 } 2179 2180 // Put the cursor on the new line. Careful: the scrollup() above may 2181 // have moved w_cursor, we must use old_cursor. 2182 curwin->w_cursor.lnum = old_cursor.lnum + 1; 2183 } 2184 if (did_append) 2185 changed_lines(curwin->w_cursor.lnum, 0, curwin->w_cursor.lnum, 1L); 2186 2187 curwin->w_cursor.col = newcol; 2188 curwin->w_cursor.coladd = 0; 2189 2190 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) 2191 // In VREPLACE mode, we are handling the replace stack ourselves, so stop 2192 // fixthisline() from doing it (via change_indent()) by telling it we're in 2193 // normal INSERT mode. 2194 if (State & VREPLACE_FLAG) 2195 { 2196 vreplace_mode = State; // So we know to put things right later 2197 State = INSERT; 2198 } 2199 else 2200 vreplace_mode = 0; 2201 #endif 2202 #ifdef FEAT_LISP 2203 // May do lisp indenting. 2204 if (!p_paste 2205 && leader == NULL 2206 && curbuf->b_p_lisp 2207 && curbuf->b_p_ai) 2208 { 2209 fixthisline(get_lisp_indent); 2210 ai_col = (colnr_T)getwhitecols_curline(); 2211 } 2212 #endif 2213 #ifdef FEAT_CINDENT 2214 // May do indenting after opening a new line. 2215 if (!p_paste 2216 && (curbuf->b_p_cin 2217 # ifdef FEAT_EVAL 2218 || *curbuf->b_p_inde != NUL 2219 # endif 2220 ) 2221 && in_cinkeys(dir == FORWARD 2222 ? KEY_OPEN_FORW 2223 : KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum))) 2224 { 2225 do_c_expr_indent(); 2226 ai_col = (colnr_T)getwhitecols_curline(); 2227 } 2228 #endif 2229 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) 2230 if (vreplace_mode != 0) 2231 State = vreplace_mode; 2232 #endif 2233 2234 // Finally, VREPLACE gets the stuff on the new line, then puts back the 2235 // original line, and inserts the new stuff char by char, pushing old stuff 2236 // onto the replace stack (via ins_char()). 2237 if (State & VREPLACE_FLAG) 2238 { 2239 // Put new line in p_extra 2240 p_extra = vim_strsave(ml_get_curline()); 2241 if (p_extra == NULL) 2242 goto theend; 2243 2244 // Put back original line 2245 ml_replace(curwin->w_cursor.lnum, next_line, FALSE); 2246 2247 // Insert new stuff into line again 2248 curwin->w_cursor.col = 0; 2249 curwin->w_cursor.coladd = 0; 2250 ins_bytes(p_extra); // will call changed_bytes() 2251 vim_free(p_extra); 2252 next_line = NULL; 2253 } 2254 2255 retval = OK; // success! 2256 theend: 2257 curbuf->b_p_pi = saved_pi; 2258 vim_free(saved_line); 2259 vim_free(next_line); 2260 vim_free(allocated); 2261 return retval; 2262 } 2263 2264 /* 2265 * Delete from cursor to end of line. 2266 * Caller must have prepared for undo. 2267 * If "fixpos" is TRUE fix the cursor position when done. 2268 * 2269 * Return FAIL for failure, OK otherwise. 2270 */ 2271 int 2272 truncate_line(int fixpos) 2273 { 2274 char_u *newp; 2275 linenr_T lnum = curwin->w_cursor.lnum; 2276 colnr_T col = curwin->w_cursor.col; 2277 2278 if (col == 0) 2279 newp = vim_strsave((char_u *)""); 2280 else 2281 newp = vim_strnsave(ml_get(lnum), col); 2282 2283 if (newp == NULL) 2284 return FAIL; 2285 2286 ml_replace(lnum, newp, FALSE); 2287 2288 // mark the buffer as changed and prepare for displaying 2289 changed_bytes(lnum, curwin->w_cursor.col); 2290 2291 // If "fixpos" is TRUE we don't want to end up positioned at the NUL. 2292 if (fixpos && curwin->w_cursor.col > 0) 2293 --curwin->w_cursor.col; 2294 2295 return OK; 2296 } 2297 2298 /* 2299 * Delete "nlines" lines at the cursor. 2300 * Saves the lines for undo first if "undo" is TRUE. 2301 */ 2302 void 2303 del_lines(long nlines, int undo) 2304 { 2305 long n; 2306 linenr_T first = curwin->w_cursor.lnum; 2307 2308 if (nlines <= 0) 2309 return; 2310 2311 // save the deleted lines for undo 2312 if (undo && u_savedel(first, nlines) == FAIL) 2313 return; 2314 2315 for (n = 0; n < nlines; ) 2316 { 2317 if (curbuf->b_ml.ml_flags & ML_EMPTY) // nothing to delete 2318 break; 2319 2320 ml_delete(first, TRUE); 2321 ++n; 2322 2323 // If we delete the last line in the file, stop 2324 if (first > curbuf->b_ml.ml_line_count) 2325 break; 2326 } 2327 2328 // Correct the cursor position before calling deleted_lines_mark(), it may 2329 // trigger a callback to display the cursor. 2330 curwin->w_cursor.col = 0; 2331 check_cursor_lnum(); 2332 2333 // adjust marks, mark the buffer as changed and prepare for displaying 2334 deleted_lines_mark(first, n); 2335 } 2336