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