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 * ex_cmds.c: some functions for command line commands 12 */ 13 14 #include "vim.h" 15 #include "version.h" 16 17 #ifdef FEAT_FLOAT 18 # include <float.h> 19 #endif 20 21 static int linelen(int *has_tab); 22 static void do_filter(linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, int do_in, int do_out); 23 static int not_writing(void); 24 static int check_readonly(int *forceit, buf_T *buf); 25 static void delbuf_msg(char_u *name); 26 27 /* 28 * ":ascii" and "ga". 29 */ 30 void 31 do_ascii(exarg_T *eap UNUSED) 32 { 33 int c; 34 int cval; 35 char buf1[20]; 36 char buf2[20]; 37 char_u buf3[7]; 38 #ifdef FEAT_DIGRAPHS 39 char_u *dig; 40 #endif 41 int cc[MAX_MCO]; 42 int ci = 0; 43 int len; 44 45 if (enc_utf8) 46 c = utfc_ptr2char(ml_get_cursor(), cc); 47 else 48 c = gchar_cursor(); 49 if (c == NUL) 50 { 51 msg("NUL"); 52 return; 53 } 54 55 IObuff[0] = NUL; 56 if (!has_mbyte || (enc_dbcs != 0 && c < 0x100) || c < 0x80) 57 { 58 if (c == NL) // NUL is stored as NL 59 c = NUL; 60 if (c == CAR && get_fileformat(curbuf) == EOL_MAC) 61 cval = NL; // NL is stored as CR 62 else 63 cval = c; 64 if (vim_isprintc_strict(c) && (c < ' ' 65 #ifndef EBCDIC 66 || c > '~' 67 #endif 68 )) 69 { 70 transchar_nonprint(curbuf, buf3, c); 71 vim_snprintf(buf1, sizeof(buf1), " <%s>", (char *)buf3); 72 } 73 else 74 buf1[0] = NUL; 75 #ifndef EBCDIC 76 if (c >= 0x80) 77 vim_snprintf(buf2, sizeof(buf2), " <M-%s>", 78 (char *)transchar(c & 0x7f)); 79 else 80 #endif 81 buf2[0] = NUL; 82 #ifdef FEAT_DIGRAPHS 83 dig = get_digraph_for_char(cval); 84 if (dig != NULL) 85 vim_snprintf((char *)IObuff, IOSIZE, 86 _("<%s>%s%s %d, Hex %02x, Oct %03o, Digr %s"), 87 transchar(c), buf1, buf2, cval, cval, cval, dig); 88 else 89 #endif 90 vim_snprintf((char *)IObuff, IOSIZE, 91 _("<%s>%s%s %d, Hex %02x, Octal %03o"), 92 transchar(c), buf1, buf2, cval, cval, cval); 93 if (enc_utf8) 94 c = cc[ci++]; 95 else 96 c = 0; 97 } 98 99 // Repeat for combining characters. 100 while (has_mbyte && (c >= 0x100 || (enc_utf8 && c >= 0x80))) 101 { 102 len = (int)STRLEN(IObuff); 103 // This assumes every multi-byte char is printable... 104 if (len > 0) 105 IObuff[len++] = ' '; 106 IObuff[len++] = '<'; 107 if (enc_utf8 && utf_iscomposing(c) 108 # ifdef USE_GUI 109 && !gui.in_use 110 # endif 111 ) 112 IObuff[len++] = ' '; // draw composing char on top of a space 113 len += (*mb_char2bytes)(c, IObuff + len); 114 #ifdef FEAT_DIGRAPHS 115 dig = get_digraph_for_char(c); 116 if (dig != NULL) 117 vim_snprintf((char *)IObuff + len, IOSIZE - len, 118 c < 0x10000 ? _("> %d, Hex %04x, Oct %o, Digr %s") 119 : _("> %d, Hex %08x, Oct %o, Digr %s"), 120 c, c, c, dig); 121 else 122 #endif 123 vim_snprintf((char *)IObuff + len, IOSIZE - len, 124 c < 0x10000 ? _("> %d, Hex %04x, Octal %o") 125 : _("> %d, Hex %08x, Octal %o"), 126 c, c, c); 127 if (ci == MAX_MCO) 128 break; 129 if (enc_utf8) 130 c = cc[ci++]; 131 else 132 c = 0; 133 } 134 135 msg((char *)IObuff); 136 } 137 138 /* 139 * ":left", ":center" and ":right": align text. 140 */ 141 void 142 ex_align(exarg_T *eap) 143 { 144 pos_T save_curpos; 145 int len; 146 int indent = 0; 147 int new_indent; 148 int has_tab; 149 int width; 150 151 #ifdef FEAT_RIGHTLEFT 152 if (curwin->w_p_rl) 153 { 154 // switch left and right aligning 155 if (eap->cmdidx == CMD_right) 156 eap->cmdidx = CMD_left; 157 else if (eap->cmdidx == CMD_left) 158 eap->cmdidx = CMD_right; 159 } 160 #endif 161 162 width = atoi((char *)eap->arg); 163 save_curpos = curwin->w_cursor; 164 if (eap->cmdidx == CMD_left) // width is used for new indent 165 { 166 if (width >= 0) 167 indent = width; 168 } 169 else 170 { 171 /* 172 * if 'textwidth' set, use it 173 * else if 'wrapmargin' set, use it 174 * if invalid value, use 80 175 */ 176 if (width <= 0) 177 width = curbuf->b_p_tw; 178 if (width == 0 && curbuf->b_p_wm > 0) 179 width = curwin->w_width - curbuf->b_p_wm; 180 if (width <= 0) 181 width = 80; 182 } 183 184 if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL) 185 return; 186 187 for (curwin->w_cursor.lnum = eap->line1; 188 curwin->w_cursor.lnum <= eap->line2; ++curwin->w_cursor.lnum) 189 { 190 if (eap->cmdidx == CMD_left) // left align 191 new_indent = indent; 192 else 193 { 194 has_tab = FALSE; // avoid uninit warnings 195 len = linelen(eap->cmdidx == CMD_right ? &has_tab 196 : NULL) - get_indent(); 197 198 if (len <= 0) // skip blank lines 199 continue; 200 201 if (eap->cmdidx == CMD_center) 202 new_indent = (width - len) / 2; 203 else 204 { 205 new_indent = width - len; // right align 206 207 /* 208 * Make sure that embedded TABs don't make the text go too far 209 * to the right. 210 */ 211 if (has_tab) 212 while (new_indent > 0) 213 { 214 (void)set_indent(new_indent, 0); 215 if (linelen(NULL) <= width) 216 { 217 /* 218 * Now try to move the line as much as possible to 219 * the right. Stop when it moves too far. 220 */ 221 do 222 (void)set_indent(++new_indent, 0); 223 while (linelen(NULL) <= width); 224 --new_indent; 225 break; 226 } 227 --new_indent; 228 } 229 } 230 } 231 if (new_indent < 0) 232 new_indent = 0; 233 (void)set_indent(new_indent, 0); // set indent 234 } 235 changed_lines(eap->line1, 0, eap->line2 + 1, 0L); 236 curwin->w_cursor = save_curpos; 237 beginline(BL_WHITE | BL_FIX); 238 } 239 240 /* 241 * Get the length of the current line, excluding trailing white space. 242 */ 243 static int 244 linelen(int *has_tab) 245 { 246 char_u *line; 247 char_u *first; 248 char_u *last; 249 int save; 250 int len; 251 252 // Get the line. If it's empty bail out early (could be the empty string 253 // for an unloaded buffer). 254 line = ml_get_curline(); 255 if (*line == NUL) 256 return 0; 257 258 // find the first non-blank character 259 first = skipwhite(line); 260 261 // find the character after the last non-blank character 262 for (last = first + STRLEN(first); 263 last > first && VIM_ISWHITE(last[-1]); --last) 264 ; 265 save = *last; 266 *last = NUL; 267 len = linetabsize(line); // get line length 268 if (has_tab != NULL) // check for embedded TAB 269 *has_tab = (vim_strchr(first, TAB) != NULL); 270 *last = save; 271 272 return len; 273 } 274 275 // Buffer for two lines used during sorting. They are allocated to 276 // contain the longest line being sorted. 277 static char_u *sortbuf1; 278 static char_u *sortbuf2; 279 280 static int sort_ic; // ignore case 281 static int sort_nr; // sort on number 282 static int sort_rx; // sort on regex instead of skipping it 283 #ifdef FEAT_FLOAT 284 static int sort_flt; // sort on floating number 285 #endif 286 287 static int sort_abort; // flag to indicate if sorting has been interrupted 288 289 // Struct to store info to be sorted. 290 typedef struct 291 { 292 linenr_T lnum; // line number 293 union { 294 struct 295 { 296 varnumber_T start_col_nr; // starting column number 297 varnumber_T end_col_nr; // ending column number 298 } line; 299 struct 300 { 301 varnumber_T value; // value if sorting by integer 302 int is_number; // TRUE when line contains a number 303 } num; 304 #ifdef FEAT_FLOAT 305 float_T value_flt; // value if sorting by float 306 #endif 307 } st_u; 308 } sorti_T; 309 310 static int sort_compare(const void *s1, const void *s2); 311 312 static int 313 sort_compare(const void *s1, const void *s2) 314 { 315 sorti_T l1 = *(sorti_T *)s1; 316 sorti_T l2 = *(sorti_T *)s2; 317 int result = 0; 318 319 // If the user interrupts, there's no way to stop qsort() immediately, but 320 // if we return 0 every time, qsort will assume it's done sorting and 321 // exit. 322 if (sort_abort) 323 return 0; 324 fast_breakcheck(); 325 if (got_int) 326 sort_abort = TRUE; 327 328 if (sort_nr) 329 { 330 if (l1.st_u.num.is_number != l2.st_u.num.is_number) 331 result = l1.st_u.num.is_number - l2.st_u.num.is_number; 332 else 333 result = l1.st_u.num.value == l2.st_u.num.value ? 0 334 : l1.st_u.num.value > l2.st_u.num.value ? 1 : -1; 335 } 336 #ifdef FEAT_FLOAT 337 else if (sort_flt) 338 result = l1.st_u.value_flt == l2.st_u.value_flt ? 0 339 : l1.st_u.value_flt > l2.st_u.value_flt ? 1 : -1; 340 #endif 341 else 342 { 343 // We need to copy one line into "sortbuf1", because there is no 344 // guarantee that the first pointer becomes invalid when obtaining the 345 // second one. 346 STRNCPY(sortbuf1, ml_get(l1.lnum) + l1.st_u.line.start_col_nr, 347 l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr + 1); 348 sortbuf1[l1.st_u.line.end_col_nr - l1.st_u.line.start_col_nr] = 0; 349 STRNCPY(sortbuf2, ml_get(l2.lnum) + l2.st_u.line.start_col_nr, 350 l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr + 1); 351 sortbuf2[l2.st_u.line.end_col_nr - l2.st_u.line.start_col_nr] = 0; 352 353 result = sort_ic ? STRICMP(sortbuf1, sortbuf2) 354 : STRCMP(sortbuf1, sortbuf2); 355 } 356 357 // If two lines have the same value, preserve the original line order. 358 if (result == 0) 359 return (int)(l1.lnum - l2.lnum); 360 return result; 361 } 362 363 /* 364 * ":sort". 365 */ 366 void 367 ex_sort(exarg_T *eap) 368 { 369 regmatch_T regmatch; 370 int len; 371 linenr_T lnum; 372 long maxlen = 0; 373 sorti_T *nrs; 374 size_t count = (size_t)(eap->line2 - eap->line1 + 1); 375 size_t i; 376 char_u *p; 377 char_u *s; 378 char_u *s2; 379 char_u c; // temporary character storage 380 int unique = FALSE; 381 long deleted; 382 colnr_T start_col; 383 colnr_T end_col; 384 int sort_what = 0; 385 int format_found = 0; 386 int change_occurred = FALSE; // Buffer contents changed. 387 388 // Sorting one line is really quick! 389 if (count <= 1) 390 return; 391 392 if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL) 393 return; 394 sortbuf1 = NULL; 395 sortbuf2 = NULL; 396 regmatch.regprog = NULL; 397 nrs = ALLOC_MULT(sorti_T, count); 398 if (nrs == NULL) 399 goto sortend; 400 401 sort_abort = sort_ic = sort_rx = sort_nr = 0; 402 #ifdef FEAT_FLOAT 403 sort_flt = 0; 404 #endif 405 406 for (p = eap->arg; *p != NUL; ++p) 407 { 408 if (VIM_ISWHITE(*p)) 409 ; 410 else if (*p == 'i') 411 sort_ic = TRUE; 412 else if (*p == 'r') 413 sort_rx = TRUE; 414 else if (*p == 'n') 415 { 416 sort_nr = 1; 417 ++format_found; 418 } 419 #ifdef FEAT_FLOAT 420 else if (*p == 'f') 421 { 422 sort_flt = 1; 423 ++format_found; 424 } 425 #endif 426 else if (*p == 'b') 427 { 428 sort_what = STR2NR_BIN + STR2NR_FORCE; 429 ++format_found; 430 } 431 else if (*p == 'o') 432 { 433 sort_what = STR2NR_OCT + STR2NR_FORCE; 434 ++format_found; 435 } 436 else if (*p == 'x') 437 { 438 sort_what = STR2NR_HEX + STR2NR_FORCE; 439 ++format_found; 440 } 441 else if (*p == 'u') 442 unique = TRUE; 443 else if (*p == '"') // comment start 444 break; 445 else if (check_nextcmd(p) != NULL) 446 { 447 eap->nextcmd = check_nextcmd(p); 448 break; 449 } 450 else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL) 451 { 452 s = skip_regexp_err(p + 1, *p, TRUE); 453 if (s == NULL) 454 goto sortend; 455 *s = NUL; 456 // Use last search pattern if sort pattern is empty. 457 if (s == p + 1) 458 { 459 if (last_search_pat() == NULL) 460 { 461 emsg(_(e_noprevre)); 462 goto sortend; 463 } 464 regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC); 465 } 466 else 467 regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC); 468 if (regmatch.regprog == NULL) 469 goto sortend; 470 p = s; // continue after the regexp 471 regmatch.rm_ic = p_ic; 472 } 473 else 474 { 475 semsg(_(e_invarg2), p); 476 goto sortend; 477 } 478 } 479 480 // Can only have one of 'n', 'b', 'o' and 'x'. 481 if (format_found > 1) 482 { 483 emsg(_(e_invarg)); 484 goto sortend; 485 } 486 487 // From here on "sort_nr" is used as a flag for any integer number 488 // sorting. 489 sort_nr += sort_what; 490 491 /* 492 * Make an array with all line numbers. This avoids having to copy all 493 * the lines into allocated memory. 494 * When sorting on strings "start_col_nr" is the offset in the line, for 495 * numbers sorting it's the number to sort on. This means the pattern 496 * matching and number conversion only has to be done once per line. 497 * Also get the longest line length for allocating "sortbuf". 498 */ 499 for (lnum = eap->line1; lnum <= eap->line2; ++lnum) 500 { 501 s = ml_get(lnum); 502 len = (int)STRLEN(s); 503 if (maxlen < len) 504 maxlen = len; 505 506 start_col = 0; 507 end_col = len; 508 if (regmatch.regprog != NULL && vim_regexec(®match, s, 0)) 509 { 510 if (sort_rx) 511 { 512 start_col = (colnr_T)(regmatch.startp[0] - s); 513 end_col = (colnr_T)(regmatch.endp[0] - s); 514 } 515 else 516 start_col = (colnr_T)(regmatch.endp[0] - s); 517 } 518 else 519 if (regmatch.regprog != NULL) 520 end_col = 0; 521 522 if (sort_nr 523 #ifdef FEAT_FLOAT 524 || sort_flt 525 #endif 526 ) 527 { 528 // Make sure vim_str2nr doesn't read any digits past the end 529 // of the match, by temporarily terminating the string there 530 s2 = s + end_col; 531 c = *s2; 532 *s2 = NUL; 533 // Sorting on number: Store the number itself. 534 p = s + start_col; 535 if (sort_nr) 536 { 537 if (sort_what & STR2NR_HEX) 538 s = skiptohex(p); 539 else if (sort_what & STR2NR_BIN) 540 s = skiptobin(p); 541 else 542 s = skiptodigit(p); 543 if (s > p && s[-1] == '-') 544 --s; // include preceding negative sign 545 if (*s == NUL) 546 { 547 // line without number should sort before any number 548 nrs[lnum - eap->line1].st_u.num.is_number = FALSE; 549 nrs[lnum - eap->line1].st_u.num.value = 0; 550 } 551 else 552 { 553 nrs[lnum - eap->line1].st_u.num.is_number = TRUE; 554 vim_str2nr(s, NULL, NULL, sort_what, 555 &nrs[lnum - eap->line1].st_u.num.value, 556 NULL, 0, FALSE); 557 } 558 } 559 #ifdef FEAT_FLOAT 560 else 561 { 562 s = skipwhite(p); 563 if (*s == '+') 564 s = skipwhite(s + 1); 565 566 if (*s == NUL) 567 // empty line should sort before any number 568 nrs[lnum - eap->line1].st_u.value_flt = -DBL_MAX; 569 else 570 nrs[lnum - eap->line1].st_u.value_flt = 571 strtod((char *)s, NULL); 572 } 573 #endif 574 *s2 = c; 575 } 576 else 577 { 578 // Store the column to sort at. 579 nrs[lnum - eap->line1].st_u.line.start_col_nr = start_col; 580 nrs[lnum - eap->line1].st_u.line.end_col_nr = end_col; 581 } 582 583 nrs[lnum - eap->line1].lnum = lnum; 584 585 if (regmatch.regprog != NULL) 586 fast_breakcheck(); 587 if (got_int) 588 goto sortend; 589 } 590 591 // Allocate a buffer that can hold the longest line. 592 sortbuf1 = alloc(maxlen + 1); 593 if (sortbuf1 == NULL) 594 goto sortend; 595 sortbuf2 = alloc(maxlen + 1); 596 if (sortbuf2 == NULL) 597 goto sortend; 598 599 // Sort the array of line numbers. Note: can't be interrupted! 600 qsort((void *)nrs, count, sizeof(sorti_T), sort_compare); 601 602 if (sort_abort) 603 goto sortend; 604 605 // Insert the lines in the sorted order below the last one. 606 lnum = eap->line2; 607 for (i = 0; i < count; ++i) 608 { 609 linenr_T get_lnum = nrs[eap->forceit ? count - i - 1 : i].lnum; 610 611 // If the original line number of the line being placed is not the same 612 // as "lnum" (accounting for offset), we know that the buffer changed. 613 if (get_lnum + ((linenr_T)count - 1) != lnum) 614 change_occurred = TRUE; 615 616 s = ml_get(get_lnum); 617 if (!unique || i == 0 618 || (sort_ic ? STRICMP(s, sortbuf1) : STRCMP(s, sortbuf1)) != 0) 619 { 620 // Copy the line into a buffer, it may become invalid in 621 // ml_append(). And it's needed for "unique". 622 STRCPY(sortbuf1, s); 623 if (ml_append(lnum++, sortbuf1, (colnr_T)0, FALSE) == FAIL) 624 break; 625 } 626 fast_breakcheck(); 627 if (got_int) 628 goto sortend; 629 } 630 631 // delete the original lines if appending worked 632 if (i == count) 633 for (i = 0; i < count; ++i) 634 ml_delete(eap->line1); 635 else 636 count = 0; 637 638 // Adjust marks for deleted (or added) lines and prepare for displaying. 639 deleted = (long)(count - (lnum - eap->line2)); 640 if (deleted > 0) 641 { 642 mark_adjust(eap->line2 - deleted, eap->line2, (long)MAXLNUM, -deleted); 643 msgmore(-deleted); 644 } 645 else if (deleted < 0) 646 mark_adjust(eap->line2, MAXLNUM, -deleted, 0L); 647 648 if (change_occurred || deleted != 0) 649 changed_lines(eap->line1, 0, eap->line2 + 1, -deleted); 650 651 curwin->w_cursor.lnum = eap->line1; 652 beginline(BL_WHITE | BL_FIX); 653 654 sortend: 655 vim_free(nrs); 656 vim_free(sortbuf1); 657 vim_free(sortbuf2); 658 vim_regfree(regmatch.regprog); 659 if (got_int) 660 emsg(_(e_interr)); 661 } 662 663 /* 664 * :move command - move lines line1-line2 to line dest 665 * 666 * return FAIL for failure, OK otherwise 667 */ 668 int 669 do_move(linenr_T line1, linenr_T line2, linenr_T dest) 670 { 671 char_u *str; 672 linenr_T l; 673 linenr_T extra; // Num lines added before line1 674 linenr_T num_lines; // Num lines moved 675 linenr_T last_line; // Last line in file after adding new text 676 #ifdef FEAT_FOLDING 677 win_T *win; 678 tabpage_T *tp; 679 #endif 680 681 if (dest >= line1 && dest < line2) 682 { 683 emsg(_("E134: Cannot move a range of lines into itself")); 684 return FAIL; 685 } 686 687 // Do nothing if we are not actually moving any lines. This will prevent 688 // the 'modified' flag from being set without cause. 689 if (dest == line1 - 1 || dest == line2) 690 { 691 // Move the cursor as if lines were moved (see below) to be backwards 692 // compatible. 693 if (dest >= line1) 694 curwin->w_cursor.lnum = dest; 695 else 696 curwin->w_cursor.lnum = dest + (line2 - line1) + 1; 697 698 return OK; 699 } 700 701 num_lines = line2 - line1 + 1; 702 703 /* 704 * First we copy the old text to its new location -- webb 705 * Also copy the flag that ":global" command uses. 706 */ 707 if (u_save(dest, dest + 1) == FAIL) 708 return FAIL; 709 for (extra = 0, l = line1; l <= line2; l++) 710 { 711 str = vim_strsave(ml_get(l + extra)); 712 if (str != NULL) 713 { 714 ml_append(dest + l - line1, str, (colnr_T)0, FALSE); 715 vim_free(str); 716 if (dest < line1) 717 extra++; 718 } 719 } 720 721 /* 722 * Now we must be careful adjusting our marks so that we don't overlap our 723 * mark_adjust() calls. 724 * 725 * We adjust the marks within the old text so that they refer to the 726 * last lines of the file (temporarily), because we know no other marks 727 * will be set there since these line numbers did not exist until we added 728 * our new lines. 729 * 730 * Then we adjust the marks on lines between the old and new text positions 731 * (either forwards or backwards). 732 * 733 * And Finally we adjust the marks we put at the end of the file back to 734 * their final destination at the new text position -- webb 735 */ 736 last_line = curbuf->b_ml.ml_line_count; 737 mark_adjust_nofold(line1, line2, last_line - line2, 0L); 738 if (dest >= line2) 739 { 740 mark_adjust_nofold(line2 + 1, dest, -num_lines, 0L); 741 #ifdef FEAT_FOLDING 742 FOR_ALL_TAB_WINDOWS(tp, win) { 743 if (win->w_buffer == curbuf) 744 foldMoveRange(&win->w_folds, line1, line2, dest); 745 } 746 #endif 747 if (!cmdmod.lockmarks) 748 { 749 curbuf->b_op_start.lnum = dest - num_lines + 1; 750 curbuf->b_op_end.lnum = dest; 751 } 752 } 753 else 754 { 755 mark_adjust_nofold(dest + 1, line1 - 1, num_lines, 0L); 756 #ifdef FEAT_FOLDING 757 FOR_ALL_TAB_WINDOWS(tp, win) { 758 if (win->w_buffer == curbuf) 759 foldMoveRange(&win->w_folds, dest + 1, line1 - 1, line2); 760 } 761 #endif 762 if (!cmdmod.lockmarks) 763 { 764 curbuf->b_op_start.lnum = dest + 1; 765 curbuf->b_op_end.lnum = dest + num_lines; 766 } 767 } 768 if (!cmdmod.lockmarks) 769 curbuf->b_op_start.col = curbuf->b_op_end.col = 0; 770 mark_adjust_nofold(last_line - num_lines + 1, last_line, 771 -(last_line - dest - extra), 0L); 772 773 /* 774 * Now we delete the original text -- webb 775 */ 776 if (u_save(line1 + extra - 1, line2 + extra + 1) == FAIL) 777 return FAIL; 778 779 for (l = line1; l <= line2; l++) 780 ml_delete_flags(line1 + extra, ML_DEL_MESSAGE); 781 782 if (!global_busy && num_lines > p_report) 783 smsg(NGETTEXT("%ld line moved", "%ld lines moved", num_lines), 784 (long)num_lines); 785 786 /* 787 * Leave the cursor on the last of the moved lines. 788 */ 789 if (dest >= line1) 790 curwin->w_cursor.lnum = dest; 791 else 792 curwin->w_cursor.lnum = dest + (line2 - line1) + 1; 793 794 if (line1 < dest) 795 { 796 dest += num_lines + 1; 797 last_line = curbuf->b_ml.ml_line_count; 798 if (dest > last_line + 1) 799 dest = last_line + 1; 800 changed_lines(line1, 0, dest, 0L); 801 } 802 else 803 changed_lines(dest + 1, 0, line1 + num_lines, 0L); 804 805 return OK; 806 } 807 808 /* 809 * ":copy" 810 */ 811 void 812 ex_copy(linenr_T line1, linenr_T line2, linenr_T n) 813 { 814 linenr_T count; 815 char_u *p; 816 817 count = line2 - line1 + 1; 818 if (!cmdmod.lockmarks) 819 { 820 curbuf->b_op_start.lnum = n + 1; 821 curbuf->b_op_end.lnum = n + count; 822 curbuf->b_op_start.col = curbuf->b_op_end.col = 0; 823 } 824 825 /* 826 * there are three situations: 827 * 1. destination is above line1 828 * 2. destination is between line1 and line2 829 * 3. destination is below line2 830 * 831 * n = destination (when starting) 832 * curwin->w_cursor.lnum = destination (while copying) 833 * line1 = start of source (while copying) 834 * line2 = end of source (while copying) 835 */ 836 if (u_save(n, n + 1) == FAIL) 837 return; 838 839 curwin->w_cursor.lnum = n; 840 while (line1 <= line2) 841 { 842 // need to use vim_strsave() because the line will be unlocked within 843 // ml_append() 844 p = vim_strsave(ml_get(line1)); 845 if (p != NULL) 846 { 847 ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, FALSE); 848 vim_free(p); 849 } 850 // situation 2: skip already copied lines 851 if (line1 == n) 852 line1 = curwin->w_cursor.lnum; 853 ++line1; 854 if (curwin->w_cursor.lnum < line1) 855 ++line1; 856 if (curwin->w_cursor.lnum < line2) 857 ++line2; 858 ++curwin->w_cursor.lnum; 859 } 860 861 appended_lines_mark(n, count); 862 863 msgmore((long)count); 864 } 865 866 static char_u *prevcmd = NULL; // the previous command 867 868 #if defined(EXITFREE) || defined(PROTO) 869 void 870 free_prev_shellcmd(void) 871 { 872 vim_free(prevcmd); 873 } 874 #endif 875 876 /* 877 * Handle the ":!cmd" command. Also for ":r !cmd" and ":w !cmd" 878 * Bangs in the argument are replaced with the previously entered command. 879 * Remember the argument. 880 */ 881 void 882 do_bang( 883 int addr_count, 884 exarg_T *eap, 885 int forceit, 886 int do_in, 887 int do_out) 888 { 889 char_u *arg = eap->arg; // command 890 linenr_T line1 = eap->line1; // start of range 891 linenr_T line2 = eap->line2; // end of range 892 char_u *newcmd = NULL; // the new command 893 int free_newcmd = FALSE; // need to free() newcmd 894 int ins_prevcmd; 895 char_u *t; 896 char_u *p; 897 char_u *trailarg; 898 int len; 899 int scroll_save = msg_scroll; 900 901 /* 902 * Disallow shell commands for "rvim". 903 * Disallow shell commands from .exrc and .vimrc in current directory for 904 * security reasons. 905 */ 906 if (check_restricted() || check_secure()) 907 return; 908 909 if (addr_count == 0) // :! 910 { 911 msg_scroll = FALSE; // don't scroll here 912 autowrite_all(); 913 msg_scroll = scroll_save; 914 } 915 916 /* 917 * Try to find an embedded bang, like in :!<cmd> ! [args] 918 * (:!! is indicated by the 'forceit' variable) 919 */ 920 ins_prevcmd = forceit; 921 trailarg = arg; 922 do 923 { 924 len = (int)STRLEN(trailarg) + 1; 925 if (newcmd != NULL) 926 len += (int)STRLEN(newcmd); 927 if (ins_prevcmd) 928 { 929 if (prevcmd == NULL) 930 { 931 emsg(_(e_noprev)); 932 vim_free(newcmd); 933 return; 934 } 935 len += (int)STRLEN(prevcmd); 936 } 937 if ((t = alloc(len)) == NULL) 938 { 939 vim_free(newcmd); 940 return; 941 } 942 *t = NUL; 943 if (newcmd != NULL) 944 STRCAT(t, newcmd); 945 if (ins_prevcmd) 946 STRCAT(t, prevcmd); 947 p = t + STRLEN(t); 948 STRCAT(t, trailarg); 949 vim_free(newcmd); 950 newcmd = t; 951 952 /* 953 * Scan the rest of the argument for '!', which is replaced by the 954 * previous command. "\!" is replaced by "!" (this is vi compatible). 955 */ 956 trailarg = NULL; 957 while (*p) 958 { 959 if (*p == '!') 960 { 961 if (p > newcmd && p[-1] == '\\') 962 STRMOVE(p - 1, p); 963 else 964 { 965 trailarg = p; 966 *trailarg++ = NUL; 967 ins_prevcmd = TRUE; 968 break; 969 } 970 } 971 ++p; 972 } 973 } while (trailarg != NULL); 974 975 vim_free(prevcmd); 976 prevcmd = newcmd; 977 978 if (bangredo) // put cmd in redo buffer for ! command 979 { 980 // If % or # appears in the command, it must have been escaped. 981 // Reescape them, so that redoing them does not substitute them by the 982 // buffername. 983 char_u *cmd = vim_strsave_escaped(prevcmd, (char_u *)"%#"); 984 985 if (cmd != NULL) 986 { 987 AppendToRedobuffLit(cmd, -1); 988 vim_free(cmd); 989 } 990 else 991 AppendToRedobuffLit(prevcmd, -1); 992 AppendToRedobuff((char_u *)"\n"); 993 bangredo = FALSE; 994 } 995 /* 996 * Add quotes around the command, for shells that need them. 997 */ 998 if (*p_shq != NUL) 999 { 1000 newcmd = alloc(STRLEN(prevcmd) + 2 * STRLEN(p_shq) + 1); 1001 if (newcmd == NULL) 1002 return; 1003 STRCPY(newcmd, p_shq); 1004 STRCAT(newcmd, prevcmd); 1005 STRCAT(newcmd, p_shq); 1006 free_newcmd = TRUE; 1007 } 1008 if (addr_count == 0) // :! 1009 { 1010 // echo the command 1011 msg_start(); 1012 msg_putchar(':'); 1013 msg_putchar('!'); 1014 msg_outtrans(newcmd); 1015 msg_clr_eos(); 1016 windgoto(msg_row, msg_col); 1017 1018 do_shell(newcmd, 0); 1019 } 1020 else // :range! 1021 { 1022 // Careful: This may recursively call do_bang() again! (because of 1023 // autocommands) 1024 do_filter(line1, line2, eap, newcmd, do_in, do_out); 1025 apply_autocmds(EVENT_SHELLFILTERPOST, NULL, NULL, FALSE, curbuf); 1026 } 1027 if (free_newcmd) 1028 vim_free(newcmd); 1029 } 1030 1031 /* 1032 * do_filter: filter lines through a command given by the user 1033 * 1034 * We mostly use temp files and the call_shell() routine here. This would 1035 * normally be done using pipes on a UNIX machine, but this is more portable 1036 * to non-unix machines. The call_shell() routine needs to be able 1037 * to deal with redirection somehow, and should handle things like looking 1038 * at the PATH env. variable, and adding reasonable extensions to the 1039 * command name given by the user. All reasonable versions of call_shell() 1040 * do this. 1041 * Alternatively, if on Unix and redirecting input or output, but not both, 1042 * and the 'shelltemp' option isn't set, use pipes. 1043 * We use input redirection if do_in is TRUE. 1044 * We use output redirection if do_out is TRUE. 1045 */ 1046 static void 1047 do_filter( 1048 linenr_T line1, 1049 linenr_T line2, 1050 exarg_T *eap, // for forced 'ff' and 'fenc' 1051 char_u *cmd, 1052 int do_in, 1053 int do_out) 1054 { 1055 char_u *itmp = NULL; 1056 char_u *otmp = NULL; 1057 linenr_T linecount; 1058 linenr_T read_linecount; 1059 pos_T cursor_save; 1060 char_u *cmd_buf; 1061 buf_T *old_curbuf = curbuf; 1062 int shell_flags = 0; 1063 pos_T orig_start = curbuf->b_op_start; 1064 pos_T orig_end = curbuf->b_op_end; 1065 int save_lockmarks = cmdmod.lockmarks; 1066 #ifdef FEAT_FILTERPIPE 1067 int stmp = p_stmp; 1068 #endif 1069 1070 if (*cmd == NUL) // no filter command 1071 return; 1072 1073 // Temporarily disable lockmarks since that's needed to propagate changed 1074 // regions of the buffer for foldUpdate(), linecount, etc. 1075 cmdmod.lockmarks = 0; 1076 1077 cursor_save = curwin->w_cursor; 1078 linecount = line2 - line1 + 1; 1079 curwin->w_cursor.lnum = line1; 1080 curwin->w_cursor.col = 0; 1081 changed_line_abv_curs(); 1082 invalidate_botline(); 1083 1084 /* 1085 * When using temp files: 1086 * 1. * Form temp file names 1087 * 2. * Write the lines to a temp file 1088 * 3. Run the filter command on the temp file 1089 * 4. * Read the output of the command into the buffer 1090 * 5. * Delete the original lines to be filtered 1091 * 6. * Remove the temp files 1092 * 1093 * When writing the input with a pipe or when catching the output with a 1094 * pipe only need to do 3. 1095 */ 1096 1097 if (do_out) 1098 shell_flags |= SHELL_DOOUT; 1099 1100 #ifdef FEAT_FILTERPIPE 1101 # ifdef VIMDLL 1102 if (!gui.in_use && !gui.starting) 1103 stmp = 1; // Console mode doesn't support filterpipe. 1104 # endif 1105 1106 if (!do_in && do_out && !stmp) 1107 { 1108 // Use a pipe to fetch stdout of the command, do not use a temp file. 1109 shell_flags |= SHELL_READ; 1110 curwin->w_cursor.lnum = line2; 1111 } 1112 else if (do_in && !do_out && !stmp) 1113 { 1114 // Use a pipe to write stdin of the command, do not use a temp file. 1115 shell_flags |= SHELL_WRITE; 1116 curbuf->b_op_start.lnum = line1; 1117 curbuf->b_op_end.lnum = line2; 1118 } 1119 else if (do_in && do_out && !stmp) 1120 { 1121 // Use a pipe to write stdin and fetch stdout of the command, do not 1122 // use a temp file. 1123 shell_flags |= SHELL_READ|SHELL_WRITE; 1124 curbuf->b_op_start.lnum = line1; 1125 curbuf->b_op_end.lnum = line2; 1126 curwin->w_cursor.lnum = line2; 1127 } 1128 else 1129 #endif 1130 if ((do_in && (itmp = vim_tempname('i', FALSE)) == NULL) 1131 || (do_out && (otmp = vim_tempname('o', FALSE)) == NULL)) 1132 { 1133 emsg(_(e_notmp)); 1134 goto filterend; 1135 } 1136 1137 /* 1138 * The writing and reading of temp files will not be shown. 1139 * Vi also doesn't do this and the messages are not very informative. 1140 */ 1141 ++no_wait_return; // don't call wait_return() while busy 1142 if (itmp != NULL && buf_write(curbuf, itmp, NULL, line1, line2, eap, 1143 FALSE, FALSE, FALSE, TRUE) == FAIL) 1144 { 1145 msg_putchar('\n'); // keep message from buf_write() 1146 --no_wait_return; 1147 #if defined(FEAT_EVAL) 1148 if (!aborting()) 1149 #endif 1150 (void)semsg(_(e_notcreate), itmp); // will call wait_return 1151 goto filterend; 1152 } 1153 if (curbuf != old_curbuf) 1154 goto filterend; 1155 1156 if (!do_out) 1157 msg_putchar('\n'); 1158 1159 // Create the shell command in allocated memory. 1160 cmd_buf = make_filter_cmd(cmd, itmp, otmp); 1161 if (cmd_buf == NULL) 1162 goto filterend; 1163 1164 windgoto((int)Rows - 1, 0); 1165 cursor_on(); 1166 1167 /* 1168 * When not redirecting the output the command can write anything to the 1169 * screen. If 'shellredir' is equal to ">", screen may be messed up by 1170 * stderr output of external command. Clear the screen later. 1171 * If do_in is FALSE, this could be something like ":r !cat", which may 1172 * also mess up the screen, clear it later. 1173 */ 1174 if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in) 1175 redraw_later_clear(); 1176 1177 if (do_out) 1178 { 1179 if (u_save((linenr_T)(line2), (linenr_T)(line2 + 1)) == FAIL) 1180 { 1181 vim_free(cmd_buf); 1182 goto error; 1183 } 1184 redraw_curbuf_later(VALID); 1185 } 1186 read_linecount = curbuf->b_ml.ml_line_count; 1187 1188 /* 1189 * When call_shell() fails wait_return() is called to give the user a 1190 * chance to read the error messages. Otherwise errors are ignored, so you 1191 * can see the error messages from the command that appear on stdout; use 1192 * 'u' to fix the text 1193 * Switch to cooked mode when not redirecting stdin, avoids that something 1194 * like ":r !cat" hangs. 1195 * Pass on the SHELL_DOOUT flag when the output is being redirected. 1196 */ 1197 if (call_shell(cmd_buf, SHELL_FILTER | SHELL_COOKED | shell_flags)) 1198 { 1199 redraw_later_clear(); 1200 wait_return(FALSE); 1201 } 1202 vim_free(cmd_buf); 1203 1204 did_check_timestamps = FALSE; 1205 need_check_timestamps = TRUE; 1206 1207 // When interrupting the shell command, it may still have produced some 1208 // useful output. Reset got_int here, so that readfile() won't cancel 1209 // reading. 1210 ui_breakcheck(); 1211 got_int = FALSE; 1212 1213 if (do_out) 1214 { 1215 if (otmp != NULL) 1216 { 1217 if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM, 1218 eap, READ_FILTER) != OK) 1219 { 1220 #if defined(FEAT_EVAL) 1221 if (!aborting()) 1222 #endif 1223 { 1224 msg_putchar('\n'); 1225 semsg(_(e_notread), otmp); 1226 } 1227 goto error; 1228 } 1229 if (curbuf != old_curbuf) 1230 goto filterend; 1231 } 1232 1233 read_linecount = curbuf->b_ml.ml_line_count - read_linecount; 1234 1235 if (shell_flags & SHELL_READ) 1236 { 1237 curbuf->b_op_start.lnum = line2 + 1; 1238 curbuf->b_op_end.lnum = curwin->w_cursor.lnum; 1239 appended_lines_mark(line2, read_linecount); 1240 } 1241 1242 if (do_in) 1243 { 1244 if (cmdmod.keepmarks || vim_strchr(p_cpo, CPO_REMMARK) == NULL) 1245 { 1246 if (read_linecount >= linecount) 1247 // move all marks from old lines to new lines 1248 mark_adjust(line1, line2, linecount, 0L); 1249 else 1250 { 1251 // move marks from old lines to new lines, delete marks 1252 // that are in deleted lines 1253 mark_adjust(line1, line1 + read_linecount - 1, 1254 linecount, 0L); 1255 mark_adjust(line1 + read_linecount, line2, MAXLNUM, 0L); 1256 } 1257 } 1258 1259 /* 1260 * Put cursor on first filtered line for ":range!cmd". 1261 * Adjust '[ and '] (set by buf_write()). 1262 */ 1263 curwin->w_cursor.lnum = line1; 1264 del_lines(linecount, TRUE); 1265 curbuf->b_op_start.lnum -= linecount; // adjust '[ 1266 curbuf->b_op_end.lnum -= linecount; // adjust '] 1267 write_lnum_adjust(-linecount); // adjust last line 1268 // for next write 1269 #ifdef FEAT_FOLDING 1270 foldUpdate(curwin, curbuf->b_op_start.lnum, curbuf->b_op_end.lnum); 1271 #endif 1272 } 1273 else 1274 { 1275 /* 1276 * Put cursor on last new line for ":r !cmd". 1277 */ 1278 linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1; 1279 curwin->w_cursor.lnum = curbuf->b_op_end.lnum; 1280 } 1281 1282 beginline(BL_WHITE | BL_FIX); // cursor on first non-blank 1283 --no_wait_return; 1284 1285 if (linecount > p_report) 1286 { 1287 if (do_in) 1288 { 1289 vim_snprintf(msg_buf, sizeof(msg_buf), 1290 _("%ld lines filtered"), (long)linecount); 1291 if (msg(msg_buf) && !msg_scroll) 1292 // save message to display it after redraw 1293 set_keep_msg((char_u *)msg_buf, 0); 1294 } 1295 else 1296 msgmore((long)linecount); 1297 } 1298 } 1299 else 1300 { 1301 error: 1302 // put cursor back in same position for ":w !cmd" 1303 curwin->w_cursor = cursor_save; 1304 --no_wait_return; 1305 wait_return(FALSE); 1306 } 1307 1308 filterend: 1309 1310 cmdmod.lockmarks = save_lockmarks; 1311 if (curbuf != old_curbuf) 1312 { 1313 --no_wait_return; 1314 emsg(_("E135: *Filter* Autocommands must not change current buffer")); 1315 } 1316 else if (cmdmod.lockmarks) 1317 { 1318 curbuf->b_op_start = orig_start; 1319 curbuf->b_op_end = orig_end; 1320 } 1321 1322 if (itmp != NULL) 1323 mch_remove(itmp); 1324 if (otmp != NULL) 1325 mch_remove(otmp); 1326 vim_free(itmp); 1327 vim_free(otmp); 1328 } 1329 1330 /* 1331 * Call a shell to execute a command. 1332 * When "cmd" is NULL start an interactive shell. 1333 */ 1334 void 1335 do_shell( 1336 char_u *cmd, 1337 int flags) // may be SHELL_DOOUT when output is redirected 1338 { 1339 buf_T *buf; 1340 #if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL) 1341 int save_nwr; 1342 #endif 1343 #ifdef MSWIN 1344 int winstart = FALSE; 1345 int keep_termcap = FALSE; 1346 #endif 1347 1348 /* 1349 * Disallow shell commands for "rvim". 1350 * Disallow shell commands from .exrc and .vimrc in current directory for 1351 * security reasons. 1352 */ 1353 if (check_restricted() || check_secure()) 1354 { 1355 msg_end(); 1356 return; 1357 } 1358 1359 #ifdef MSWIN 1360 /* 1361 * Check if ":!start" is used. This implies not stopping termcap mode. 1362 */ 1363 if (cmd != NULL) 1364 keep_termcap = winstart = (STRNICMP(cmd, "start ", 6) == 0); 1365 1366 # if defined(FEAT_GUI) && defined(FEAT_TERMINAL) 1367 // Don't stop termcap mode when using a terminal window for the shell. 1368 if (gui.in_use && vim_strchr(p_go, GO_TERMINAL) != NULL) 1369 keep_termcap = TRUE; 1370 # endif 1371 #endif 1372 1373 /* 1374 * For autocommands we want to get the output on the current screen, to 1375 * avoid having to type return below. 1376 */ 1377 msg_putchar('\r'); // put cursor at start of line 1378 if (!autocmd_busy) 1379 { 1380 #ifdef MSWIN 1381 if (!keep_termcap) 1382 #endif 1383 stoptermcap(); 1384 } 1385 #ifdef MSWIN 1386 if (!winstart) 1387 #endif 1388 msg_putchar('\n'); // may shift screen one line up 1389 1390 // warning message before calling the shell 1391 if (p_warn && !autocmd_busy && msg_silent == 0) 1392 FOR_ALL_BUFFERS(buf) 1393 if (bufIsChangedNotTerm(buf)) 1394 { 1395 #ifdef FEAT_GUI_MSWIN 1396 if (!keep_termcap) 1397 starttermcap(); // don't want a message box here 1398 #endif 1399 msg_puts(_("[No write since last change]\n")); 1400 #ifdef FEAT_GUI_MSWIN 1401 if (!keep_termcap) 1402 stoptermcap(); 1403 #endif 1404 break; 1405 } 1406 1407 // This windgoto is required for when the '\n' resulted in a "delete line 1408 // 1" command to the terminal. 1409 if (!swapping_screen()) 1410 windgoto(msg_row, msg_col); 1411 cursor_on(); 1412 (void)call_shell(cmd, SHELL_COOKED | flags); 1413 did_check_timestamps = FALSE; 1414 need_check_timestamps = TRUE; 1415 1416 /* 1417 * put the message cursor at the end of the screen, avoids wait_return() 1418 * to overwrite the text that the external command showed 1419 */ 1420 if (!swapping_screen()) 1421 { 1422 msg_row = Rows - 1; 1423 msg_col = 0; 1424 } 1425 1426 if (autocmd_busy) 1427 { 1428 if (msg_silent == 0) 1429 redraw_later_clear(); 1430 } 1431 else 1432 { 1433 /* 1434 * For ":sh" there is no need to call wait_return(), just redraw. 1435 * Also for the Win32 GUI (the output is in a console window). 1436 * Otherwise there is probably text on the screen that the user wants 1437 * to read before redrawing, so call wait_return(). 1438 */ 1439 #if !defined(FEAT_GUI_MSWIN) || defined(VIMDLL) 1440 # ifdef VIMDLL 1441 if (!gui.in_use) 1442 # endif 1443 { 1444 if (cmd == NULL 1445 # ifdef MSWIN 1446 || (keep_termcap && !need_wait_return) 1447 # endif 1448 ) 1449 { 1450 if (msg_silent == 0) 1451 redraw_later_clear(); 1452 need_wait_return = FALSE; 1453 } 1454 else 1455 { 1456 /* 1457 * If we switch screens when starttermcap() is called, we 1458 * really want to wait for "hit return to continue". 1459 */ 1460 save_nwr = no_wait_return; 1461 if (swapping_screen()) 1462 no_wait_return = FALSE; 1463 # ifdef AMIGA 1464 wait_return(term_console ? -1 : msg_silent == 0); // see below 1465 # else 1466 wait_return(msg_silent == 0); 1467 # endif 1468 no_wait_return = save_nwr; 1469 } 1470 } 1471 #endif // FEAT_GUI_MSWIN 1472 1473 #ifdef MSWIN 1474 if (!keep_termcap) // if keep_termcap is TRUE didn't stop termcap 1475 #endif 1476 starttermcap(); // start termcap if not done by wait_return() 1477 1478 /* 1479 * In an Amiga window redrawing is caused by asking the window size. 1480 * If we got an interrupt this will not work. The chance that the 1481 * window size is wrong is very small, but we need to redraw the 1482 * screen. Don't do this if ':' hit in wait_return(). THIS IS UGLY 1483 * but it saves an extra redraw. 1484 */ 1485 #ifdef AMIGA 1486 if (skip_redraw) // ':' hit in wait_return() 1487 { 1488 if (msg_silent == 0) 1489 redraw_later_clear(); 1490 } 1491 else if (term_console) 1492 { 1493 OUT_STR(IF_EB("\033[0 q", ESC_STR "[0 q")); // get window size 1494 if (got_int && msg_silent == 0) 1495 redraw_later_clear(); // if got_int is TRUE, redraw needed 1496 else 1497 must_redraw = 0; // no extra redraw needed 1498 } 1499 #endif 1500 } 1501 1502 // display any error messages now 1503 display_errors(); 1504 1505 apply_autocmds(EVENT_SHELLCMDPOST, NULL, NULL, FALSE, curbuf); 1506 } 1507 1508 #if !defined(UNIX) 1509 static char_u * 1510 find_pipe(char_u *cmd) 1511 { 1512 char_u *p; 1513 int inquote = FALSE; 1514 1515 for (p = cmd; *p != NUL; ++p) 1516 { 1517 if (!inquote && *p == '|') 1518 return p; 1519 if (*p == '"') 1520 inquote = !inquote; 1521 else if (rem_backslash(p)) 1522 ++p; 1523 } 1524 return NULL; 1525 } 1526 #endif 1527 1528 /* 1529 * Create a shell command from a command string, input redirection file and 1530 * output redirection file. 1531 * Returns an allocated string with the shell command, or NULL for failure. 1532 */ 1533 char_u * 1534 make_filter_cmd( 1535 char_u *cmd, // command 1536 char_u *itmp, // NULL or name of input file 1537 char_u *otmp) // NULL or name of output file 1538 { 1539 char_u *buf; 1540 long_u len; 1541 1542 #if defined(UNIX) 1543 int is_fish_shell; 1544 char_u *shell_name = get_isolated_shell_name(); 1545 1546 // Account for fish's different syntax for subshells 1547 is_fish_shell = (fnamecmp(shell_name, "fish") == 0); 1548 vim_free(shell_name); 1549 if (is_fish_shell) 1550 len = (long_u)STRLEN(cmd) + 13; // "begin; " + "; end" + NUL 1551 else 1552 #endif 1553 len = (long_u)STRLEN(cmd) + 3; // "()" + NUL 1554 if (itmp != NULL) 1555 len += (long_u)STRLEN(itmp) + 9; // " { < " + " } " 1556 if (otmp != NULL) 1557 len += (long_u)STRLEN(otmp) + (long_u)STRLEN(p_srr) + 2; // " " 1558 buf = alloc(len); 1559 if (buf == NULL) 1560 return NULL; 1561 1562 #if defined(UNIX) 1563 /* 1564 * Put braces around the command (for concatenated commands) when 1565 * redirecting input and/or output. 1566 */ 1567 if (itmp != NULL || otmp != NULL) 1568 { 1569 if (is_fish_shell) 1570 vim_snprintf((char *)buf, len, "begin; %s; end", (char *)cmd); 1571 else 1572 vim_snprintf((char *)buf, len, "(%s)", (char *)cmd); 1573 } 1574 else 1575 STRCPY(buf, cmd); 1576 if (itmp != NULL) 1577 { 1578 STRCAT(buf, " < "); 1579 STRCAT(buf, itmp); 1580 } 1581 #else 1582 // For shells that don't understand braces around commands, at least allow 1583 // the use of commands in a pipe. 1584 if (*p_sxe != NUL && *p_sxq == '(') 1585 { 1586 if (itmp != NULL || otmp != NULL) 1587 vim_snprintf((char *)buf, len, "(%s)", (char *)cmd); 1588 else 1589 STRCPY(buf, cmd); 1590 if (itmp != NULL) 1591 { 1592 STRCAT(buf, " < "); 1593 STRCAT(buf, itmp); 1594 } 1595 } 1596 else 1597 { 1598 STRCPY(buf, cmd); 1599 if (itmp != NULL) 1600 { 1601 char_u *p; 1602 1603 // If there is a pipe, we have to put the '<' in front of it. 1604 // Don't do this when 'shellquote' is not empty, otherwise the 1605 // redirection would be inside the quotes. 1606 if (*p_shq == NUL) 1607 { 1608 p = find_pipe(buf); 1609 if (p != NULL) 1610 *p = NUL; 1611 } 1612 STRCAT(buf, " <"); // " < " causes problems on Amiga 1613 STRCAT(buf, itmp); 1614 if (*p_shq == NUL) 1615 { 1616 p = find_pipe(cmd); 1617 if (p != NULL) 1618 { 1619 STRCAT(buf, " "); // insert a space before the '|' for DOS 1620 STRCAT(buf, p); 1621 } 1622 } 1623 } 1624 } 1625 #endif 1626 if (otmp != NULL) 1627 append_redir(buf, (int)len, p_srr, otmp); 1628 1629 return buf; 1630 } 1631 1632 /* 1633 * Append output redirection for file "fname" to the end of string buffer 1634 * "buf[buflen]" 1635 * Works with the 'shellredir' and 'shellpipe' options. 1636 * The caller should make sure that there is enough room: 1637 * STRLEN(opt) + STRLEN(fname) + 3 1638 */ 1639 void 1640 append_redir( 1641 char_u *buf, 1642 int buflen, 1643 char_u *opt, 1644 char_u *fname) 1645 { 1646 char_u *p; 1647 char_u *end; 1648 1649 end = buf + STRLEN(buf); 1650 // find "%s" 1651 for (p = opt; (p = vim_strchr(p, '%')) != NULL; ++p) 1652 { 1653 if (p[1] == 's') // found %s 1654 break; 1655 if (p[1] == '%') // skip %% 1656 ++p; 1657 } 1658 if (p != NULL) 1659 { 1660 #ifdef MSWIN 1661 *end++ = ' '; // not really needed? Not with sh, ksh or bash 1662 #endif 1663 vim_snprintf((char *)end, (size_t)(buflen - (end - buf)), 1664 (char *)opt, (char *)fname); 1665 } 1666 else 1667 vim_snprintf((char *)end, (size_t)(buflen - (end - buf)), 1668 #ifdef FEAT_QUICKFIX 1669 " %s %s", 1670 #else 1671 " %s%s", // " > %s" causes problems on Amiga 1672 #endif 1673 (char *)opt, (char *)fname); 1674 } 1675 1676 /* 1677 * Implementation of ":fixdel", also used by get_stty(). 1678 * <BS> resulting <Del> 1679 * ^? ^H 1680 * not ^? ^? 1681 */ 1682 void 1683 do_fixdel(exarg_T *eap UNUSED) 1684 { 1685 char_u *p; 1686 1687 p = find_termcode((char_u *)"kb"); 1688 add_termcode((char_u *)"kD", p != NULL 1689 && *p == DEL ? (char_u *)CTRL_H_STR : DEL_STR, FALSE); 1690 } 1691 1692 void 1693 print_line_no_prefix( 1694 linenr_T lnum, 1695 int use_number, 1696 int list) 1697 { 1698 char numbuf[30]; 1699 1700 if (curwin->w_p_nu || use_number) 1701 { 1702 vim_snprintf(numbuf, sizeof(numbuf), 1703 "%*ld ", number_width(curwin), (long)lnum); 1704 msg_puts_attr(numbuf, HL_ATTR(HLF_N)); // Highlight line nrs 1705 } 1706 msg_prt_line(ml_get(lnum), list); 1707 } 1708 1709 /* 1710 * Print a text line. Also in silent mode ("ex -s"). 1711 */ 1712 void 1713 print_line(linenr_T lnum, int use_number, int list) 1714 { 1715 int save_silent = silent_mode; 1716 1717 // apply :filter /pat/ 1718 if (message_filtered(ml_get(lnum))) 1719 return; 1720 1721 msg_start(); 1722 silent_mode = FALSE; 1723 info_message = TRUE; // use mch_msg(), not mch_errmsg() 1724 print_line_no_prefix(lnum, use_number, list); 1725 if (save_silent) 1726 { 1727 msg_putchar('\n'); 1728 cursor_on(); // msg_start() switches it off 1729 out_flush(); 1730 silent_mode = save_silent; 1731 } 1732 info_message = FALSE; 1733 } 1734 1735 int 1736 rename_buffer(char_u *new_fname) 1737 { 1738 char_u *fname, *sfname, *xfname; 1739 buf_T *buf; 1740 1741 buf = curbuf; 1742 apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf); 1743 // buffer changed, don't change name now 1744 if (buf != curbuf) 1745 return FAIL; 1746 #ifdef FEAT_EVAL 1747 if (aborting()) // autocmds may abort script processing 1748 return FAIL; 1749 #endif 1750 /* 1751 * The name of the current buffer will be changed. 1752 * A new (unlisted) buffer entry needs to be made to hold the old file 1753 * name, which will become the alternate file name. 1754 * But don't set the alternate file name if the buffer didn't have a 1755 * name. 1756 */ 1757 fname = curbuf->b_ffname; 1758 sfname = curbuf->b_sfname; 1759 xfname = curbuf->b_fname; 1760 curbuf->b_ffname = NULL; 1761 curbuf->b_sfname = NULL; 1762 if (setfname(curbuf, new_fname, NULL, TRUE) == FAIL) 1763 { 1764 curbuf->b_ffname = fname; 1765 curbuf->b_sfname = sfname; 1766 return FAIL; 1767 } 1768 curbuf->b_flags |= BF_NOTEDITED; 1769 if (xfname != NULL && *xfname != NUL) 1770 { 1771 buf = buflist_new(fname, xfname, curwin->w_cursor.lnum, 0); 1772 if (buf != NULL && !cmdmod.keepalt) 1773 curwin->w_alt_fnum = buf->b_fnum; 1774 } 1775 vim_free(fname); 1776 vim_free(sfname); 1777 apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf); 1778 1779 // Change directories when the 'acd' option is set. 1780 DO_AUTOCHDIR; 1781 return OK; 1782 } 1783 1784 /* 1785 * ":file[!] [fname]". 1786 */ 1787 void 1788 ex_file(exarg_T *eap) 1789 { 1790 // ":0file" removes the file name. Check for illegal uses ":3file", 1791 // "0file name", etc. 1792 if (eap->addr_count > 0 1793 && (*eap->arg != NUL 1794 || eap->line2 > 0 1795 || eap->addr_count > 1)) 1796 { 1797 emsg(_(e_invarg)); 1798 return; 1799 } 1800 1801 if (*eap->arg != NUL || eap->addr_count == 1) 1802 { 1803 if (rename_buffer(eap->arg) == FAIL) 1804 return; 1805 redraw_tabline = TRUE; 1806 } 1807 1808 // print file name if no argument or 'F' is not in 'shortmess' 1809 if (*eap->arg == NUL || !shortmess(SHM_FILEINFO)) 1810 fileinfo(FALSE, FALSE, eap->forceit); 1811 } 1812 1813 /* 1814 * ":update". 1815 */ 1816 void 1817 ex_update(exarg_T *eap) 1818 { 1819 if (curbufIsChanged()) 1820 (void)do_write(eap); 1821 } 1822 1823 /* 1824 * ":write" and ":saveas". 1825 */ 1826 void 1827 ex_write(exarg_T *eap) 1828 { 1829 if (eap->cmdidx == CMD_saveas) 1830 { 1831 // :saveas does not take a range, uses all lines. 1832 eap->line1 = 1; 1833 eap->line2 = curbuf->b_ml.ml_line_count; 1834 } 1835 1836 if (eap->usefilter) // input lines to shell command 1837 do_bang(1, eap, FALSE, TRUE, FALSE); 1838 else 1839 (void)do_write(eap); 1840 } 1841 1842 /* 1843 * write current buffer to file 'eap->arg' 1844 * if 'eap->append' is TRUE, append to the file 1845 * 1846 * if *eap->arg == NUL write to current file 1847 * 1848 * return FAIL for failure, OK otherwise 1849 */ 1850 int 1851 do_write(exarg_T *eap) 1852 { 1853 int other; 1854 char_u *fname = NULL; // init to shut up gcc 1855 char_u *ffname; 1856 int retval = FAIL; 1857 char_u *free_fname = NULL; 1858 #ifdef FEAT_BROWSE 1859 char_u *browse_file = NULL; 1860 #endif 1861 buf_T *alt_buf = NULL; 1862 int name_was_missing; 1863 1864 if (not_writing()) // check 'write' option 1865 return FAIL; 1866 1867 ffname = eap->arg; 1868 #ifdef FEAT_BROWSE 1869 if (cmdmod.browse && !exiting) 1870 { 1871 browse_file = do_browse(BROWSE_SAVE, (char_u *)_("Save As"), ffname, 1872 NULL, NULL, NULL, curbuf); 1873 if (browse_file == NULL) 1874 goto theend; 1875 ffname = browse_file; 1876 } 1877 #endif 1878 if (*ffname == NUL) 1879 { 1880 if (eap->cmdidx == CMD_saveas) 1881 { 1882 emsg(_(e_argreq)); 1883 goto theend; 1884 } 1885 other = FALSE; 1886 } 1887 else 1888 { 1889 fname = ffname; 1890 free_fname = fix_fname(ffname); 1891 /* 1892 * When out-of-memory, keep unexpanded file name, because we MUST be 1893 * able to write the file in this situation. 1894 */ 1895 if (free_fname != NULL) 1896 ffname = free_fname; 1897 other = otherfile(ffname); 1898 } 1899 1900 /* 1901 * If we have a new file, put its name in the list of alternate file names. 1902 */ 1903 if (other) 1904 { 1905 if (vim_strchr(p_cpo, CPO_ALTWRITE) != NULL 1906 || eap->cmdidx == CMD_saveas) 1907 alt_buf = setaltfname(ffname, fname, (linenr_T)1); 1908 else 1909 alt_buf = buflist_findname(ffname); 1910 if (alt_buf != NULL && alt_buf->b_ml.ml_mfp != NULL) 1911 { 1912 // Overwriting a file that is loaded in another buffer is not a 1913 // good idea. 1914 emsg(_(e_bufloaded)); 1915 goto theend; 1916 } 1917 } 1918 1919 /* 1920 * Writing to the current file is not allowed in readonly mode 1921 * and a file name is required. 1922 * "nofile" and "nowrite" buffers cannot be written implicitly either. 1923 */ 1924 if (!other && ( 1925 #ifdef FEAT_QUICKFIX 1926 bt_dontwrite_msg(curbuf) || 1927 #endif 1928 check_fname() == FAIL || check_readonly(&eap->forceit, curbuf))) 1929 goto theend; 1930 1931 if (!other) 1932 { 1933 ffname = curbuf->b_ffname; 1934 fname = curbuf->b_fname; 1935 /* 1936 * Not writing the whole file is only allowed with '!'. 1937 */ 1938 if ( (eap->line1 != 1 1939 || eap->line2 != curbuf->b_ml.ml_line_count) 1940 && !eap->forceit 1941 && !eap->append 1942 && !p_wa) 1943 { 1944 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 1945 if (p_confirm || cmdmod.confirm) 1946 { 1947 if (vim_dialog_yesno(VIM_QUESTION, NULL, 1948 (char_u *)_("Write partial file?"), 2) != VIM_YES) 1949 goto theend; 1950 eap->forceit = TRUE; 1951 } 1952 else 1953 #endif 1954 { 1955 emsg(_("E140: Use ! to write partial buffer")); 1956 goto theend; 1957 } 1958 } 1959 } 1960 1961 if (check_overwrite(eap, curbuf, fname, ffname, other) == OK) 1962 { 1963 if (eap->cmdidx == CMD_saveas && alt_buf != NULL) 1964 { 1965 buf_T *was_curbuf = curbuf; 1966 1967 apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf); 1968 apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, alt_buf); 1969 #ifdef FEAT_EVAL 1970 if (curbuf != was_curbuf || aborting()) 1971 #else 1972 if (curbuf != was_curbuf) 1973 #endif 1974 { 1975 // buffer changed, don't change name now 1976 retval = FAIL; 1977 goto theend; 1978 } 1979 // Exchange the file names for the current and the alternate 1980 // buffer. This makes it look like we are now editing the buffer 1981 // under the new name. Must be done before buf_write(), because 1982 // if there is no file name and 'cpo' contains 'F', it will set 1983 // the file name. 1984 fname = alt_buf->b_fname; 1985 alt_buf->b_fname = curbuf->b_fname; 1986 curbuf->b_fname = fname; 1987 fname = alt_buf->b_ffname; 1988 alt_buf->b_ffname = curbuf->b_ffname; 1989 curbuf->b_ffname = fname; 1990 fname = alt_buf->b_sfname; 1991 alt_buf->b_sfname = curbuf->b_sfname; 1992 curbuf->b_sfname = fname; 1993 buf_name_changed(curbuf); 1994 1995 apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf); 1996 apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, alt_buf); 1997 if (!alt_buf->b_p_bl) 1998 { 1999 alt_buf->b_p_bl = TRUE; 2000 apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, alt_buf); 2001 } 2002 #ifdef FEAT_EVAL 2003 if (curbuf != was_curbuf || aborting()) 2004 #else 2005 if (curbuf != was_curbuf) 2006 #endif 2007 { 2008 // buffer changed, don't write the file 2009 retval = FAIL; 2010 goto theend; 2011 } 2012 2013 // If 'filetype' was empty try detecting it now. 2014 if (*curbuf->b_p_ft == NUL) 2015 { 2016 if (au_has_group((char_u *)"filetypedetect")) 2017 (void)do_doautocmd((char_u *)"filetypedetect BufRead", 2018 TRUE, NULL); 2019 do_modelines(0); 2020 } 2021 2022 // Autocommands may have changed buffer names, esp. when 2023 // 'autochdir' is set. 2024 fname = curbuf->b_sfname; 2025 } 2026 2027 name_was_missing = curbuf->b_ffname == NULL; 2028 2029 retval = buf_write(curbuf, ffname, fname, eap->line1, eap->line2, 2030 eap, eap->append, eap->forceit, TRUE, FALSE); 2031 2032 // After ":saveas fname" reset 'readonly'. 2033 if (eap->cmdidx == CMD_saveas) 2034 { 2035 if (retval == OK) 2036 { 2037 curbuf->b_p_ro = FALSE; 2038 redraw_tabline = TRUE; 2039 } 2040 } 2041 2042 // Change directories when the 'acd' option is set and the file name 2043 // got changed or set. 2044 if (eap->cmdidx == CMD_saveas || name_was_missing) 2045 DO_AUTOCHDIR; 2046 } 2047 2048 theend: 2049 #ifdef FEAT_BROWSE 2050 vim_free(browse_file); 2051 #endif 2052 vim_free(free_fname); 2053 return retval; 2054 } 2055 2056 /* 2057 * Check if it is allowed to overwrite a file. If b_flags has BF_NOTEDITED, 2058 * BF_NEW or BF_READERR, check for overwriting current file. 2059 * May set eap->forceit if a dialog says it's OK to overwrite. 2060 * Return OK if it's OK, FAIL if it is not. 2061 */ 2062 int 2063 check_overwrite( 2064 exarg_T *eap, 2065 buf_T *buf, 2066 char_u *fname, // file name to be used (can differ from 2067 // buf->ffname) 2068 char_u *ffname, // full path version of fname 2069 int other) // writing under other name 2070 { 2071 /* 2072 * Write to another file or b_flags set or not writing the whole file: 2073 * overwriting only allowed with '!'. 2074 */ 2075 if ( (other 2076 || (buf->b_flags & BF_NOTEDITED) 2077 || ((buf->b_flags & BF_NEW) 2078 && vim_strchr(p_cpo, CPO_OVERNEW) == NULL) 2079 || (buf->b_flags & BF_READERR)) 2080 && !p_wa 2081 && vim_fexists(ffname)) 2082 { 2083 if (!eap->forceit && !eap->append) 2084 { 2085 #ifdef UNIX 2086 // with UNIX it is possible to open a directory 2087 if (mch_isdir(ffname)) 2088 { 2089 semsg(_(e_isadir2), ffname); 2090 return FAIL; 2091 } 2092 #endif 2093 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 2094 if (p_confirm || cmdmod.confirm) 2095 { 2096 char_u buff[DIALOG_MSG_SIZE]; 2097 2098 dialog_msg(buff, _("Overwrite existing file \"%s\"?"), fname); 2099 if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) != VIM_YES) 2100 return FAIL; 2101 eap->forceit = TRUE; 2102 } 2103 else 2104 #endif 2105 { 2106 emsg(_(e_exists)); 2107 return FAIL; 2108 } 2109 } 2110 2111 // For ":w! filename" check that no swap file exists for "filename". 2112 if (other && !emsg_silent) 2113 { 2114 char_u *dir; 2115 char_u *p; 2116 int r; 2117 char_u *swapname; 2118 2119 // We only try the first entry in 'directory', without checking if 2120 // it's writable. If the "." directory is not writable the write 2121 // will probably fail anyway. 2122 // Use 'shortname' of the current buffer, since there is no buffer 2123 // for the written file. 2124 if (*p_dir == NUL) 2125 { 2126 dir = alloc(5); 2127 if (dir == NULL) 2128 return FAIL; 2129 STRCPY(dir, "."); 2130 } 2131 else 2132 { 2133 dir = alloc(MAXPATHL); 2134 if (dir == NULL) 2135 return FAIL; 2136 p = p_dir; 2137 copy_option_part(&p, dir, MAXPATHL, ","); 2138 } 2139 swapname = makeswapname(fname, ffname, curbuf, dir); 2140 vim_free(dir); 2141 r = vim_fexists(swapname); 2142 if (r) 2143 { 2144 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 2145 if (p_confirm || cmdmod.confirm) 2146 { 2147 char_u buff[DIALOG_MSG_SIZE]; 2148 2149 dialog_msg(buff, 2150 _("Swap file \"%s\" exists, overwrite anyway?"), 2151 swapname); 2152 if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) 2153 != VIM_YES) 2154 { 2155 vim_free(swapname); 2156 return FAIL; 2157 } 2158 eap->forceit = TRUE; 2159 } 2160 else 2161 #endif 2162 { 2163 semsg(_("E768: Swap file exists: %s (:silent! overrides)"), 2164 swapname); 2165 vim_free(swapname); 2166 return FAIL; 2167 } 2168 } 2169 vim_free(swapname); 2170 } 2171 } 2172 return OK; 2173 } 2174 2175 /* 2176 * Handle ":wnext", ":wNext" and ":wprevious" commands. 2177 */ 2178 void 2179 ex_wnext(exarg_T *eap) 2180 { 2181 int i; 2182 2183 if (eap->cmd[1] == 'n') 2184 i = curwin->w_arg_idx + (int)eap->line2; 2185 else 2186 i = curwin->w_arg_idx - (int)eap->line2; 2187 eap->line1 = 1; 2188 eap->line2 = curbuf->b_ml.ml_line_count; 2189 if (do_write(eap) != FAIL) 2190 do_argfile(eap, i); 2191 } 2192 2193 /* 2194 * ":wall", ":wqall" and ":xall": Write all changed files (and exit). 2195 */ 2196 void 2197 do_wqall(exarg_T *eap) 2198 { 2199 buf_T *buf; 2200 int error = 0; 2201 int save_forceit = eap->forceit; 2202 2203 if (eap->cmdidx == CMD_xall || eap->cmdidx == CMD_wqall) 2204 exiting = TRUE; 2205 2206 FOR_ALL_BUFFERS(buf) 2207 { 2208 #ifdef FEAT_TERMINAL 2209 if (exiting && term_job_running(buf->b_term)) 2210 { 2211 no_write_message_nobang(buf); 2212 ++error; 2213 } 2214 else 2215 #endif 2216 if (bufIsChanged(buf) && !bt_dontwrite(buf)) 2217 { 2218 /* 2219 * Check if there is a reason the buffer cannot be written: 2220 * 1. if the 'write' option is set 2221 * 2. if there is no file name (even after browsing) 2222 * 3. if the 'readonly' is set (even after a dialog) 2223 * 4. if overwriting is allowed (even after a dialog) 2224 */ 2225 if (not_writing()) 2226 { 2227 ++error; 2228 break; 2229 } 2230 #ifdef FEAT_BROWSE 2231 // ":browse wall": ask for file name if there isn't one 2232 if (buf->b_ffname == NULL && cmdmod.browse) 2233 browse_save_fname(buf); 2234 #endif 2235 if (buf->b_ffname == NULL) 2236 { 2237 semsg(_("E141: No file name for buffer %ld"), (long)buf->b_fnum); 2238 ++error; 2239 } 2240 else if (check_readonly(&eap->forceit, buf) 2241 || check_overwrite(eap, buf, buf->b_fname, buf->b_ffname, 2242 FALSE) == FAIL) 2243 { 2244 ++error; 2245 } 2246 else 2247 { 2248 bufref_T bufref; 2249 2250 set_bufref(&bufref, buf); 2251 if (buf_write_all(buf, eap->forceit) == FAIL) 2252 ++error; 2253 // an autocommand may have deleted the buffer 2254 if (!bufref_valid(&bufref)) 2255 buf = firstbuf; 2256 } 2257 eap->forceit = save_forceit; // check_overwrite() may set it 2258 } 2259 } 2260 if (exiting) 2261 { 2262 if (!error) 2263 getout(0); // exit Vim 2264 not_exiting(); 2265 } 2266 } 2267 2268 /* 2269 * Check the 'write' option. 2270 * Return TRUE and give a message when it's not set. 2271 */ 2272 static int 2273 not_writing(void) 2274 { 2275 if (p_write) 2276 return FALSE; 2277 emsg(_("E142: File not written: Writing is disabled by 'write' option")); 2278 return TRUE; 2279 } 2280 2281 /* 2282 * Check if a buffer is read-only (either 'readonly' option is set or file is 2283 * read-only). Ask for overruling in a dialog. Return TRUE and give an error 2284 * message when the buffer is readonly. 2285 */ 2286 static int 2287 check_readonly(int *forceit, buf_T *buf) 2288 { 2289 stat_T st; 2290 2291 // Handle a file being readonly when the 'readonly' option is set or when 2292 // the file exists and permissions are read-only. 2293 // We will send 0777 to check_file_readonly(), as the "perm" variable is 2294 // important for device checks but not here. 2295 if (!*forceit && (buf->b_p_ro 2296 || (mch_stat((char *)buf->b_ffname, &st) >= 0 2297 && check_file_readonly(buf->b_ffname, 0777)))) 2298 { 2299 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 2300 if ((p_confirm || cmdmod.confirm) && buf->b_fname != NULL) 2301 { 2302 char_u buff[DIALOG_MSG_SIZE]; 2303 2304 if (buf->b_p_ro) 2305 dialog_msg(buff, _("'readonly' option is set for \"%s\".\nDo you wish to write anyway?"), 2306 buf->b_fname); 2307 else 2308 dialog_msg(buff, _("File permissions of \"%s\" are read-only.\nIt may still be possible to write it.\nDo you wish to try?"), 2309 buf->b_fname); 2310 2311 if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) == VIM_YES) 2312 { 2313 // Set forceit, to force the writing of a readonly file 2314 *forceit = TRUE; 2315 return FALSE; 2316 } 2317 else 2318 return TRUE; 2319 } 2320 else 2321 #endif 2322 if (buf->b_p_ro) 2323 emsg(_(e_readonly)); 2324 else 2325 semsg(_("E505: \"%s\" is read-only (add ! to override)"), 2326 buf->b_fname); 2327 return TRUE; 2328 } 2329 2330 return FALSE; 2331 } 2332 2333 /* 2334 * Try to abandon the current file and edit a new or existing file. 2335 * "fnum" is the number of the file, if zero use "ffname_arg"/"sfname_arg". 2336 * "lnum" is the line number for the cursor in the new file (if non-zero). 2337 * 2338 * Return: 2339 * GETFILE_ERROR for "normal" error, 2340 * GETFILE_NOT_WRITTEN for "not written" error, 2341 * GETFILE_SAME_FILE for success 2342 * GETFILE_OPEN_OTHER for successfully opening another file. 2343 */ 2344 int 2345 getfile( 2346 int fnum, 2347 char_u *ffname_arg, 2348 char_u *sfname_arg, 2349 int setpm, 2350 linenr_T lnum, 2351 int forceit) 2352 { 2353 char_u *ffname = ffname_arg; 2354 char_u *sfname = sfname_arg; 2355 int other; 2356 int retval; 2357 char_u *free_me = NULL; 2358 2359 if (text_locked()) 2360 return GETFILE_ERROR; 2361 if (curbuf_locked()) 2362 return GETFILE_ERROR; 2363 2364 if (fnum == 0) 2365 { 2366 // make ffname full path, set sfname 2367 fname_expand(curbuf, &ffname, &sfname); 2368 other = otherfile(ffname); 2369 free_me = ffname; // has been allocated, free() later 2370 } 2371 else 2372 other = (fnum != curbuf->b_fnum); 2373 2374 if (other) 2375 ++no_wait_return; // don't wait for autowrite message 2376 if (other && !forceit && curbuf->b_nwindows == 1 && !buf_hide(curbuf) 2377 && curbufIsChanged() && autowrite(curbuf, forceit) == FAIL) 2378 { 2379 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 2380 if (p_confirm && p_write) 2381 dialog_changed(curbuf, FALSE); 2382 if (curbufIsChanged()) 2383 #endif 2384 { 2385 if (other) 2386 --no_wait_return; 2387 no_write_message(); 2388 retval = GETFILE_NOT_WRITTEN; // file has been changed 2389 goto theend; 2390 } 2391 } 2392 if (other) 2393 --no_wait_return; 2394 if (setpm) 2395 setpcmark(); 2396 if (!other) 2397 { 2398 if (lnum != 0) 2399 curwin->w_cursor.lnum = lnum; 2400 check_cursor_lnum(); 2401 beginline(BL_SOL | BL_FIX); 2402 retval = GETFILE_SAME_FILE; // it's in the same file 2403 } 2404 else if (do_ecmd(fnum, ffname, sfname, NULL, lnum, 2405 (buf_hide(curbuf) ? ECMD_HIDE : 0) + (forceit ? ECMD_FORCEIT : 0), 2406 curwin) == OK) 2407 retval = GETFILE_OPEN_OTHER; // opened another file 2408 else 2409 retval = GETFILE_ERROR; // error encountered 2410 2411 theend: 2412 vim_free(free_me); 2413 return retval; 2414 } 2415 2416 /* 2417 * start editing a new file 2418 * 2419 * fnum: file number; if zero use ffname/sfname 2420 * ffname: the file name 2421 * - full path if sfname used, 2422 * - any file name if sfname is NULL 2423 * - empty string to re-edit with the same file name (but may be 2424 * in a different directory) 2425 * - NULL to start an empty buffer 2426 * sfname: the short file name (or NULL) 2427 * eap: contains the command to be executed after loading the file and 2428 * forced 'ff' and 'fenc' 2429 * newlnum: if > 0: put cursor on this line number (if possible) 2430 * if ECMD_LASTL: use last position in loaded file 2431 * if ECMD_LAST: use last position in all files 2432 * if ECMD_ONE: use first line 2433 * flags: 2434 * ECMD_HIDE: if TRUE don't free the current buffer 2435 * ECMD_SET_HELP: set b_help flag of (new) buffer before opening file 2436 * ECMD_OLDBUF: use existing buffer if it exists 2437 * ECMD_FORCEIT: ! used for Ex command 2438 * ECMD_ADDBUF: don't edit, just add to buffer list 2439 * oldwin: Should be "curwin" when editing a new buffer in the current 2440 * window, NULL when splitting the window first. When not NULL info 2441 * of the previous buffer for "oldwin" is stored. 2442 * 2443 * return FAIL for failure, OK otherwise 2444 */ 2445 int 2446 do_ecmd( 2447 int fnum, 2448 char_u *ffname, 2449 char_u *sfname, 2450 exarg_T *eap, // can be NULL! 2451 linenr_T newlnum, 2452 int flags, 2453 win_T *oldwin) 2454 { 2455 int other_file; // TRUE if editing another file 2456 int oldbuf; // TRUE if using existing buffer 2457 int auto_buf = FALSE; // TRUE if autocommands brought us 2458 // into the buffer unexpectedly 2459 char_u *new_name = NULL; 2460 #if defined(FEAT_EVAL) 2461 int did_set_swapcommand = FALSE; 2462 #endif 2463 buf_T *buf; 2464 bufref_T bufref; 2465 bufref_T old_curbuf; 2466 char_u *free_fname = NULL; 2467 #ifdef FEAT_BROWSE 2468 char_u *browse_file = NULL; 2469 #endif 2470 int retval = FAIL; 2471 long n; 2472 pos_T orig_pos; 2473 linenr_T topline = 0; 2474 int newcol = -1; 2475 int solcol = -1; 2476 pos_T *pos; 2477 char_u *command = NULL; 2478 #ifdef FEAT_SPELL 2479 int did_get_winopts = FALSE; 2480 #endif 2481 int readfile_flags = 0; 2482 int did_inc_redrawing_disabled = FALSE; 2483 long *so_ptr = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so; 2484 2485 #ifdef FEAT_PROP_POPUP 2486 if (ERROR_IF_TERM_POPUP_WINDOW) 2487 return FAIL; 2488 #endif 2489 2490 if (eap != NULL) 2491 command = eap->do_ecmd_cmd; 2492 set_bufref(&old_curbuf, curbuf); 2493 2494 if (fnum != 0) 2495 { 2496 if (fnum == curbuf->b_fnum) // file is already being edited 2497 return OK; // nothing to do 2498 other_file = TRUE; 2499 } 2500 else 2501 { 2502 #ifdef FEAT_BROWSE 2503 if (cmdmod.browse && !exiting) 2504 { 2505 if ( 2506 # ifdef FEAT_GUI 2507 !gui.in_use && 2508 # endif 2509 au_has_group((char_u *)"FileExplorer")) 2510 { 2511 // No browsing supported but we do have the file explorer: 2512 // Edit the directory. 2513 if (ffname == NULL || !mch_isdir(ffname)) 2514 ffname = (char_u *)"."; 2515 } 2516 else 2517 { 2518 browse_file = do_browse(0, (char_u *)_("Edit File"), ffname, 2519 NULL, NULL, NULL, curbuf); 2520 if (browse_file == NULL) 2521 goto theend; 2522 ffname = browse_file; 2523 } 2524 } 2525 #endif 2526 // if no short name given, use ffname for short name 2527 if (sfname == NULL) 2528 sfname = ffname; 2529 #ifdef USE_FNAME_CASE 2530 if (sfname != NULL) 2531 fname_case(sfname, 0); // set correct case for sfname 2532 #endif 2533 2534 if ((flags & ECMD_ADDBUF) && (ffname == NULL || *ffname == NUL)) 2535 goto theend; 2536 2537 if (ffname == NULL) 2538 other_file = TRUE; 2539 // there is no file name 2540 else if (*ffname == NUL && curbuf->b_ffname == NULL) 2541 other_file = FALSE; 2542 else 2543 { 2544 if (*ffname == NUL) // re-edit with same file name 2545 { 2546 ffname = curbuf->b_ffname; 2547 sfname = curbuf->b_fname; 2548 } 2549 free_fname = fix_fname(ffname); // may expand to full path name 2550 if (free_fname != NULL) 2551 ffname = free_fname; 2552 other_file = otherfile(ffname); 2553 } 2554 } 2555 2556 /* 2557 * If the file was changed we may not be allowed to abandon it: 2558 * - if we are going to re-edit the same file 2559 * - or if we are the only window on this file and if ECMD_HIDE is FALSE 2560 */ 2561 if ( ((!other_file && !(flags & ECMD_OLDBUF)) 2562 || (curbuf->b_nwindows == 1 2563 && !(flags & (ECMD_HIDE | ECMD_ADDBUF)))) 2564 && check_changed(curbuf, (p_awa ? CCGD_AW : 0) 2565 | (other_file ? 0 : CCGD_MULTWIN) 2566 | ((flags & ECMD_FORCEIT) ? CCGD_FORCEIT : 0) 2567 | (eap == NULL ? 0 : CCGD_EXCMD))) 2568 { 2569 if (fnum == 0 && other_file && ffname != NULL) 2570 (void)setaltfname(ffname, sfname, newlnum < 0 ? 0 : newlnum); 2571 goto theend; 2572 } 2573 2574 /* 2575 * End Visual mode before switching to another buffer, so the text can be 2576 * copied into the GUI selection buffer. 2577 */ 2578 reset_VIsual(); 2579 2580 #if defined(FEAT_EVAL) 2581 if ((command != NULL || newlnum > (linenr_T)0) 2582 && *get_vim_var_str(VV_SWAPCOMMAND) == NUL) 2583 { 2584 int len; 2585 char_u *p; 2586 2587 // Set v:swapcommand for the SwapExists autocommands. 2588 if (command != NULL) 2589 len = (int)STRLEN(command) + 3; 2590 else 2591 len = 30; 2592 p = alloc(len); 2593 if (p != NULL) 2594 { 2595 if (command != NULL) 2596 vim_snprintf((char *)p, len, ":%s\r", command); 2597 else 2598 vim_snprintf((char *)p, len, "%ldG", (long)newlnum); 2599 set_vim_var_string(VV_SWAPCOMMAND, p, -1); 2600 did_set_swapcommand = TRUE; 2601 vim_free(p); 2602 } 2603 } 2604 #endif 2605 2606 /* 2607 * If we are starting to edit another file, open a (new) buffer. 2608 * Otherwise we re-use the current buffer. 2609 */ 2610 if (other_file) 2611 { 2612 if (!(flags & ECMD_ADDBUF)) 2613 { 2614 if (!cmdmod.keepalt) 2615 curwin->w_alt_fnum = curbuf->b_fnum; 2616 if (oldwin != NULL) 2617 buflist_altfpos(oldwin); 2618 } 2619 2620 if (fnum) 2621 buf = buflist_findnr(fnum); 2622 else 2623 { 2624 if (flags & ECMD_ADDBUF) 2625 { 2626 linenr_T tlnum = 1L; 2627 2628 if (command != NULL) 2629 { 2630 tlnum = atol((char *)command); 2631 if (tlnum <= 0) 2632 tlnum = 1L; 2633 } 2634 (void)buflist_new(ffname, sfname, tlnum, BLN_LISTED); 2635 goto theend; 2636 } 2637 buf = buflist_new(ffname, sfname, 0L, 2638 BLN_CURBUF | ((flags & ECMD_SET_HELP) ? 0 : BLN_LISTED)); 2639 2640 // autocommands may change curwin and curbuf 2641 if (oldwin != NULL) 2642 oldwin = curwin; 2643 set_bufref(&old_curbuf, curbuf); 2644 } 2645 if (buf == NULL) 2646 goto theend; 2647 if (buf->b_ml.ml_mfp == NULL) // no memfile yet 2648 { 2649 oldbuf = FALSE; 2650 } 2651 else // existing memfile 2652 { 2653 oldbuf = TRUE; 2654 set_bufref(&bufref, buf); 2655 (void)buf_check_timestamp(buf, FALSE); 2656 // Check if autocommands made the buffer invalid or changed the 2657 // current buffer. 2658 if (!bufref_valid(&bufref) || curbuf != old_curbuf.br_buf) 2659 goto theend; 2660 #ifdef FEAT_EVAL 2661 if (aborting()) // autocmds may abort script processing 2662 goto theend; 2663 #endif 2664 } 2665 2666 // May jump to last used line number for a loaded buffer or when asked 2667 // for explicitly 2668 if ((oldbuf && newlnum == ECMD_LASTL) || newlnum == ECMD_LAST) 2669 { 2670 pos = buflist_findfpos(buf); 2671 newlnum = pos->lnum; 2672 solcol = pos->col; 2673 } 2674 2675 /* 2676 * Make the (new) buffer the one used by the current window. 2677 * If the old buffer becomes unused, free it if ECMD_HIDE is FALSE. 2678 * If the current buffer was empty and has no file name, curbuf 2679 * is returned by buflist_new(), nothing to do here. 2680 */ 2681 if (buf != curbuf) 2682 { 2683 /* 2684 * Be careful: The autocommands may delete any buffer and change 2685 * the current buffer. 2686 * - If the buffer we are going to edit is deleted, give up. 2687 * - If the current buffer is deleted, prefer to load the new 2688 * buffer when loading a buffer is required. This avoids 2689 * loading another buffer which then must be closed again. 2690 * - If we ended up in the new buffer already, need to skip a few 2691 * things, set auto_buf. 2692 */ 2693 if (buf->b_fname != NULL) 2694 new_name = vim_strsave(buf->b_fname); 2695 set_bufref(&au_new_curbuf, buf); 2696 apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf); 2697 if (!bufref_valid(&au_new_curbuf)) 2698 { 2699 // new buffer has been deleted 2700 delbuf_msg(new_name); // frees new_name 2701 goto theend; 2702 } 2703 #ifdef FEAT_EVAL 2704 if (aborting()) // autocmds may abort script processing 2705 { 2706 vim_free(new_name); 2707 goto theend; 2708 } 2709 #endif 2710 if (buf == curbuf) // already in new buffer 2711 auto_buf = TRUE; 2712 else 2713 { 2714 win_T *the_curwin = curwin; 2715 2716 // Set the w_closing flag to avoid that autocommands close the 2717 // window. And set b_locked for the same reason. 2718 the_curwin->w_closing = TRUE; 2719 ++buf->b_locked; 2720 2721 if (curbuf == old_curbuf.br_buf) 2722 buf_copy_options(buf, BCO_ENTER); 2723 2724 // Close the link to the current buffer. This will set 2725 // oldwin->w_buffer to NULL. 2726 u_sync(FALSE); 2727 close_buffer(oldwin, curbuf, 2728 (flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD, FALSE, FALSE); 2729 2730 the_curwin->w_closing = FALSE; 2731 --buf->b_locked; 2732 2733 #ifdef FEAT_EVAL 2734 // autocmds may abort script processing 2735 if (aborting() && curwin->w_buffer != NULL) 2736 { 2737 vim_free(new_name); 2738 goto theend; 2739 } 2740 #endif 2741 // Be careful again, like above. 2742 if (!bufref_valid(&au_new_curbuf)) 2743 { 2744 // new buffer has been deleted 2745 delbuf_msg(new_name); // frees new_name 2746 goto theend; 2747 } 2748 if (buf == curbuf) // already in new buffer 2749 auto_buf = TRUE; 2750 else 2751 { 2752 #ifdef FEAT_SYN_HL 2753 /* 2754 * <VN> We could instead free the synblock 2755 * and re-attach to buffer, perhaps. 2756 */ 2757 if (curwin->w_buffer == NULL 2758 || curwin->w_s == &(curwin->w_buffer->b_s)) 2759 curwin->w_s = &(buf->b_s); 2760 #endif 2761 curwin->w_buffer = buf; 2762 curbuf = buf; 2763 ++curbuf->b_nwindows; 2764 2765 // Set 'fileformat', 'binary' and 'fenc' when forced. 2766 if (!oldbuf && eap != NULL) 2767 { 2768 set_file_options(TRUE, eap); 2769 set_forced_fenc(eap); 2770 } 2771 } 2772 2773 // May get the window options from the last time this buffer 2774 // was in this window (or another window). If not used 2775 // before, reset the local window options to the global 2776 // values. Also restores old folding stuff. 2777 get_winopts(curbuf); 2778 #ifdef FEAT_SPELL 2779 did_get_winopts = TRUE; 2780 #endif 2781 } 2782 vim_free(new_name); 2783 au_new_curbuf.br_buf = NULL; 2784 au_new_curbuf.br_buf_free_count = 0; 2785 } 2786 2787 curwin->w_pcmark.lnum = 1; 2788 curwin->w_pcmark.col = 0; 2789 } 2790 else // !other_file 2791 { 2792 if ((flags & ECMD_ADDBUF) || check_fname() == FAIL) 2793 goto theend; 2794 2795 oldbuf = (flags & ECMD_OLDBUF); 2796 } 2797 2798 // Don't redraw until the cursor is in the right line, otherwise 2799 // autocommands may cause ml_get errors. 2800 ++RedrawingDisabled; 2801 did_inc_redrawing_disabled = TRUE; 2802 2803 buf = curbuf; 2804 if ((flags & ECMD_SET_HELP) || keep_help_flag) 2805 { 2806 prepare_help_buffer(); 2807 } 2808 else 2809 { 2810 // Don't make a buffer listed if it's a help buffer. Useful when 2811 // using CTRL-O to go back to a help file. 2812 if (!curbuf->b_help) 2813 set_buflisted(TRUE); 2814 } 2815 2816 // If autocommands change buffers under our fingers, forget about 2817 // editing the file. 2818 if (buf != curbuf) 2819 goto theend; 2820 #ifdef FEAT_EVAL 2821 if (aborting()) // autocmds may abort script processing 2822 goto theend; 2823 #endif 2824 2825 // Since we are starting to edit a file, consider the filetype to be 2826 // unset. Helps for when an autocommand changes files and expects syntax 2827 // highlighting to work in the other file. 2828 did_filetype = FALSE; 2829 2830 /* 2831 * other_file oldbuf 2832 * FALSE FALSE re-edit same file, buffer is re-used 2833 * FALSE TRUE re-edit same file, nothing changes 2834 * TRUE FALSE start editing new file, new buffer 2835 * TRUE TRUE start editing in existing buffer (nothing to do) 2836 */ 2837 if (!other_file && !oldbuf) // re-use the buffer 2838 { 2839 set_last_cursor(curwin); // may set b_last_cursor 2840 if (newlnum == ECMD_LAST || newlnum == ECMD_LASTL) 2841 { 2842 newlnum = curwin->w_cursor.lnum; 2843 solcol = curwin->w_cursor.col; 2844 } 2845 buf = curbuf; 2846 if (buf->b_fname != NULL) 2847 new_name = vim_strsave(buf->b_fname); 2848 else 2849 new_name = NULL; 2850 set_bufref(&bufref, buf); 2851 2852 if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur) 2853 { 2854 // Save all the text, so that the reload can be undone. 2855 // Sync first so that this is a separate undo-able action. 2856 u_sync(FALSE); 2857 if (u_savecommon(0, curbuf->b_ml.ml_line_count + 1, 0, TRUE) 2858 == FAIL) 2859 { 2860 vim_free(new_name); 2861 goto theend; 2862 } 2863 u_unchanged(curbuf); 2864 buf_freeall(curbuf, BFA_KEEP_UNDO); 2865 2866 // tell readfile() not to clear or reload undo info 2867 readfile_flags = READ_KEEP_UNDO; 2868 } 2869 else 2870 buf_freeall(curbuf, 0); // free all things for buffer 2871 2872 // If autocommands deleted the buffer we were going to re-edit, give 2873 // up and jump to the end. 2874 if (!bufref_valid(&bufref)) 2875 { 2876 delbuf_msg(new_name); // frees new_name 2877 goto theend; 2878 } 2879 vim_free(new_name); 2880 2881 // If autocommands change buffers under our fingers, forget about 2882 // re-editing the file. Should do the buf_clear_file(), but perhaps 2883 // the autocommands changed the buffer... 2884 if (buf != curbuf) 2885 goto theend; 2886 #ifdef FEAT_EVAL 2887 if (aborting()) // autocmds may abort script processing 2888 goto theend; 2889 #endif 2890 buf_clear_file(curbuf); 2891 curbuf->b_op_start.lnum = 0; // clear '[ and '] marks 2892 curbuf->b_op_end.lnum = 0; 2893 } 2894 2895 /* 2896 * If we get here we are sure to start editing 2897 */ 2898 // Assume success now 2899 retval = OK; 2900 2901 /* 2902 * Check if we are editing the w_arg_idx file in the argument list. 2903 */ 2904 check_arg_idx(curwin); 2905 2906 if (!auto_buf) 2907 { 2908 /* 2909 * Set cursor and init window before reading the file and executing 2910 * autocommands. This allows for the autocommands to position the 2911 * cursor. 2912 */ 2913 curwin_init(); 2914 2915 #ifdef FEAT_FOLDING 2916 // It's possible that all lines in the buffer changed. Need to update 2917 // automatic folding for all windows where it's used. 2918 { 2919 win_T *win; 2920 tabpage_T *tp; 2921 2922 FOR_ALL_TAB_WINDOWS(tp, win) 2923 if (win->w_buffer == curbuf) 2924 foldUpdateAll(win); 2925 } 2926 #endif 2927 2928 // Change directories when the 'acd' option is set. 2929 DO_AUTOCHDIR; 2930 2931 /* 2932 * Careful: open_buffer() and apply_autocmds() may change the current 2933 * buffer and window. 2934 */ 2935 orig_pos = curwin->w_cursor; 2936 topline = curwin->w_topline; 2937 if (!oldbuf) // need to read the file 2938 { 2939 #ifdef FEAT_PROP_POPUP 2940 // Don't use the swap-exists dialog for a popup window, can't edit 2941 // the buffer. 2942 if (WIN_IS_POPUP(curwin)) 2943 curbuf->b_flags |= BF_NO_SEA; 2944 #endif 2945 swap_exists_action = SEA_DIALOG; 2946 curbuf->b_flags |= BF_CHECK_RO; // set/reset 'ro' flag 2947 2948 /* 2949 * Open the buffer and read the file. 2950 */ 2951 #if defined(FEAT_EVAL) 2952 if (should_abort(open_buffer(FALSE, eap, readfile_flags))) 2953 retval = FAIL; 2954 #else 2955 (void)open_buffer(FALSE, eap, readfile_flags); 2956 #endif 2957 2958 #ifdef FEAT_PROP_POPUP 2959 curbuf->b_flags &= ~BF_NO_SEA; 2960 #endif 2961 if (swap_exists_action == SEA_QUIT) 2962 retval = FAIL; 2963 handle_swap_exists(&old_curbuf); 2964 } 2965 else 2966 { 2967 // Read the modelines, but only to set window-local options. Any 2968 // buffer-local options have already been set and may have been 2969 // changed by the user. 2970 do_modelines(OPT_WINONLY); 2971 2972 apply_autocmds_retval(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf, 2973 &retval); 2974 apply_autocmds_retval(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf, 2975 &retval); 2976 } 2977 check_arg_idx(curwin); 2978 2979 // If autocommands change the cursor position or topline, we should 2980 // keep it. Also when it moves within a line. But not when it moves 2981 // to the first non-blank. 2982 if (!EQUAL_POS(curwin->w_cursor, orig_pos)) 2983 { 2984 char_u *text = ml_get_curline(); 2985 2986 if (curwin->w_cursor.lnum != orig_pos.lnum 2987 || curwin->w_cursor.col != (int)(skipwhite(text) - text)) 2988 { 2989 newlnum = curwin->w_cursor.lnum; 2990 newcol = curwin->w_cursor.col; 2991 } 2992 } 2993 if (curwin->w_topline == topline) 2994 topline = 0; 2995 2996 // Even when cursor didn't move we need to recompute topline. 2997 changed_line_abv_curs(); 2998 2999 #ifdef FEAT_TITLE 3000 maketitle(); 3001 #endif 3002 #if defined(FEAT_PROP_POPUP) && defined(FEAT_QUICKFIX) 3003 if (WIN_IS_POPUP(curwin) && curwin->w_p_pvw && retval != FAIL) 3004 popup_set_title(curwin); 3005 #endif 3006 } 3007 3008 #ifdef FEAT_DIFF 3009 // Tell the diff stuff that this buffer is new and/or needs updating. 3010 // Also needed when re-editing the same buffer, because unloading will 3011 // have removed it as a diff buffer. 3012 if (curwin->w_p_diff) 3013 { 3014 diff_buf_add(curbuf); 3015 diff_invalidate(curbuf); 3016 } 3017 #endif 3018 3019 #ifdef FEAT_SPELL 3020 // If the window options were changed may need to set the spell language. 3021 // Can only do this after the buffer has been properly setup. 3022 if (did_get_winopts && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) 3023 (void)did_set_spelllang(curwin); 3024 #endif 3025 3026 if (command == NULL) 3027 { 3028 if (newcol >= 0) // position set by autocommands 3029 { 3030 curwin->w_cursor.lnum = newlnum; 3031 curwin->w_cursor.col = newcol; 3032 check_cursor(); 3033 } 3034 else if (newlnum > 0) // line number from caller or old position 3035 { 3036 curwin->w_cursor.lnum = newlnum; 3037 check_cursor_lnum(); 3038 if (solcol >= 0 && !p_sol) 3039 { 3040 // 'sol' is off: Use last known column. 3041 curwin->w_cursor.col = solcol; 3042 check_cursor_col(); 3043 curwin->w_cursor.coladd = 0; 3044 curwin->w_set_curswant = TRUE; 3045 } 3046 else 3047 beginline(BL_SOL | BL_FIX); 3048 } 3049 else // no line number, go to last line in Ex mode 3050 { 3051 if (exmode_active) 3052 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 3053 beginline(BL_WHITE | BL_FIX); 3054 } 3055 } 3056 3057 // Check if cursors in other windows on the same buffer are still valid 3058 check_lnums(FALSE); 3059 3060 /* 3061 * Did not read the file, need to show some info about the file. 3062 * Do this after setting the cursor. 3063 */ 3064 if (oldbuf && !auto_buf) 3065 { 3066 int msg_scroll_save = msg_scroll; 3067 3068 // Obey the 'O' flag in 'cpoptions': overwrite any previous file 3069 // message. 3070 if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0) 3071 msg_scroll = FALSE; 3072 if (!msg_scroll) // wait a bit when overwriting an error msg 3073 check_for_delay(FALSE); 3074 msg_start(); 3075 msg_scroll = msg_scroll_save; 3076 msg_scrolled_ign = TRUE; 3077 3078 if (!shortmess(SHM_FILEINFO)) 3079 fileinfo(FALSE, TRUE, FALSE); 3080 3081 msg_scrolled_ign = FALSE; 3082 } 3083 3084 #ifdef FEAT_VIMINFO 3085 curbuf->b_last_used = vim_time(); 3086 #endif 3087 3088 if (command != NULL) 3089 do_cmdline(command, NULL, NULL, DOCMD_VERBOSE); 3090 3091 #ifdef FEAT_KEYMAP 3092 if (curbuf->b_kmap_state & KEYMAP_INIT) 3093 (void)keymap_init(); 3094 #endif 3095 3096 --RedrawingDisabled; 3097 did_inc_redrawing_disabled = FALSE; 3098 if (!skip_redraw) 3099 { 3100 n = *so_ptr; 3101 if (topline == 0 && command == NULL) 3102 *so_ptr = 9999; // force cursor halfway the window 3103 update_topline(); 3104 curwin->w_scbind_pos = curwin->w_topline; 3105 *so_ptr = n; 3106 redraw_curbuf_later(NOT_VALID); // redraw this buffer later 3107 } 3108 3109 if (p_im) 3110 need_start_insertmode = TRUE; 3111 3112 #ifdef FEAT_AUTOCHDIR 3113 // Change directories when the 'acd' option is set and we aren't already in 3114 // that directory (should already be done above). Expect getcwd() to be 3115 // faster than calling shorten_fnames() unnecessarily. 3116 if (p_acd && curbuf->b_ffname != NULL) 3117 { 3118 char_u curdir[MAXPATHL]; 3119 char_u filedir[MAXPATHL]; 3120 3121 vim_strncpy(filedir, curbuf->b_ffname, MAXPATHL - 1); 3122 *gettail_sep(filedir) = NUL; 3123 if (mch_dirname(curdir, MAXPATHL) != FAIL 3124 && vim_fnamecmp(curdir, filedir) != 0) 3125 do_autochdir(); 3126 } 3127 #endif 3128 3129 #if defined(FEAT_NETBEANS_INTG) 3130 if (curbuf->b_ffname != NULL) 3131 { 3132 # ifdef FEAT_NETBEANS_INTG 3133 if ((flags & ECMD_SET_HELP) != ECMD_SET_HELP) 3134 netbeans_file_opened(curbuf); 3135 # endif 3136 } 3137 #endif 3138 3139 theend: 3140 if (did_inc_redrawing_disabled) 3141 --RedrawingDisabled; 3142 #if defined(FEAT_EVAL) 3143 if (did_set_swapcommand) 3144 set_vim_var_string(VV_SWAPCOMMAND, NULL, -1); 3145 #endif 3146 #ifdef FEAT_BROWSE 3147 vim_free(browse_file); 3148 #endif 3149 vim_free(free_fname); 3150 return retval; 3151 } 3152 3153 static void 3154 delbuf_msg(char_u *name) 3155 { 3156 semsg(_("E143: Autocommands unexpectedly deleted new buffer %s"), 3157 name == NULL ? (char_u *)"" : name); 3158 vim_free(name); 3159 au_new_curbuf.br_buf = NULL; 3160 au_new_curbuf.br_buf_free_count = 0; 3161 } 3162 3163 static int append_indent = 0; // autoindent for first line 3164 3165 /* 3166 * ":insert" and ":append", also used by ":change" 3167 */ 3168 void 3169 ex_append(exarg_T *eap) 3170 { 3171 char_u *theline; 3172 int did_undo = FALSE; 3173 linenr_T lnum = eap->line2; 3174 int indent = 0; 3175 char_u *p; 3176 int vcol; 3177 int empty = (curbuf->b_ml.ml_flags & ML_EMPTY); 3178 3179 #ifdef FEAT_EVAL 3180 if (not_in_vim9(eap) == FAIL) 3181 return; 3182 #endif 3183 // the ! flag toggles autoindent 3184 if (eap->forceit) 3185 curbuf->b_p_ai = !curbuf->b_p_ai; 3186 3187 // First autoindent comes from the line we start on 3188 if (eap->cmdidx != CMD_change && curbuf->b_p_ai && lnum > 0) 3189 append_indent = get_indent_lnum(lnum); 3190 3191 if (eap->cmdidx != CMD_append) 3192 --lnum; 3193 3194 // when the buffer is empty need to delete the dummy line 3195 if (empty && lnum == 1) 3196 lnum = 0; 3197 3198 State = INSERT; // behave like in Insert mode 3199 if (curbuf->b_p_iminsert == B_IMODE_LMAP) 3200 State |= LANGMAP; 3201 3202 for (;;) 3203 { 3204 msg_scroll = TRUE; 3205 need_wait_return = FALSE; 3206 if (curbuf->b_p_ai) 3207 { 3208 if (append_indent >= 0) 3209 { 3210 indent = append_indent; 3211 append_indent = -1; 3212 } 3213 else if (lnum > 0) 3214 indent = get_indent_lnum(lnum); 3215 } 3216 ex_keep_indent = FALSE; 3217 if (eap->getline == NULL) 3218 { 3219 // No getline() function, use the lines that follow. This ends 3220 // when there is no more. 3221 if (eap->nextcmd == NULL || *eap->nextcmd == NUL) 3222 break; 3223 p = vim_strchr(eap->nextcmd, NL); 3224 if (p == NULL) 3225 p = eap->nextcmd + STRLEN(eap->nextcmd); 3226 theline = vim_strnsave(eap->nextcmd, p - eap->nextcmd); 3227 if (*p != NUL) 3228 ++p; 3229 eap->nextcmd = p; 3230 } 3231 else 3232 { 3233 int save_State = State; 3234 3235 // Set State to avoid the cursor shape to be set to INSERT mode 3236 // when getline() returns. 3237 State = CMDLINE; 3238 theline = eap->getline( 3239 #ifdef FEAT_EVAL 3240 eap->cstack->cs_looplevel > 0 ? -1 : 3241 #endif 3242 NUL, eap->cookie, indent, TRUE); 3243 State = save_State; 3244 } 3245 lines_left = Rows - 1; 3246 if (theline == NULL) 3247 break; 3248 3249 // Using ^ CTRL-D in getexmodeline() makes us repeat the indent. 3250 if (ex_keep_indent) 3251 append_indent = indent; 3252 3253 // Look for the "." after automatic indent. 3254 vcol = 0; 3255 for (p = theline; indent > vcol; ++p) 3256 { 3257 if (*p == ' ') 3258 ++vcol; 3259 else if (*p == TAB) 3260 vcol += 8 - vcol % 8; 3261 else 3262 break; 3263 } 3264 if ((p[0] == '.' && p[1] == NUL) 3265 || (!did_undo && u_save(lnum, lnum + 1 + (empty ? 1 : 0)) 3266 == FAIL)) 3267 { 3268 vim_free(theline); 3269 break; 3270 } 3271 3272 // don't use autoindent if nothing was typed. 3273 if (p[0] == NUL) 3274 theline[0] = NUL; 3275 3276 did_undo = TRUE; 3277 ml_append(lnum, theline, (colnr_T)0, FALSE); 3278 appended_lines_mark(lnum + (empty ? 1 : 0), 1L); 3279 3280 vim_free(theline); 3281 ++lnum; 3282 3283 if (empty) 3284 { 3285 ml_delete(2L); 3286 empty = FALSE; 3287 } 3288 } 3289 State = NORMAL; 3290 3291 if (eap->forceit) 3292 curbuf->b_p_ai = !curbuf->b_p_ai; 3293 3294 // "start" is set to eap->line2+1 unless that position is invalid (when 3295 // eap->line2 pointed to the end of the buffer and nothing was appended) 3296 // "end" is set to lnum when something has been appended, otherwise 3297 // it is the same than "start" -- Acevedo 3298 if (!cmdmod.lockmarks) 3299 { 3300 curbuf->b_op_start.lnum = (eap->line2 < curbuf->b_ml.ml_line_count) ? 3301 eap->line2 + 1 : curbuf->b_ml.ml_line_count; 3302 if (eap->cmdidx != CMD_append) 3303 --curbuf->b_op_start.lnum; 3304 curbuf->b_op_end.lnum = (eap->line2 < lnum) 3305 ? lnum : curbuf->b_op_start.lnum; 3306 curbuf->b_op_start.col = curbuf->b_op_end.col = 0; 3307 } 3308 curwin->w_cursor.lnum = lnum; 3309 check_cursor_lnum(); 3310 beginline(BL_SOL | BL_FIX); 3311 3312 need_wait_return = FALSE; // don't use wait_return() now 3313 ex_no_reprint = TRUE; 3314 } 3315 3316 /* 3317 * ":change" 3318 */ 3319 void 3320 ex_change(exarg_T *eap) 3321 { 3322 linenr_T lnum; 3323 3324 #ifdef FEAT_EVAL 3325 if (not_in_vim9(eap) == FAIL) 3326 return; 3327 #endif 3328 if (eap->line2 >= eap->line1 3329 && u_save(eap->line1 - 1, eap->line2 + 1) == FAIL) 3330 return; 3331 3332 // the ! flag toggles autoindent 3333 if (eap->forceit ? !curbuf->b_p_ai : curbuf->b_p_ai) 3334 append_indent = get_indent_lnum(eap->line1); 3335 3336 for (lnum = eap->line2; lnum >= eap->line1; --lnum) 3337 { 3338 if (curbuf->b_ml.ml_flags & ML_EMPTY) // nothing to delete 3339 break; 3340 ml_delete(eap->line1); 3341 } 3342 3343 // make sure the cursor is not beyond the end of the file now 3344 check_cursor_lnum(); 3345 deleted_lines_mark(eap->line1, (long)(eap->line2 - lnum)); 3346 3347 // ":append" on the line above the deleted lines. 3348 eap->line2 = eap->line1; 3349 ex_append(eap); 3350 } 3351 3352 void 3353 ex_z(exarg_T *eap) 3354 { 3355 char_u *x; 3356 long bigness; 3357 char_u *kind; 3358 int minus = 0; 3359 linenr_T start, end, curs, i; 3360 int j; 3361 linenr_T lnum = eap->line2; 3362 3363 // Vi compatible: ":z!" uses display height, without a count uses 3364 // 'scroll' 3365 if (eap->forceit) 3366 bigness = curwin->w_height; 3367 else if (!ONE_WINDOW) 3368 bigness = curwin->w_height - 3; 3369 else 3370 bigness = curwin->w_p_scr * 2; 3371 if (bigness < 1) 3372 bigness = 1; 3373 3374 x = eap->arg; 3375 kind = x; 3376 if (*kind == '-' || *kind == '+' || *kind == '=' 3377 || *kind == '^' || *kind == '.') 3378 ++x; 3379 while (*x == '-' || *x == '+') 3380 ++x; 3381 3382 if (*x != 0) 3383 { 3384 if (!VIM_ISDIGIT(*x)) 3385 { 3386 emsg(_("E144: non-numeric argument to :z")); 3387 return; 3388 } 3389 else 3390 { 3391 bigness = atol((char *)x); 3392 3393 // bigness could be < 0 if atol(x) overflows. 3394 if (bigness > 2 * curbuf->b_ml.ml_line_count || bigness < 0) 3395 bigness = 2 * curbuf->b_ml.ml_line_count; 3396 3397 p_window = bigness; 3398 if (*kind == '=') 3399 bigness += 2; 3400 } 3401 } 3402 3403 // the number of '-' and '+' multiplies the distance 3404 if (*kind == '-' || *kind == '+') 3405 for (x = kind + 1; *x == *kind; ++x) 3406 ; 3407 3408 switch (*kind) 3409 { 3410 case '-': 3411 start = lnum - bigness * (linenr_T)(x - kind) + 1; 3412 end = start + bigness - 1; 3413 curs = end; 3414 break; 3415 3416 case '=': 3417 start = lnum - (bigness + 1) / 2 + 1; 3418 end = lnum + (bigness + 1) / 2 - 1; 3419 curs = lnum; 3420 minus = 1; 3421 break; 3422 3423 case '^': 3424 start = lnum - bigness * 2; 3425 end = lnum - bigness; 3426 curs = lnum - bigness; 3427 break; 3428 3429 case '.': 3430 start = lnum - (bigness + 1) / 2 + 1; 3431 end = lnum + (bigness + 1) / 2 - 1; 3432 curs = end; 3433 break; 3434 3435 default: // '+' 3436 start = lnum; 3437 if (*kind == '+') 3438 start += bigness * (linenr_T)(x - kind - 1) + 1; 3439 else if (eap->addr_count == 0) 3440 ++start; 3441 end = start + bigness - 1; 3442 curs = end; 3443 break; 3444 } 3445 3446 if (start < 1) 3447 start = 1; 3448 3449 if (end > curbuf->b_ml.ml_line_count) 3450 end = curbuf->b_ml.ml_line_count; 3451 3452 if (curs > curbuf->b_ml.ml_line_count) 3453 curs = curbuf->b_ml.ml_line_count; 3454 else if (curs < 1) 3455 curs = 1; 3456 3457 for (i = start; i <= end; i++) 3458 { 3459 if (minus && i == lnum) 3460 { 3461 msg_putchar('\n'); 3462 3463 for (j = 1; j < Columns; j++) 3464 msg_putchar('-'); 3465 } 3466 3467 print_line(i, eap->flags & EXFLAG_NR, eap->flags & EXFLAG_LIST); 3468 3469 if (minus && i == lnum) 3470 { 3471 msg_putchar('\n'); 3472 3473 for (j = 1; j < Columns; j++) 3474 msg_putchar('-'); 3475 } 3476 } 3477 3478 if (curwin->w_cursor.lnum != curs) 3479 { 3480 curwin->w_cursor.lnum = curs; 3481 curwin->w_cursor.col = 0; 3482 } 3483 ex_no_reprint = TRUE; 3484 } 3485 3486 /* 3487 * Check if the restricted flag is set. 3488 * If so, give an error message and return TRUE. 3489 * Otherwise, return FALSE. 3490 */ 3491 int 3492 check_restricted(void) 3493 { 3494 if (restricted) 3495 { 3496 emsg(_("E145: Shell commands and some functionality not allowed in rvim")); 3497 return TRUE; 3498 } 3499 return FALSE; 3500 } 3501 3502 /* 3503 * Check if the secure flag is set (.exrc or .vimrc in current directory). 3504 * If so, give an error message and return TRUE. 3505 * Otherwise, return FALSE. 3506 */ 3507 int 3508 check_secure(void) 3509 { 3510 if (secure) 3511 { 3512 secure = 2; 3513 emsg(_(e_curdir)); 3514 return TRUE; 3515 } 3516 #ifdef HAVE_SANDBOX 3517 /* 3518 * In the sandbox more things are not allowed, including the things 3519 * disallowed in secure mode. 3520 */ 3521 if (sandbox != 0) 3522 { 3523 emsg(_(e_sandbox)); 3524 return TRUE; 3525 } 3526 #endif 3527 return FALSE; 3528 } 3529 3530 static char_u *old_sub = NULL; // previous substitute pattern 3531 static int global_need_beginline; // call beginline() after ":g" 3532 3533 /* 3534 * Flags that are kept between calls to :substitute. 3535 */ 3536 typedef struct { 3537 int do_all; // do multiple substitutions per line 3538 int do_ask; // ask for confirmation 3539 int do_count; // count only 3540 int do_error; // if false, ignore errors 3541 int do_print; // print last line with subs. 3542 int do_list; // list last line with subs. 3543 int do_number; // list last line with line nr 3544 int do_ic; // ignore case flag 3545 } subflags_T; 3546 3547 /* 3548 * Perform a substitution from line eap->line1 to line eap->line2 using the 3549 * command pointed to by eap->arg which should be of the form: 3550 * 3551 * /pattern/substitution/{flags} 3552 * 3553 * The usual escapes are supported as described in the regexp docs. 3554 */ 3555 void 3556 do_sub(exarg_T *eap) 3557 { 3558 linenr_T lnum; 3559 long i = 0; 3560 regmmatch_T regmatch; 3561 static subflags_T subflags = {FALSE, FALSE, FALSE, TRUE, FALSE, 3562 FALSE, FALSE, 0}; 3563 #ifdef FEAT_EVAL 3564 subflags_T subflags_save; 3565 #endif 3566 int save_do_all; // remember user specified 'g' flag 3567 int save_do_ask; // remember user specified 'c' flag 3568 char_u *pat = NULL, *sub = NULL; // init for GCC 3569 int delimiter; 3570 int sublen; 3571 int got_quit = FALSE; 3572 int got_match = FALSE; 3573 int temp; 3574 int which_pat; 3575 char_u *cmd; 3576 int save_State; 3577 linenr_T first_line = 0; // first changed line 3578 linenr_T last_line= 0; // below last changed line AFTER the 3579 // change 3580 linenr_T old_line_count = curbuf->b_ml.ml_line_count; 3581 linenr_T line2; 3582 long nmatch; // number of lines in match 3583 char_u *sub_firstline; // allocated copy of first sub line 3584 int endcolumn = FALSE; // cursor in last column when done 3585 pos_T old_cursor = curwin->w_cursor; 3586 int start_nsubs; 3587 #ifdef FEAT_EVAL 3588 int save_ma = 0; 3589 #endif 3590 3591 cmd = eap->arg; 3592 if (!global_busy) 3593 { 3594 sub_nsubs = 0; 3595 sub_nlines = 0; 3596 } 3597 start_nsubs = sub_nsubs; 3598 3599 if (eap->cmdidx == CMD_tilde) 3600 which_pat = RE_LAST; // use last used regexp 3601 else 3602 which_pat = RE_SUBST; // use last substitute regexp 3603 3604 // new pattern and substitution 3605 if (eap->cmd[0] == 's' && *cmd != NUL && !VIM_ISWHITE(*cmd) 3606 && vim_strchr((char_u *)"0123456789cegriIp|\"", *cmd) == NULL) 3607 { 3608 // don't accept alphanumeric for separator 3609 if (isalpha(*cmd)) 3610 { 3611 emsg(_("E146: Regular expressions can't be delimited by letters")); 3612 return; 3613 } 3614 /* 3615 * undocumented vi feature: 3616 * "\/sub/" and "\?sub?" use last used search pattern (almost like 3617 * //sub/r). "\&sub&" use last substitute pattern (like //sub/). 3618 */ 3619 if (*cmd == '\\') 3620 { 3621 ++cmd; 3622 if (vim_strchr((char_u *)"/?&", *cmd) == NULL) 3623 { 3624 emsg(_(e_backslash)); 3625 return; 3626 } 3627 if (*cmd != '&') 3628 which_pat = RE_SEARCH; // use last '/' pattern 3629 pat = (char_u *)""; // empty search pattern 3630 delimiter = *cmd++; // remember delimiter character 3631 } 3632 else // find the end of the regexp 3633 { 3634 which_pat = RE_LAST; // use last used regexp 3635 delimiter = *cmd++; // remember delimiter character 3636 pat = cmd; // remember start of search pat 3637 cmd = skip_regexp_ex(cmd, delimiter, p_magic, &eap->arg, NULL); 3638 if (cmd[0] == delimiter) // end delimiter found 3639 *cmd++ = NUL; // replace it with a NUL 3640 } 3641 3642 /* 3643 * Small incompatibility: vi sees '\n' as end of the command, but in 3644 * Vim we want to use '\n' to find/substitute a NUL. 3645 */ 3646 sub = cmd; // remember the start of the substitution 3647 3648 while (cmd[0]) 3649 { 3650 if (cmd[0] == delimiter) // end delimiter found 3651 { 3652 *cmd++ = NUL; // replace it with a NUL 3653 break; 3654 } 3655 if (cmd[0] == '\\' && cmd[1] != 0) // skip escaped characters 3656 ++cmd; 3657 MB_PTR_ADV(cmd); 3658 } 3659 3660 if (!eap->skip) 3661 { 3662 // In POSIX vi ":s/pat/%/" uses the previous subst. string. 3663 if (STRCMP(sub, "%") == 0 3664 && vim_strchr(p_cpo, CPO_SUBPERCENT) != NULL) 3665 { 3666 if (old_sub == NULL) // there is no previous command 3667 { 3668 emsg(_(e_nopresub)); 3669 return; 3670 } 3671 sub = old_sub; 3672 } 3673 else 3674 { 3675 vim_free(old_sub); 3676 old_sub = vim_strsave(sub); 3677 } 3678 } 3679 } 3680 else if (!eap->skip) // use previous pattern and substitution 3681 { 3682 if (old_sub == NULL) // there is no previous command 3683 { 3684 emsg(_(e_nopresub)); 3685 return; 3686 } 3687 pat = NULL; // search_regcomp() will use previous pattern 3688 sub = old_sub; 3689 3690 // Vi compatibility quirk: repeating with ":s" keeps the cursor in the 3691 // last column after using "$". 3692 endcolumn = (curwin->w_curswant == MAXCOL); 3693 } 3694 3695 // Recognize ":%s/\n//" and turn it into a join command, which is much 3696 // more efficient. 3697 // TODO: find a generic solution to make line-joining operations more 3698 // efficient, avoid allocating a string that grows in size. 3699 if (pat != NULL && STRCMP(pat, "\\n") == 0 3700 && *sub == NUL 3701 && (*cmd == NUL || (cmd[1] == NUL && (*cmd == 'g' || *cmd == 'l' 3702 || *cmd == 'p' || *cmd == '#')))) 3703 { 3704 linenr_T joined_lines_count; 3705 3706 curwin->w_cursor.lnum = eap->line1; 3707 if (*cmd == 'l') 3708 eap->flags = EXFLAG_LIST; 3709 else if (*cmd == '#') 3710 eap->flags = EXFLAG_NR; 3711 else if (*cmd == 'p') 3712 eap->flags = EXFLAG_PRINT; 3713 3714 // The number of lines joined is the number of lines in the range plus 3715 // one. One less when the last line is included. 3716 joined_lines_count = eap->line2 - eap->line1 + 1; 3717 if (eap->line2 < curbuf->b_ml.ml_line_count) 3718 ++joined_lines_count; 3719 if (joined_lines_count > 1) 3720 { 3721 (void)do_join(joined_lines_count, FALSE, TRUE, FALSE, TRUE); 3722 sub_nsubs = joined_lines_count - 1; 3723 sub_nlines = 1; 3724 (void)do_sub_msg(FALSE); 3725 ex_may_print(eap); 3726 } 3727 3728 if (!cmdmod.keeppatterns) 3729 save_re_pat(RE_SUBST, pat, p_magic); 3730 // put pattern in history 3731 add_to_history(HIST_SEARCH, pat, TRUE, NUL); 3732 3733 return; 3734 } 3735 3736 /* 3737 * Find trailing options. When '&' is used, keep old options. 3738 */ 3739 if (*cmd == '&') 3740 ++cmd; 3741 else 3742 { 3743 if (!p_ed) 3744 { 3745 if (p_gd) // default is global on 3746 subflags.do_all = TRUE; 3747 else 3748 subflags.do_all = FALSE; 3749 subflags.do_ask = FALSE; 3750 } 3751 subflags.do_error = TRUE; 3752 subflags.do_print = FALSE; 3753 subflags.do_list = FALSE; 3754 subflags.do_count = FALSE; 3755 subflags.do_number = FALSE; 3756 subflags.do_ic = 0; 3757 } 3758 while (*cmd) 3759 { 3760 /* 3761 * Note that 'g' and 'c' are always inverted, also when p_ed is off. 3762 * 'r' is never inverted. 3763 */ 3764 if (*cmd == 'g') 3765 subflags.do_all = !subflags.do_all; 3766 else if (*cmd == 'c') 3767 subflags.do_ask = !subflags.do_ask; 3768 else if (*cmd == 'n') 3769 subflags.do_count = TRUE; 3770 else if (*cmd == 'e') 3771 subflags.do_error = !subflags.do_error; 3772 else if (*cmd == 'r') // use last used regexp 3773 which_pat = RE_LAST; 3774 else if (*cmd == 'p') 3775 subflags.do_print = TRUE; 3776 else if (*cmd == '#') 3777 { 3778 subflags.do_print = TRUE; 3779 subflags.do_number = TRUE; 3780 } 3781 else if (*cmd == 'l') 3782 { 3783 subflags.do_print = TRUE; 3784 subflags.do_list = TRUE; 3785 } 3786 else if (*cmd == 'i') // ignore case 3787 subflags.do_ic = 'i'; 3788 else if (*cmd == 'I') // don't ignore case 3789 subflags.do_ic = 'I'; 3790 else 3791 break; 3792 ++cmd; 3793 } 3794 if (subflags.do_count) 3795 subflags.do_ask = FALSE; 3796 3797 save_do_all = subflags.do_all; 3798 save_do_ask = subflags.do_ask; 3799 3800 /* 3801 * check for a trailing count 3802 */ 3803 cmd = skipwhite(cmd); 3804 if (VIM_ISDIGIT(*cmd)) 3805 { 3806 i = getdigits(&cmd); 3807 if (i <= 0 && !eap->skip && subflags.do_error) 3808 { 3809 emsg(_(e_zerocount)); 3810 return; 3811 } 3812 eap->line1 = eap->line2; 3813 eap->line2 += i - 1; 3814 if (eap->line2 > curbuf->b_ml.ml_line_count) 3815 eap->line2 = curbuf->b_ml.ml_line_count; 3816 } 3817 3818 /* 3819 * check for trailing command or garbage 3820 */ 3821 cmd = skipwhite(cmd); 3822 if (*cmd && *cmd != '"') // if not end-of-line or comment 3823 { 3824 eap->nextcmd = check_nextcmd(cmd); 3825 if (eap->nextcmd == NULL) 3826 { 3827 semsg(_(e_trailing_arg), cmd); 3828 return; 3829 } 3830 } 3831 3832 if (eap->skip) // not executing commands, only parsing 3833 return; 3834 3835 if (!subflags.do_count && !curbuf->b_p_ma) 3836 { 3837 // Substitution is not allowed in non-'modifiable' buffer 3838 emsg(_(e_modifiable)); 3839 return; 3840 } 3841 3842 if (search_regcomp(pat, RE_SUBST, which_pat, SEARCH_HIS, ®match) == FAIL) 3843 { 3844 if (subflags.do_error) 3845 emsg(_(e_invcmd)); 3846 return; 3847 } 3848 3849 // the 'i' or 'I' flag overrules 'ignorecase' and 'smartcase' 3850 if (subflags.do_ic == 'i') 3851 regmatch.rmm_ic = TRUE; 3852 else if (subflags.do_ic == 'I') 3853 regmatch.rmm_ic = FALSE; 3854 3855 sub_firstline = NULL; 3856 3857 /* 3858 * ~ in the substitute pattern is replaced with the old pattern. 3859 * We do it here once to avoid it to be replaced over and over again. 3860 * But don't do it when it starts with "\=", then it's an expression. 3861 */ 3862 if (!(sub[0] == '\\' && sub[1] == '=')) 3863 sub = regtilde(sub, p_magic); 3864 3865 /* 3866 * Check for a match on each line. 3867 */ 3868 line2 = eap->line2; 3869 for (lnum = eap->line1; lnum <= line2 && !(got_quit 3870 #if defined(FEAT_EVAL) 3871 || aborting() 3872 #endif 3873 ); ++lnum) 3874 { 3875 nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum, 3876 (colnr_T)0, NULL, NULL); 3877 if (nmatch) 3878 { 3879 colnr_T copycol; 3880 colnr_T matchcol; 3881 colnr_T prev_matchcol = MAXCOL; 3882 char_u *new_end, *new_start = NULL; 3883 unsigned new_start_len = 0; 3884 char_u *p1; 3885 int did_sub = FALSE; 3886 int lastone; 3887 int len, copy_len, needed_len; 3888 long nmatch_tl = 0; // nr of lines matched below lnum 3889 int do_again; // do it again after joining lines 3890 int skip_match = FALSE; 3891 linenr_T sub_firstlnum; // nr of first sub line 3892 #ifdef FEAT_PROP_POPUP 3893 int apc_flags = APC_SAVE_FOR_UNDO | APC_SUBSTITUTE; 3894 colnr_T total_added = 0; 3895 #endif 3896 3897 /* 3898 * The new text is build up step by step, to avoid too much 3899 * copying. There are these pieces: 3900 * sub_firstline The old text, unmodified. 3901 * copycol Column in the old text where we started 3902 * looking for a match; from here old text still 3903 * needs to be copied to the new text. 3904 * matchcol Column number of the old text where to look 3905 * for the next match. It's just after the 3906 * previous match or one further. 3907 * prev_matchcol Column just after the previous match (if any). 3908 * Mostly equal to matchcol, except for the first 3909 * match and after skipping an empty match. 3910 * regmatch.*pos Where the pattern matched in the old text. 3911 * new_start The new text, all that has been produced so 3912 * far. 3913 * new_end The new text, where to append new text. 3914 * 3915 * lnum The line number where we found the start of 3916 * the match. Can be below the line we searched 3917 * when there is a \n before a \zs in the 3918 * pattern. 3919 * sub_firstlnum The line number in the buffer where to look 3920 * for a match. Can be different from "lnum" 3921 * when the pattern or substitute string contains 3922 * line breaks. 3923 * 3924 * Special situations: 3925 * - When the substitute string contains a line break, the part up 3926 * to the line break is inserted in the text, but the copy of 3927 * the original line is kept. "sub_firstlnum" is adjusted for 3928 * the inserted lines. 3929 * - When the matched pattern contains a line break, the old line 3930 * is taken from the line at the end of the pattern. The lines 3931 * in the match are deleted later, "sub_firstlnum" is adjusted 3932 * accordingly. 3933 * 3934 * The new text is built up in new_start[]. It has some extra 3935 * room to avoid using alloc()/free() too often. new_start_len is 3936 * the length of the allocated memory at new_start. 3937 * 3938 * Make a copy of the old line, so it won't be taken away when 3939 * updating the screen or handling a multi-line match. The "old_" 3940 * pointers point into this copy. 3941 */ 3942 sub_firstlnum = lnum; 3943 copycol = 0; 3944 matchcol = 0; 3945 3946 // At first match, remember current cursor position. 3947 if (!got_match) 3948 { 3949 setpcmark(); 3950 got_match = TRUE; 3951 } 3952 3953 /* 3954 * Loop until nothing more to replace in this line. 3955 * 1. Handle match with empty string. 3956 * 2. If do_ask is set, ask for confirmation. 3957 * 3. substitute the string. 3958 * 4. if do_all is set, find next match 3959 * 5. break if there isn't another match in this line 3960 */ 3961 for (;;) 3962 { 3963 // Advance "lnum" to the line where the match starts. The 3964 // match does not start in the first line when there is a line 3965 // break before \zs. 3966 if (regmatch.startpos[0].lnum > 0) 3967 { 3968 lnum += regmatch.startpos[0].lnum; 3969 sub_firstlnum += regmatch.startpos[0].lnum; 3970 nmatch -= regmatch.startpos[0].lnum; 3971 VIM_CLEAR(sub_firstline); 3972 } 3973 3974 // Match might be after the last line for "\n\zs" matching at 3975 // the end of the last line. 3976 if (lnum > curbuf->b_ml.ml_line_count) 3977 break; 3978 3979 if (sub_firstline == NULL) 3980 { 3981 sub_firstline = vim_strsave(ml_get(sub_firstlnum)); 3982 if (sub_firstline == NULL) 3983 { 3984 vim_free(new_start); 3985 goto outofmem; 3986 } 3987 } 3988 3989 // Save the line number of the last change for the final 3990 // cursor position (just like Vi). 3991 curwin->w_cursor.lnum = lnum; 3992 do_again = FALSE; 3993 3994 /* 3995 * 1. Match empty string does not count, except for first 3996 * match. This reproduces the strange vi behaviour. 3997 * This also catches endless loops. 3998 */ 3999 if (matchcol == prev_matchcol 4000 && regmatch.endpos[0].lnum == 0 4001 && matchcol == regmatch.endpos[0].col) 4002 { 4003 if (sub_firstline[matchcol] == NUL) 4004 // We already were at the end of the line. Don't look 4005 // for a match in this line again. 4006 skip_match = TRUE; 4007 else 4008 { 4009 // search for a match at next column 4010 if (has_mbyte) 4011 matchcol += mb_ptr2len(sub_firstline + matchcol); 4012 else 4013 ++matchcol; 4014 } 4015 goto skip; 4016 } 4017 4018 // Normally we continue searching for a match just after the 4019 // previous match. 4020 matchcol = regmatch.endpos[0].col; 4021 prev_matchcol = matchcol; 4022 4023 /* 4024 * 2. If do_count is set only increase the counter. 4025 * If do_ask is set, ask for confirmation. 4026 */ 4027 if (subflags.do_count) 4028 { 4029 // For a multi-line match, put matchcol at the NUL at 4030 // the end of the line and set nmatch to one, so that 4031 // we continue looking for a match on the next line. 4032 // Avoids that ":s/\nB\@=//gc" get stuck. 4033 if (nmatch > 1) 4034 { 4035 matchcol = (colnr_T)STRLEN(sub_firstline); 4036 nmatch = 1; 4037 skip_match = TRUE; 4038 } 4039 sub_nsubs++; 4040 did_sub = TRUE; 4041 #ifdef FEAT_EVAL 4042 // Skip the substitution, unless an expression is used, 4043 // then it is evaluated in the sandbox. 4044 if (!(sub[0] == '\\' && sub[1] == '=')) 4045 #endif 4046 goto skip; 4047 } 4048 4049 if (subflags.do_ask) 4050 { 4051 int typed = 0; 4052 4053 // change State to CONFIRM, so that the mouse works 4054 // properly 4055 save_State = State; 4056 State = CONFIRM; 4057 setmouse(); // disable mouse in xterm 4058 curwin->w_cursor.col = regmatch.startpos[0].col; 4059 if (curwin->w_p_crb) 4060 do_check_cursorbind(); 4061 4062 // When 'cpoptions' contains "u" don't sync undo when 4063 // asking for confirmation. 4064 if (vim_strchr(p_cpo, CPO_UNDO) != NULL) 4065 ++no_u_sync; 4066 4067 /* 4068 * Loop until 'y', 'n', 'q', CTRL-E or CTRL-Y typed. 4069 */ 4070 while (subflags.do_ask) 4071 { 4072 if (exmode_active) 4073 { 4074 char_u *resp; 4075 colnr_T sc, ec; 4076 4077 print_line_no_prefix(lnum, 4078 subflags.do_number, subflags.do_list); 4079 4080 getvcol(curwin, &curwin->w_cursor, &sc, NULL, NULL); 4081 curwin->w_cursor.col = regmatch.endpos[0].col - 1; 4082 if (curwin->w_cursor.col < 0) 4083 curwin->w_cursor.col = 0; 4084 getvcol(curwin, &curwin->w_cursor, NULL, NULL, &ec); 4085 if (subflags.do_number || curwin->w_p_nu) 4086 { 4087 int numw = number_width(curwin) + 1; 4088 sc += numw; 4089 ec += numw; 4090 } 4091 msg_start(); 4092 for (i = 0; i < (long)sc; ++i) 4093 msg_putchar(' '); 4094 for ( ; i <= (long)ec; ++i) 4095 msg_putchar('^'); 4096 4097 resp = getexmodeline('?', NULL, 0, TRUE); 4098 if (resp != NULL) 4099 { 4100 typed = *resp; 4101 vim_free(resp); 4102 } 4103 } 4104 else 4105 { 4106 char_u *orig_line = NULL; 4107 int len_change = 0; 4108 #ifdef FEAT_FOLDING 4109 int save_p_fen = curwin->w_p_fen; 4110 4111 curwin->w_p_fen = FALSE; 4112 #endif 4113 // Invert the matched string. 4114 // Remove the inversion afterwards. 4115 temp = RedrawingDisabled; 4116 RedrawingDisabled = 0; 4117 4118 if (new_start != NULL) 4119 { 4120 // There already was a substitution, we would 4121 // like to show this to the user. We cannot 4122 // really update the line, it would change 4123 // what matches. Temporarily replace the line 4124 // and change it back afterwards. 4125 orig_line = vim_strsave(ml_get(lnum)); 4126 if (orig_line != NULL) 4127 { 4128 char_u *new_line = concat_str(new_start, 4129 sub_firstline + copycol); 4130 4131 if (new_line == NULL) 4132 VIM_CLEAR(orig_line); 4133 else 4134 { 4135 // Position the cursor relative to the 4136 // end of the line, the previous 4137 // substitute may have inserted or 4138 // deleted characters before the 4139 // cursor. 4140 len_change = (int)STRLEN(new_line) 4141 - (int)STRLEN(orig_line); 4142 curwin->w_cursor.col += len_change; 4143 ml_replace(lnum, new_line, FALSE); 4144 } 4145 } 4146 } 4147 4148 search_match_lines = regmatch.endpos[0].lnum 4149 - regmatch.startpos[0].lnum; 4150 search_match_endcol = regmatch.endpos[0].col 4151 + len_change; 4152 highlight_match = TRUE; 4153 4154 update_topline(); 4155 validate_cursor(); 4156 update_screen(SOME_VALID); 4157 highlight_match = FALSE; 4158 redraw_later(SOME_VALID); 4159 4160 #ifdef FEAT_FOLDING 4161 curwin->w_p_fen = save_p_fen; 4162 #endif 4163 if (msg_row == Rows - 1) 4164 msg_didout = FALSE; // avoid a scroll-up 4165 msg_starthere(); 4166 i = msg_scroll; 4167 msg_scroll = 0; // truncate msg when 4168 // needed 4169 msg_no_more = TRUE; 4170 // write message same highlighting as for 4171 // wait_return 4172 smsg_attr(HL_ATTR(HLF_R), 4173 _("replace with %s (y/n/a/q/l/^E/^Y)?"), sub); 4174 msg_no_more = FALSE; 4175 msg_scroll = i; 4176 showruler(TRUE); 4177 windgoto(msg_row, msg_col); 4178 RedrawingDisabled = temp; 4179 4180 #ifdef USE_ON_FLY_SCROLL 4181 dont_scroll = FALSE; // allow scrolling here 4182 #endif 4183 ++no_mapping; // don't map this key 4184 ++allow_keys; // allow special keys 4185 typed = plain_vgetc(); 4186 --allow_keys; 4187 --no_mapping; 4188 4189 // clear the question 4190 msg_didout = FALSE; // don't scroll up 4191 msg_col = 0; 4192 gotocmdline(TRUE); 4193 4194 // restore the line 4195 if (orig_line != NULL) 4196 ml_replace(lnum, orig_line, FALSE); 4197 } 4198 4199 need_wait_return = FALSE; // no hit-return prompt 4200 if (typed == 'q' || typed == ESC || typed == Ctrl_C 4201 #ifdef UNIX 4202 || typed == intr_char 4203 #endif 4204 ) 4205 { 4206 got_quit = TRUE; 4207 break; 4208 } 4209 if (typed == 'n') 4210 break; 4211 if (typed == 'y') 4212 break; 4213 if (typed == 'l') 4214 { 4215 // last: replace and then stop 4216 subflags.do_all = FALSE; 4217 line2 = lnum; 4218 break; 4219 } 4220 if (typed == 'a') 4221 { 4222 subflags.do_ask = FALSE; 4223 break; 4224 } 4225 if (typed == Ctrl_E) 4226 scrollup_clamp(); 4227 else if (typed == Ctrl_Y) 4228 scrolldown_clamp(); 4229 } 4230 State = save_State; 4231 setmouse(); 4232 if (vim_strchr(p_cpo, CPO_UNDO) != NULL) 4233 --no_u_sync; 4234 4235 if (typed == 'n') 4236 { 4237 // For a multi-line match, put matchcol at the NUL at 4238 // the end of the line and set nmatch to one, so that 4239 // we continue looking for a match on the next line. 4240 // Avoids that ":%s/\nB\@=//gc" and ":%s/\n/,\r/gc" 4241 // get stuck when pressing 'n'. 4242 if (nmatch > 1) 4243 { 4244 matchcol = (colnr_T)STRLEN(sub_firstline); 4245 skip_match = TRUE; 4246 } 4247 goto skip; 4248 } 4249 if (got_quit) 4250 goto skip; 4251 } 4252 4253 // Move the cursor to the start of the match, so that we can 4254 // use "\=col("."). 4255 curwin->w_cursor.col = regmatch.startpos[0].col; 4256 4257 /* 4258 * 3. substitute the string. 4259 */ 4260 #ifdef FEAT_EVAL 4261 save_ma = curbuf->b_p_ma; 4262 if (subflags.do_count) 4263 { 4264 // prevent accidentally changing the buffer by a function 4265 curbuf->b_p_ma = FALSE; 4266 sandbox++; 4267 } 4268 // Save flags for recursion. They can change for e.g. 4269 // :s/^/\=execute("s#^##gn") 4270 subflags_save = subflags; 4271 #endif 4272 // get length of substitution part 4273 sublen = vim_regsub_multi(®match, 4274 sub_firstlnum - regmatch.startpos[0].lnum, 4275 sub, sub_firstline, FALSE, p_magic, TRUE); 4276 #ifdef FEAT_EVAL 4277 // If getting the substitute string caused an error, don't do 4278 // the replacement. 4279 // Don't keep flags set by a recursive call. 4280 subflags = subflags_save; 4281 if (aborting() || subflags.do_count) 4282 { 4283 curbuf->b_p_ma = save_ma; 4284 if (sandbox > 0) 4285 sandbox--; 4286 goto skip; 4287 } 4288 #endif 4289 4290 // When the match included the "$" of the last line it may 4291 // go beyond the last line of the buffer. 4292 if (nmatch > curbuf->b_ml.ml_line_count - sub_firstlnum + 1) 4293 { 4294 nmatch = curbuf->b_ml.ml_line_count - sub_firstlnum + 1; 4295 skip_match = TRUE; 4296 } 4297 4298 // Need room for: 4299 // - result so far in new_start (not for first sub in line) 4300 // - original text up to match 4301 // - length of substituted part 4302 // - original text after match 4303 // Adjust text properties here, since we have all information 4304 // needed. 4305 if (nmatch == 1) 4306 { 4307 p1 = sub_firstline; 4308 #ifdef FEAT_PROP_POPUP 4309 if (curbuf->b_has_textprop) 4310 { 4311 int bytes_added = sublen - 1 - (regmatch.endpos[0].col 4312 - regmatch.startpos[0].col); 4313 4314 // When text properties are changed, need to save for 4315 // undo first, unless done already. 4316 if (adjust_prop_columns(lnum, 4317 total_added + regmatch.startpos[0].col, 4318 bytes_added, apc_flags)) 4319 apc_flags &= ~APC_SAVE_FOR_UNDO; 4320 // Offset for column byte number of the text property 4321 // in the resulting buffer afterwards. 4322 total_added += bytes_added; 4323 } 4324 #endif 4325 } 4326 else 4327 { 4328 p1 = ml_get(sub_firstlnum + nmatch - 1); 4329 nmatch_tl += nmatch - 1; 4330 } 4331 copy_len = regmatch.startpos[0].col - copycol; 4332 needed_len = copy_len + ((unsigned)STRLEN(p1) 4333 - regmatch.endpos[0].col) + sublen + 1; 4334 if (new_start == NULL) 4335 { 4336 /* 4337 * Get some space for a temporary buffer to do the 4338 * substitution into (and some extra space to avoid 4339 * too many calls to alloc()/free()). 4340 */ 4341 new_start_len = needed_len + 50; 4342 if ((new_start = alloc(new_start_len)) == NULL) 4343 goto outofmem; 4344 *new_start = NUL; 4345 new_end = new_start; 4346 } 4347 else 4348 { 4349 /* 4350 * Check if the temporary buffer is long enough to do the 4351 * substitution into. If not, make it larger (with a bit 4352 * extra to avoid too many calls to alloc()/free()). 4353 */ 4354 len = (unsigned)STRLEN(new_start); 4355 needed_len += len; 4356 if (needed_len > (int)new_start_len) 4357 { 4358 new_start_len = needed_len + 50; 4359 if ((p1 = alloc(new_start_len)) == NULL) 4360 { 4361 vim_free(new_start); 4362 goto outofmem; 4363 } 4364 mch_memmove(p1, new_start, (size_t)(len + 1)); 4365 vim_free(new_start); 4366 new_start = p1; 4367 } 4368 new_end = new_start + len; 4369 } 4370 4371 /* 4372 * copy the text up to the part that matched 4373 */ 4374 mch_memmove(new_end, sub_firstline + copycol, (size_t)copy_len); 4375 new_end += copy_len; 4376 4377 (void)vim_regsub_multi(®match, 4378 sub_firstlnum - regmatch.startpos[0].lnum, 4379 sub, new_end, TRUE, p_magic, TRUE); 4380 sub_nsubs++; 4381 did_sub = TRUE; 4382 4383 // Move the cursor to the start of the line, to avoid that it 4384 // is beyond the end of the line after the substitution. 4385 curwin->w_cursor.col = 0; 4386 4387 // For a multi-line match, make a copy of the last matched 4388 // line and continue in that one. 4389 if (nmatch > 1) 4390 { 4391 sub_firstlnum += nmatch - 1; 4392 vim_free(sub_firstline); 4393 sub_firstline = vim_strsave(ml_get(sub_firstlnum)); 4394 // When going beyond the last line, stop substituting. 4395 if (sub_firstlnum <= line2) 4396 do_again = TRUE; 4397 else 4398 subflags.do_all = FALSE; 4399 } 4400 4401 // Remember next character to be copied. 4402 copycol = regmatch.endpos[0].col; 4403 4404 if (skip_match) 4405 { 4406 // Already hit end of the buffer, sub_firstlnum is one 4407 // less than what it ought to be. 4408 vim_free(sub_firstline); 4409 sub_firstline = vim_strsave((char_u *)""); 4410 copycol = 0; 4411 } 4412 4413 /* 4414 * Now the trick is to replace CTRL-M chars with a real line 4415 * break. This would make it impossible to insert a CTRL-M in 4416 * the text. The line break can be avoided by preceding the 4417 * CTRL-M with a backslash. To be able to insert a backslash, 4418 * they must be doubled in the string and are halved here. 4419 * That is Vi compatible. 4420 */ 4421 for (p1 = new_end; *p1; ++p1) 4422 { 4423 if (p1[0] == '\\' && p1[1] != NUL) // remove backslash 4424 { 4425 STRMOVE(p1, p1 + 1); 4426 #ifdef FEAT_PROP_POPUP 4427 if (curbuf->b_has_textprop) 4428 { 4429 // When text properties are changed, need to save 4430 // for undo first, unless done already. 4431 if (adjust_prop_columns(lnum, 4432 (colnr_T)(p1 - new_start), -1, 4433 apc_flags)) 4434 apc_flags &= ~APC_SAVE_FOR_UNDO; 4435 } 4436 #endif 4437 } 4438 else if (*p1 == CAR) 4439 { 4440 if (u_inssub(lnum) == OK) // prepare for undo 4441 { 4442 colnr_T plen = (colnr_T)(p1 - new_start + 1); 4443 4444 *p1 = NUL; // truncate up to the CR 4445 ml_append(lnum - 1, new_start, plen, FALSE); 4446 mark_adjust(lnum + 1, (linenr_T)MAXLNUM, 1L, 0L); 4447 if (subflags.do_ask) 4448 appended_lines(lnum - 1, 1L); 4449 else 4450 { 4451 if (first_line == 0) 4452 first_line = lnum; 4453 last_line = lnum + 1; 4454 } 4455 #ifdef FEAT_PROP_POPUP 4456 adjust_props_for_split(lnum + 1, lnum, plen, 1); 4457 #endif 4458 // all line numbers increase 4459 ++sub_firstlnum; 4460 ++lnum; 4461 ++line2; 4462 // move the cursor to the new line, like Vi 4463 ++curwin->w_cursor.lnum; 4464 // copy the rest 4465 STRMOVE(new_start, p1 + 1); 4466 p1 = new_start - 1; 4467 } 4468 } 4469 else if (has_mbyte) 4470 p1 += (*mb_ptr2len)(p1) - 1; 4471 } 4472 4473 /* 4474 * 4. If do_all is set, find next match. 4475 * Prevent endless loop with patterns that match empty 4476 * strings, e.g. :s/$/pat/g or :s/[a-z]* /(&)/g. 4477 * But ":s/\n/#/" is OK. 4478 */ 4479 skip: 4480 // We already know that we did the last subst when we are at 4481 // the end of the line, except that a pattern like 4482 // "bar\|\nfoo" may match at the NUL. "lnum" can be below 4483 // "line2" when there is a \zs in the pattern after a line 4484 // break. 4485 lastone = (skip_match 4486 || got_int 4487 || got_quit 4488 || lnum > line2 4489 || !(subflags.do_all || do_again) 4490 || (sub_firstline[matchcol] == NUL && nmatch <= 1 4491 && !re_multiline(regmatch.regprog))); 4492 nmatch = -1; 4493 4494 /* 4495 * Replace the line in the buffer when needed. This is 4496 * skipped when there are more matches. 4497 * The check for nmatch_tl is needed for when multi-line 4498 * matching must replace the lines before trying to do another 4499 * match, otherwise "\@<=" won't work. 4500 * When the match starts below where we start searching also 4501 * need to replace the line first (using \zs after \n). 4502 */ 4503 if (lastone 4504 || nmatch_tl > 0 4505 || (nmatch = vim_regexec_multi(®match, curwin, 4506 curbuf, sub_firstlnum, 4507 matchcol, NULL, NULL)) == 0 4508 || regmatch.startpos[0].lnum > 0) 4509 { 4510 if (new_start != NULL) 4511 { 4512 /* 4513 * Copy the rest of the line, that didn't match. 4514 * "matchcol" has to be adjusted, we use the end of 4515 * the line as reference, because the substitute may 4516 * have changed the number of characters. Same for 4517 * "prev_matchcol". 4518 */ 4519 STRCAT(new_start, sub_firstline + copycol); 4520 matchcol = (colnr_T)STRLEN(sub_firstline) - matchcol; 4521 prev_matchcol = (colnr_T)STRLEN(sub_firstline) 4522 - prev_matchcol; 4523 4524 if (u_savesub(lnum) != OK) 4525 break; 4526 ml_replace(lnum, new_start, TRUE); 4527 4528 if (nmatch_tl > 0) 4529 { 4530 /* 4531 * Matched lines have now been substituted and are 4532 * useless, delete them. The part after the match 4533 * has been appended to new_start, we don't need 4534 * it in the buffer. 4535 */ 4536 ++lnum; 4537 if (u_savedel(lnum, nmatch_tl) != OK) 4538 break; 4539 for (i = 0; i < nmatch_tl; ++i) 4540 ml_delete(lnum); 4541 mark_adjust(lnum, lnum + nmatch_tl - 1, 4542 (long)MAXLNUM, -nmatch_tl); 4543 if (subflags.do_ask) 4544 deleted_lines(lnum, nmatch_tl); 4545 --lnum; 4546 line2 -= nmatch_tl; // nr of lines decreases 4547 nmatch_tl = 0; 4548 } 4549 4550 // When asking, undo is saved each time, must also set 4551 // changed flag each time. 4552 if (subflags.do_ask) 4553 changed_bytes(lnum, 0); 4554 else 4555 { 4556 if (first_line == 0) 4557 first_line = lnum; 4558 last_line = lnum + 1; 4559 } 4560 4561 sub_firstlnum = lnum; 4562 vim_free(sub_firstline); // free the temp buffer 4563 sub_firstline = new_start; 4564 new_start = NULL; 4565 matchcol = (colnr_T)STRLEN(sub_firstline) - matchcol; 4566 prev_matchcol = (colnr_T)STRLEN(sub_firstline) 4567 - prev_matchcol; 4568 copycol = 0; 4569 } 4570 if (nmatch == -1 && !lastone) 4571 nmatch = vim_regexec_multi(®match, curwin, curbuf, 4572 sub_firstlnum, matchcol, NULL, NULL); 4573 4574 /* 4575 * 5. break if there isn't another match in this line 4576 */ 4577 if (nmatch <= 0) 4578 { 4579 // If the match found didn't start where we were 4580 // searching, do the next search in the line where we 4581 // found the match. 4582 if (nmatch == -1) 4583 lnum -= regmatch.startpos[0].lnum; 4584 break; 4585 } 4586 } 4587 4588 line_breakcheck(); 4589 } 4590 4591 if (did_sub) 4592 ++sub_nlines; 4593 vim_free(new_start); // for when substitute was cancelled 4594 VIM_CLEAR(sub_firstline); // free the copy of the original line 4595 } 4596 4597 line_breakcheck(); 4598 } 4599 4600 if (first_line != 0) 4601 { 4602 // Need to subtract the number of added lines from "last_line" to get 4603 // the line number before the change (same as adding the number of 4604 // deleted lines). 4605 i = curbuf->b_ml.ml_line_count - old_line_count; 4606 changed_lines(first_line, 0, last_line - i, i); 4607 } 4608 4609 outofmem: 4610 vim_free(sub_firstline); // may have to free allocated copy of the line 4611 4612 // ":s/pat//n" doesn't move the cursor 4613 if (subflags.do_count) 4614 curwin->w_cursor = old_cursor; 4615 4616 if (sub_nsubs > start_nsubs) 4617 { 4618 if (!cmdmod.lockmarks) 4619 { 4620 // Set the '[ and '] marks. 4621 curbuf->b_op_start.lnum = eap->line1; 4622 curbuf->b_op_end.lnum = line2; 4623 curbuf->b_op_start.col = curbuf->b_op_end.col = 0; 4624 } 4625 4626 if (!global_busy) 4627 { 4628 // when interactive leave cursor on the match 4629 if (!subflags.do_ask) 4630 { 4631 if (endcolumn) 4632 coladvance((colnr_T)MAXCOL); 4633 else 4634 beginline(BL_WHITE | BL_FIX); 4635 } 4636 if (!do_sub_msg(subflags.do_count) && subflags.do_ask) 4637 msg(""); 4638 } 4639 else 4640 global_need_beginline = TRUE; 4641 if (subflags.do_print) 4642 print_line(curwin->w_cursor.lnum, 4643 subflags.do_number, subflags.do_list); 4644 } 4645 else if (!global_busy) 4646 { 4647 if (got_int) // interrupted 4648 emsg(_(e_interr)); 4649 else if (got_match) // did find something but nothing substituted 4650 msg(""); 4651 else if (subflags.do_error) // nothing found 4652 semsg(_(e_patnotf2), get_search_pat()); 4653 } 4654 4655 #ifdef FEAT_FOLDING 4656 if (subflags.do_ask && hasAnyFolding(curwin)) 4657 // Cursor position may require updating 4658 changed_window_setting(); 4659 #endif 4660 4661 vim_regfree(regmatch.regprog); 4662 4663 // Restore the flag values, they can be used for ":&&". 4664 subflags.do_all = save_do_all; 4665 subflags.do_ask = save_do_ask; 4666 } 4667 4668 /* 4669 * Give message for number of substitutions. 4670 * Can also be used after a ":global" command. 4671 * Return TRUE if a message was given. 4672 */ 4673 int 4674 do_sub_msg( 4675 int count_only) // used 'n' flag for ":s" 4676 { 4677 /* 4678 * Only report substitutions when: 4679 * - more than 'report' substitutions 4680 * - command was typed by user, or number of changed lines > 'report' 4681 * - giving messages is not disabled by 'lazyredraw' 4682 */ 4683 if (((sub_nsubs > p_report && (KeyTyped || sub_nlines > 1 || p_report < 1)) 4684 || count_only) 4685 && messaging()) 4686 { 4687 char *msg_single; 4688 char *msg_plural; 4689 4690 if (got_int) 4691 STRCPY(msg_buf, _("(Interrupted) ")); 4692 else 4693 *msg_buf = NUL; 4694 4695 msg_single = count_only 4696 ? NGETTEXT("%ld match on %ld line", 4697 "%ld matches on %ld line", sub_nsubs) 4698 : NGETTEXT("%ld substitution on %ld line", 4699 "%ld substitutions on %ld line", sub_nsubs); 4700 msg_plural = count_only 4701 ? NGETTEXT("%ld match on %ld lines", 4702 "%ld matches on %ld lines", sub_nsubs) 4703 : NGETTEXT("%ld substitution on %ld lines", 4704 "%ld substitutions on %ld lines", sub_nsubs); 4705 4706 vim_snprintf_add(msg_buf, sizeof(msg_buf), 4707 NGETTEXT(msg_single, msg_plural, sub_nlines), 4708 sub_nsubs, (long)sub_nlines); 4709 4710 if (msg(msg_buf)) 4711 // save message to display it after redraw 4712 set_keep_msg((char_u *)msg_buf, 0); 4713 return TRUE; 4714 } 4715 if (got_int) 4716 { 4717 emsg(_(e_interr)); 4718 return TRUE; 4719 } 4720 return FALSE; 4721 } 4722 4723 static void 4724 global_exe_one(char_u *cmd, linenr_T lnum) 4725 { 4726 curwin->w_cursor.lnum = lnum; 4727 curwin->w_cursor.col = 0; 4728 if (*cmd == NUL || *cmd == '\n') 4729 do_cmdline((char_u *)"p", NULL, NULL, DOCMD_NOWAIT); 4730 else 4731 do_cmdline(cmd, NULL, NULL, DOCMD_NOWAIT); 4732 } 4733 4734 /* 4735 * Execute a global command of the form: 4736 * 4737 * g/pattern/X : execute X on all lines where pattern matches 4738 * v/pattern/X : execute X on all lines where pattern does not match 4739 * 4740 * where 'X' is an EX command 4741 * 4742 * The command character (as well as the trailing slash) is optional, and 4743 * is assumed to be 'p' if missing. 4744 * 4745 * This is implemented in two passes: first we scan the file for the pattern and 4746 * set a mark for each line that (not) matches. Secondly we execute the command 4747 * for each line that has a mark. This is required because after deleting 4748 * lines we do not know where to search for the next match. 4749 */ 4750 void 4751 ex_global(exarg_T *eap) 4752 { 4753 linenr_T lnum; // line number according to old situation 4754 int ndone = 0; 4755 int type; // first char of cmd: 'v' or 'g' 4756 char_u *cmd; // command argument 4757 4758 char_u delim; // delimiter, normally '/' 4759 char_u *pat; 4760 regmmatch_T regmatch; 4761 int match; 4762 int which_pat; 4763 4764 // When nesting the command works on one line. This allows for 4765 // ":g/found/v/notfound/command". 4766 if (global_busy && (eap->line1 != 1 4767 || eap->line2 != curbuf->b_ml.ml_line_count)) 4768 { 4769 // will increment global_busy to break out of the loop 4770 emsg(_("E147: Cannot do :global recursive with a range")); 4771 return; 4772 } 4773 4774 if (eap->forceit) // ":global!" is like ":vglobal" 4775 type = 'v'; 4776 else 4777 type = *eap->cmd; 4778 cmd = eap->arg; 4779 which_pat = RE_LAST; // default: use last used regexp 4780 4781 /* 4782 * undocumented vi feature: 4783 * "\/" and "\?": use previous search pattern. 4784 * "\&": use previous substitute pattern. 4785 */ 4786 if (*cmd == '\\') 4787 { 4788 ++cmd; 4789 if (vim_strchr((char_u *)"/?&", *cmd) == NULL) 4790 { 4791 emsg(_(e_backslash)); 4792 return; 4793 } 4794 if (*cmd == '&') 4795 which_pat = RE_SUBST; // use previous substitute pattern 4796 else 4797 which_pat = RE_SEARCH; // use previous search pattern 4798 ++cmd; 4799 pat = (char_u *)""; 4800 } 4801 else if (*cmd == NUL) 4802 { 4803 emsg(_("E148: Regular expression missing from global")); 4804 return; 4805 } 4806 else 4807 { 4808 delim = *cmd; // get the delimiter 4809 if (delim) 4810 ++cmd; // skip delimiter if there is one 4811 pat = cmd; // remember start of pattern 4812 cmd = skip_regexp_ex(cmd, delim, p_magic, &eap->arg, NULL); 4813 if (cmd[0] == delim) // end delimiter found 4814 *cmd++ = NUL; // replace it with a NUL 4815 } 4816 4817 if (search_regcomp(pat, RE_BOTH, which_pat, SEARCH_HIS, ®match) == FAIL) 4818 { 4819 emsg(_(e_invcmd)); 4820 return; 4821 } 4822 4823 if (global_busy) 4824 { 4825 lnum = curwin->w_cursor.lnum; 4826 match = vim_regexec_multi(®match, curwin, curbuf, lnum, 4827 (colnr_T)0, NULL, NULL); 4828 if ((type == 'g' && match) || (type == 'v' && !match)) 4829 global_exe_one(cmd, lnum); 4830 } 4831 else 4832 { 4833 /* 4834 * pass 1: set marks for each (not) matching line 4835 */ 4836 for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum) 4837 { 4838 // a match on this line? 4839 match = vim_regexec_multi(®match, curwin, curbuf, lnum, 4840 (colnr_T)0, NULL, NULL); 4841 if ((type == 'g' && match) || (type == 'v' && !match)) 4842 { 4843 ml_setmarked(lnum); 4844 ndone++; 4845 } 4846 line_breakcheck(); 4847 } 4848 4849 /* 4850 * pass 2: execute the command for each line that has been marked 4851 */ 4852 if (got_int) 4853 msg(_(e_interr)); 4854 else if (ndone == 0) 4855 { 4856 if (type == 'v') 4857 smsg(_("Pattern found in every line: %s"), pat); 4858 else 4859 smsg(_("Pattern not found: %s"), pat); 4860 } 4861 else 4862 { 4863 #ifdef FEAT_CLIPBOARD 4864 start_global_changes(); 4865 #endif 4866 global_exe(cmd); 4867 #ifdef FEAT_CLIPBOARD 4868 end_global_changes(); 4869 #endif 4870 } 4871 4872 ml_clearmarked(); // clear rest of the marks 4873 } 4874 4875 vim_regfree(regmatch.regprog); 4876 } 4877 4878 /* 4879 * Execute "cmd" on lines marked with ml_setmarked(). 4880 */ 4881 void 4882 global_exe(char_u *cmd) 4883 { 4884 linenr_T old_lcount; // b_ml.ml_line_count before the command 4885 buf_T *old_buf = curbuf; // remember what buffer we started in 4886 linenr_T lnum; // line number according to old situation 4887 4888 /* 4889 * Set current position only once for a global command. 4890 * If global_busy is set, setpcmark() will not do anything. 4891 * If there is an error, global_busy will be incremented. 4892 */ 4893 setpcmark(); 4894 4895 // When the command writes a message, don't overwrite the command. 4896 msg_didout = TRUE; 4897 4898 sub_nsubs = 0; 4899 sub_nlines = 0; 4900 global_need_beginline = FALSE; 4901 global_busy = 1; 4902 old_lcount = curbuf->b_ml.ml_line_count; 4903 while (!got_int && (lnum = ml_firstmarked()) != 0 && global_busy == 1) 4904 { 4905 global_exe_one(cmd, lnum); 4906 ui_breakcheck(); 4907 } 4908 4909 global_busy = 0; 4910 if (global_need_beginline) 4911 beginline(BL_WHITE | BL_FIX); 4912 else 4913 check_cursor(); // cursor may be beyond the end of the line 4914 4915 // the cursor may not have moved in the text but a change in a previous 4916 // line may move it on the screen 4917 changed_line_abv_curs(); 4918 4919 // If it looks like no message was written, allow overwriting the 4920 // command with the report for number of changes. 4921 if (msg_col == 0 && msg_scrolled == 0) 4922 msg_didout = FALSE; 4923 4924 // If substitutes done, report number of substitutes, otherwise report 4925 // number of extra or deleted lines. 4926 // Don't report extra or deleted lines in the edge case where the buffer 4927 // we are in after execution is different from the buffer we started in. 4928 if (!do_sub_msg(FALSE) && curbuf == old_buf) 4929 msgmore(curbuf->b_ml.ml_line_count - old_lcount); 4930 } 4931 4932 #ifdef FEAT_VIMINFO 4933 /* 4934 * Get the previous substitute pattern. 4935 */ 4936 char_u * 4937 get_old_sub(void) 4938 { 4939 return old_sub; 4940 } 4941 4942 /* 4943 * Set the previous substitute pattern. "val" must be allocated. 4944 */ 4945 void 4946 set_old_sub(char_u *val) 4947 { 4948 vim_free(old_sub); 4949 old_sub = val; 4950 } 4951 #endif // FEAT_VIMINFO 4952 4953 #if defined(EXITFREE) || defined(PROTO) 4954 void 4955 free_old_sub(void) 4956 { 4957 vim_free(old_sub); 4958 } 4959 #endif 4960 4961 #if defined(FEAT_QUICKFIX) || defined(PROTO) 4962 /* 4963 * Set up for a tagpreview. 4964 * Makes the preview window the current window. 4965 * Return TRUE when it was created. 4966 */ 4967 int 4968 prepare_tagpreview( 4969 int undo_sync, // sync undo when leaving the window 4970 int use_previewpopup, // use popup if 'previewpopup' set 4971 use_popup_T use_popup) // use other popup window 4972 { 4973 win_T *wp; 4974 4975 # ifdef FEAT_GUI 4976 need_mouse_correct = TRUE; 4977 # endif 4978 4979 /* 4980 * If there is already a preview window open, use that one. 4981 */ 4982 if (!curwin->w_p_pvw) 4983 { 4984 # ifdef FEAT_PROP_POPUP 4985 if (use_previewpopup && *p_pvp != NUL) 4986 { 4987 wp = popup_find_preview_window(); 4988 if (wp != NULL) 4989 popup_set_wantpos_cursor(wp, wp->w_minwidth, NULL); 4990 } 4991 else if (use_popup != USEPOPUP_NONE) 4992 { 4993 wp = popup_find_info_window(); 4994 if (wp != NULL) 4995 { 4996 if (use_popup == USEPOPUP_NORMAL) 4997 popup_show(wp); 4998 else 4999 popup_hide(wp); 5000 // When the popup moves or resizes it may reveal part of 5001 // another window. TODO: can this be done more efficiently? 5002 redraw_all_later(NOT_VALID); 5003 } 5004 } 5005 else 5006 # endif 5007 { 5008 FOR_ALL_WINDOWS(wp) 5009 if (wp->w_p_pvw) 5010 break; 5011 } 5012 if (wp != NULL) 5013 win_enter(wp, undo_sync); 5014 else 5015 { 5016 /* 5017 * There is no preview window open yet. Create one. 5018 */ 5019 # ifdef FEAT_PROP_POPUP 5020 if ((use_previewpopup && *p_pvp != NUL) 5021 || use_popup != USEPOPUP_NONE) 5022 return popup_create_preview_window(use_popup != USEPOPUP_NONE); 5023 # endif 5024 if (win_split(g_do_tagpreview > 0 ? g_do_tagpreview : 0, 0) == FAIL) 5025 return FALSE; 5026 curwin->w_p_pvw = TRUE; 5027 curwin->w_p_wfh = TRUE; 5028 RESET_BINDING(curwin); // don't take over 'scrollbind' 5029 // and 'cursorbind' 5030 # ifdef FEAT_DIFF 5031 curwin->w_p_diff = FALSE; // no 'diff' 5032 # endif 5033 # ifdef FEAT_FOLDING 5034 curwin->w_p_fdc = 0; // no 'foldcolumn' 5035 # endif 5036 return TRUE; 5037 } 5038 } 5039 return FALSE; 5040 } 5041 5042 #endif 5043 5044 /* 5045 * Make the user happy. 5046 */ 5047 void 5048 ex_smile(exarg_T *eap UNUSED) 5049 { 5050 static char *code[] = { 5051 "\34 \4o\14$\4ox\30 \2o\30$\1ox\25 \2o\36$\1o\11 \1o\1$\3 \2$\1 \1o\1$x\5 \1o\1 \1$\1 \2o\10 \1o\44$\1o\7 \2$\1 \2$\1 \2$\1o\1$x\2 \2o\1 \1$\1 \1$\1 \1\"\1$\6 \1o\11$\4 \15$\4 \11$\1o\7 \3$\1o\2$\1o\1$x\2 \1\"\6$\1o\1$\5 \1o\11$\6 \13$\6 \12$\1o\4 \10$x\4 \7$\4 \13$\6 \13$\6 \27$x\4 \27$\4 \15$\4 \16$\2 \3\"\3$x\5 \1\"\3$\4\"\61$\5 \1\"\3$x\6 \3$\3 \1o\62$\5 \1\"\3$\1ox\5 \1o\2$\1\"\3 \63$\7 \3$\1ox\5 \3$\4 \55$\1\"\1 \1\"\6$", 5052 "\5o\4$\1ox\4 \1o\3$\4o\5$\2 \45$\3 \1o\21$x\4 \10$\1\"\4$\3 \42$\5 \4$\10\"x\3 \4\"\7 \4$\4 \1\"\34$\1\"\6 \1o\3$x\16 \1\"\3$\1o\5 \3\"\22$\1\"\2$\1\"\11 \3$x\20 \3$\1o\12 \1\"\2$\2\"\6$\4\"\13 \1o\3$x\21 \4$\1o\40 \1o\3$\1\"x\22 \1\"\4$\1o\6 \1o\6$\1o\1\"\4$\1o\10 \1o\4$x\24 \1\"\5$\2o\5 \2\"\4$\1o\5$\1o\3 \1o\4$\2\"x\27 \2\"\5$\4o\2 \1\"\3$\1o\11$\3\"x\32 \2\"\7$\2o\1 \12$x\42 \4\"\13$x\46 \14$x\47 \12$\1\"x\50 \1\"\3$\4\"x" 5053 }; 5054 char *p; 5055 int n; 5056 int i; 5057 5058 msg_start(); 5059 msg_putchar('\n'); 5060 for (i = 0; i < 2; ++i) 5061 for (p = code[i]; *p != NUL; ++p) 5062 if (*p == 'x') 5063 msg_putchar('\n'); 5064 else 5065 for (n = *p++; n > 0; --n) 5066 if (*p == 'o' || *p == '$') 5067 msg_putchar_attr(*p, HL_ATTR(HLF_L)); 5068 else 5069 msg_putchar(*p); 5070 msg_clr_eos(); 5071 } 5072 5073 /* 5074 * ":drop" 5075 * Opens the first argument in a window. When there are two or more arguments 5076 * the argument list is redefined. 5077 */ 5078 void 5079 ex_drop(exarg_T *eap) 5080 { 5081 int split = FALSE; 5082 win_T *wp; 5083 buf_T *buf; 5084 tabpage_T *tp; 5085 5086 if (ERROR_IF_POPUP_WINDOW || ERROR_IF_TERM_POPUP_WINDOW) 5087 return; 5088 5089 /* 5090 * Check if the first argument is already being edited in a window. If 5091 * so, jump to that window. 5092 * We would actually need to check all arguments, but that's complicated 5093 * and mostly only one file is dropped. 5094 * This also ignores wildcards, since it is very unlikely the user is 5095 * editing a file name with a wildcard character. 5096 */ 5097 set_arglist(eap->arg); 5098 5099 /* 5100 * Expanding wildcards may result in an empty argument list. E.g. when 5101 * editing "foo.pyc" and ".pyc" is in 'wildignore'. Assume that we 5102 * already did an error message for this. 5103 */ 5104 if (ARGCOUNT == 0) 5105 return; 5106 5107 if (cmdmod.tab) 5108 { 5109 // ":tab drop file ...": open a tab for each argument that isn't 5110 // edited in a window yet. It's like ":tab all" but without closing 5111 // windows or tabs. 5112 ex_all(eap); 5113 } 5114 else 5115 { 5116 // ":drop file ...": Edit the first argument. Jump to an existing 5117 // window if possible, edit in current window if the current buffer 5118 // can be abandoned, otherwise open a new window. 5119 buf = buflist_findnr(ARGLIST[0].ae_fnum); 5120 5121 FOR_ALL_TAB_WINDOWS(tp, wp) 5122 { 5123 if (wp->w_buffer == buf) 5124 { 5125 goto_tabpage_win(tp, wp); 5126 curwin->w_arg_idx = 0; 5127 return; 5128 } 5129 } 5130 5131 /* 5132 * Check whether the current buffer is changed. If so, we will need 5133 * to split the current window or data could be lost. 5134 * Skip the check if the 'hidden' option is set, as in this case the 5135 * buffer won't be lost. 5136 */ 5137 if (!buf_hide(curbuf)) 5138 { 5139 ++emsg_off; 5140 split = check_changed(curbuf, CCGD_AW | CCGD_EXCMD); 5141 --emsg_off; 5142 } 5143 5144 // Fake a ":sfirst" or ":first" command edit the first argument. 5145 if (split) 5146 { 5147 eap->cmdidx = CMD_sfirst; 5148 eap->cmd[0] = 's'; 5149 } 5150 else 5151 eap->cmdidx = CMD_first; 5152 ex_rewind(eap); 5153 } 5154 } 5155 5156 /* 5157 * Skip over the pattern argument of ":vimgrep /pat/[g][j]". 5158 * Put the start of the pattern in "*s", unless "s" is NULL. 5159 * If "flags" is not NULL put the flags in it: VGR_GLOBAL, VGR_NOJUMP. 5160 * If "s" is not NULL terminate the pattern with a NUL. 5161 * Return a pointer to the char just past the pattern plus flags. 5162 */ 5163 char_u * 5164 skip_vimgrep_pat(char_u *p, char_u **s, int *flags) 5165 { 5166 int c; 5167 5168 if (vim_isIDc(*p)) 5169 { 5170 // ":vimgrep pattern fname" 5171 if (s != NULL) 5172 *s = p; 5173 p = skiptowhite(p); 5174 if (s != NULL && *p != NUL) 5175 *p++ = NUL; 5176 } 5177 else 5178 { 5179 // ":vimgrep /pattern/[g][j] fname" 5180 if (s != NULL) 5181 *s = p + 1; 5182 c = *p; 5183 p = skip_regexp(p + 1, c, TRUE); 5184 if (*p != c) 5185 return NULL; 5186 5187 // Truncate the pattern. 5188 if (s != NULL) 5189 *p = NUL; 5190 ++p; 5191 5192 // Find the flags 5193 while (*p == 'g' || *p == 'j') 5194 { 5195 if (flags != NULL) 5196 { 5197 if (*p == 'g') 5198 *flags |= VGR_GLOBAL; 5199 else 5200 *flags |= VGR_NOJUMP; 5201 } 5202 ++p; 5203 } 5204 } 5205 return p; 5206 } 5207 5208 #if defined(FEAT_EVAL) || defined(PROTO) 5209 /* 5210 * List v:oldfiles in a nice way. 5211 */ 5212 void 5213 ex_oldfiles(exarg_T *eap UNUSED) 5214 { 5215 list_T *l = get_vim_var_list(VV_OLDFILES); 5216 listitem_T *li; 5217 int nr = 0; 5218 char_u *fname; 5219 5220 if (l == NULL) 5221 msg(_("No old files")); 5222 else 5223 { 5224 msg_start(); 5225 msg_scroll = TRUE; 5226 for (li = l->lv_first; li != NULL && !got_int; li = li->li_next) 5227 { 5228 ++nr; 5229 fname = tv_get_string(&li->li_tv); 5230 if (!message_filtered(fname)) 5231 { 5232 msg_outnum((long)nr); 5233 msg_puts(": "); 5234 msg_outtrans(fname); 5235 msg_clr_eos(); 5236 msg_putchar('\n'); 5237 out_flush(); // output one line at a time 5238 ui_breakcheck(); 5239 } 5240 } 5241 5242 // Assume "got_int" was set to truncate the listing. 5243 got_int = FALSE; 5244 5245 # ifdef FEAT_BROWSE_CMD 5246 if (cmdmod.browse) 5247 { 5248 quit_more = FALSE; 5249 nr = prompt_for_number(FALSE); 5250 msg_starthere(); 5251 if (nr > 0) 5252 { 5253 char_u *p = list_find_str(get_vim_var_list(VV_OLDFILES), 5254 (long)nr); 5255 5256 if (p != NULL) 5257 { 5258 p = expand_env_save(p); 5259 eap->arg = p; 5260 eap->cmdidx = CMD_edit; 5261 cmdmod.browse = FALSE; 5262 do_exedit(eap, NULL); 5263 vim_free(p); 5264 } 5265 } 5266 } 5267 # endif 5268 } 5269 } 5270 #endif 5271