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