1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * ex_cmds2.c: some more functions for command line commands 12 */ 13 14 #include "vim.h" 15 #include "version.h" 16 17 static void cmd_source(char_u *fname, exarg_T *eap); 18 19 #if defined(FEAT_EVAL) || defined(PROTO) 20 # if defined(FEAT_TIMERS) || defined(PROTO) 21 static timer_T *first_timer = NULL; 22 static long last_timer_id = 0; 23 24 /* 25 * Return time left until "due". Negative if past "due". 26 */ 27 long 28 proftime_time_left(proftime_T *due, proftime_T *now) 29 { 30 # ifdef MSWIN 31 LARGE_INTEGER fr; 32 33 if (now->QuadPart > due->QuadPart) 34 return 0; 35 QueryPerformanceFrequency(&fr); 36 return (long)(((double)(due->QuadPart - now->QuadPart) 37 / (double)fr.QuadPart) * 1000); 38 # else 39 if (now->tv_sec > due->tv_sec) 40 return 0; 41 return (due->tv_sec - now->tv_sec) * 1000 42 + (due->tv_usec - now->tv_usec) / 1000; 43 # endif 44 } 45 46 /* 47 * Insert a timer in the list of timers. 48 */ 49 static void 50 insert_timer(timer_T *timer) 51 { 52 timer->tr_next = first_timer; 53 timer->tr_prev = NULL; 54 if (first_timer != NULL) 55 first_timer->tr_prev = timer; 56 first_timer = timer; 57 did_add_timer = TRUE; 58 } 59 60 /* 61 * Take a timer out of the list of timers. 62 */ 63 static void 64 remove_timer(timer_T *timer) 65 { 66 if (timer->tr_prev == NULL) 67 first_timer = timer->tr_next; 68 else 69 timer->tr_prev->tr_next = timer->tr_next; 70 if (timer->tr_next != NULL) 71 timer->tr_next->tr_prev = timer->tr_prev; 72 } 73 74 static void 75 free_timer(timer_T *timer) 76 { 77 free_callback(&timer->tr_callback); 78 vim_free(timer); 79 } 80 81 /* 82 * Create a timer and return it. NULL if out of memory. 83 * Caller should set the callback. 84 */ 85 timer_T * 86 create_timer(long msec, int repeat) 87 { 88 timer_T *timer = ALLOC_CLEAR_ONE(timer_T); 89 long prev_id = last_timer_id; 90 91 if (timer == NULL) 92 return NULL; 93 if (++last_timer_id <= prev_id) 94 /* Overflow! Might cause duplicates... */ 95 last_timer_id = 0; 96 timer->tr_id = last_timer_id; 97 insert_timer(timer); 98 if (repeat != 0) 99 timer->tr_repeat = repeat - 1; 100 timer->tr_interval = msec; 101 102 profile_setlimit(msec, &timer->tr_due); 103 return timer; 104 } 105 106 /* 107 * Invoke the callback of "timer". 108 */ 109 static void 110 timer_callback(timer_T *timer) 111 { 112 typval_T rettv; 113 typval_T argv[2]; 114 115 argv[0].v_type = VAR_NUMBER; 116 argv[0].vval.v_number = (varnumber_T)timer->tr_id; 117 argv[1].v_type = VAR_UNKNOWN; 118 119 call_callback(&timer->tr_callback, -1, &rettv, 1, argv); 120 clear_tv(&rettv); 121 } 122 123 /* 124 * Call timers that are due. 125 * Return the time in msec until the next timer is due. 126 * Returns -1 if there are no pending timers. 127 */ 128 long 129 check_due_timer(void) 130 { 131 timer_T *timer; 132 timer_T *timer_next; 133 long this_due; 134 long next_due = -1; 135 proftime_T now; 136 int did_one = FALSE; 137 int need_update_screen = FALSE; 138 long current_id = last_timer_id; 139 140 /* Don't run any timers while exiting or dealing with an error. */ 141 if (exiting || aborting()) 142 return next_due; 143 144 profile_start(&now); 145 for (timer = first_timer; timer != NULL && !got_int; timer = timer_next) 146 { 147 timer_next = timer->tr_next; 148 149 if (timer->tr_id == -1 || timer->tr_firing || timer->tr_paused) 150 continue; 151 this_due = proftime_time_left(&timer->tr_due, &now); 152 if (this_due <= 1) 153 { 154 /* Save and restore a lot of flags, because the timer fires while 155 * waiting for a character, which might be halfway a command. */ 156 int save_timer_busy = timer_busy; 157 int save_vgetc_busy = vgetc_busy; 158 int save_did_emsg = did_emsg; 159 int save_called_emsg = called_emsg; 160 int save_must_redraw = must_redraw; 161 int save_trylevel = trylevel; 162 int save_did_throw = did_throw; 163 int save_ex_pressedreturn = get_pressedreturn(); 164 int save_may_garbage_collect = may_garbage_collect; 165 except_T *save_current_exception = current_exception; 166 vimvars_save_T vvsave; 167 168 /* Create a scope for running the timer callback, ignoring most of 169 * the current scope, such as being inside a try/catch. */ 170 timer_busy = timer_busy > 0 || vgetc_busy > 0; 171 vgetc_busy = 0; 172 called_emsg = FALSE; 173 did_emsg = FALSE; 174 did_uncaught_emsg = FALSE; 175 must_redraw = 0; 176 trylevel = 0; 177 did_throw = FALSE; 178 current_exception = NULL; 179 may_garbage_collect = FALSE; 180 save_vimvars(&vvsave); 181 182 timer->tr_firing = TRUE; 183 timer_callback(timer); 184 timer->tr_firing = FALSE; 185 186 timer_next = timer->tr_next; 187 did_one = TRUE; 188 timer_busy = save_timer_busy; 189 vgetc_busy = save_vgetc_busy; 190 if (did_uncaught_emsg) 191 ++timer->tr_emsg_count; 192 did_emsg = save_did_emsg; 193 called_emsg = save_called_emsg; 194 trylevel = save_trylevel; 195 did_throw = save_did_throw; 196 current_exception = save_current_exception; 197 restore_vimvars(&vvsave); 198 if (must_redraw != 0) 199 need_update_screen = TRUE; 200 must_redraw = must_redraw > save_must_redraw 201 ? must_redraw : save_must_redraw; 202 set_pressedreturn(save_ex_pressedreturn); 203 may_garbage_collect = save_may_garbage_collect; 204 205 /* Only fire the timer again if it repeats and stop_timer() wasn't 206 * called while inside the callback (tr_id == -1). */ 207 if (timer->tr_repeat != 0 && timer->tr_id != -1 208 && timer->tr_emsg_count < 3) 209 { 210 profile_setlimit(timer->tr_interval, &timer->tr_due); 211 this_due = proftime_time_left(&timer->tr_due, &now); 212 if (this_due < 1) 213 this_due = 1; 214 if (timer->tr_repeat > 0) 215 --timer->tr_repeat; 216 } 217 else 218 { 219 this_due = -1; 220 remove_timer(timer); 221 free_timer(timer); 222 } 223 } 224 if (this_due > 0 && (next_due == -1 || next_due > this_due)) 225 next_due = this_due; 226 } 227 228 if (did_one) 229 redraw_after_callback(need_update_screen); 230 231 #ifdef FEAT_BEVAL_TERM 232 if (bevalexpr_due_set) 233 { 234 this_due = proftime_time_left(&bevalexpr_due, &now); 235 if (this_due <= 1) 236 { 237 bevalexpr_due_set = FALSE; 238 if (balloonEval == NULL) 239 { 240 balloonEval = ALLOC_CLEAR_ONE(BalloonEval); 241 balloonEvalForTerm = TRUE; 242 } 243 if (balloonEval != NULL) 244 { 245 general_beval_cb(balloonEval, 0); 246 setcursor(); 247 out_flush(); 248 } 249 } 250 else if (next_due == -1 || next_due > this_due) 251 next_due = this_due; 252 } 253 #endif 254 #ifdef FEAT_TERMINAL 255 /* Some terminal windows may need their buffer updated. */ 256 next_due = term_check_timers(next_due, &now); 257 #endif 258 259 return current_id != last_timer_id ? 1 : next_due; 260 } 261 262 /* 263 * Find a timer by ID. Returns NULL if not found; 264 */ 265 timer_T * 266 find_timer(long id) 267 { 268 timer_T *timer; 269 270 if (id >= 0) 271 { 272 for (timer = first_timer; timer != NULL; timer = timer->tr_next) 273 if (timer->tr_id == id) 274 return timer; 275 } 276 return NULL; 277 } 278 279 280 /* 281 * Stop a timer and delete it. 282 */ 283 void 284 stop_timer(timer_T *timer) 285 { 286 if (timer->tr_firing) 287 /* Free the timer after the callback returns. */ 288 timer->tr_id = -1; 289 else 290 { 291 remove_timer(timer); 292 free_timer(timer); 293 } 294 } 295 296 void 297 stop_all_timers(void) 298 { 299 timer_T *timer; 300 timer_T *timer_next; 301 302 for (timer = first_timer; timer != NULL; timer = timer_next) 303 { 304 timer_next = timer->tr_next; 305 stop_timer(timer); 306 } 307 } 308 309 void 310 add_timer_info(typval_T *rettv, timer_T *timer) 311 { 312 list_T *list = rettv->vval.v_list; 313 dict_T *dict = dict_alloc(); 314 dictitem_T *di; 315 long remaining; 316 proftime_T now; 317 318 if (dict == NULL) 319 return; 320 list_append_dict(list, dict); 321 322 dict_add_number(dict, "id", timer->tr_id); 323 dict_add_number(dict, "time", (long)timer->tr_interval); 324 325 profile_start(&now); 326 remaining = proftime_time_left(&timer->tr_due, &now); 327 dict_add_number(dict, "remaining", (long)remaining); 328 329 dict_add_number(dict, "repeat", 330 (long)(timer->tr_repeat < 0 ? -1 : timer->tr_repeat + 1)); 331 dict_add_number(dict, "paused", (long)(timer->tr_paused)); 332 333 di = dictitem_alloc((char_u *)"callback"); 334 if (di != NULL) 335 { 336 if (dict_add(dict, di) == FAIL) 337 vim_free(di); 338 else 339 put_callback(&timer->tr_callback, &di->di_tv); 340 } 341 } 342 343 void 344 add_timer_info_all(typval_T *rettv) 345 { 346 timer_T *timer; 347 348 for (timer = first_timer; timer != NULL; timer = timer->tr_next) 349 if (timer->tr_id != -1) 350 add_timer_info(rettv, timer); 351 } 352 353 /* 354 * Mark references in partials of timers. 355 */ 356 int 357 set_ref_in_timer(int copyID) 358 { 359 int abort = FALSE; 360 timer_T *timer; 361 typval_T tv; 362 363 for (timer = first_timer; !abort && timer != NULL; timer = timer->tr_next) 364 { 365 if (timer->tr_callback.cb_partial != NULL) 366 { 367 tv.v_type = VAR_PARTIAL; 368 tv.vval.v_partial = timer->tr_callback.cb_partial; 369 } 370 else 371 { 372 tv.v_type = VAR_FUNC; 373 tv.vval.v_string = timer->tr_callback.cb_name; 374 } 375 abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL); 376 } 377 return abort; 378 } 379 380 # if defined(EXITFREE) || defined(PROTO) 381 void 382 timer_free_all() 383 { 384 timer_T *timer; 385 386 while (first_timer != NULL) 387 { 388 timer = first_timer; 389 remove_timer(timer); 390 free_timer(timer); 391 } 392 } 393 # endif 394 # endif 395 396 #endif 397 398 /* 399 * If 'autowrite' option set, try to write the file. 400 * Careful: autocommands may make "buf" invalid! 401 * 402 * return FAIL for failure, OK otherwise 403 */ 404 int 405 autowrite(buf_T *buf, int forceit) 406 { 407 int r; 408 bufref_T bufref; 409 410 if (!(p_aw || p_awa) || !p_write 411 #ifdef FEAT_QUICKFIX 412 /* never autowrite a "nofile" or "nowrite" buffer */ 413 || bt_dontwrite(buf) 414 #endif 415 || (!forceit && buf->b_p_ro) || buf->b_ffname == NULL) 416 return FAIL; 417 set_bufref(&bufref, buf); 418 r = buf_write_all(buf, forceit); 419 420 /* Writing may succeed but the buffer still changed, e.g., when there is a 421 * conversion error. We do want to return FAIL then. */ 422 if (bufref_valid(&bufref) && bufIsChanged(buf)) 423 r = FAIL; 424 return r; 425 } 426 427 /* 428 * Flush all buffers, except the ones that are readonly or are never written. 429 */ 430 void 431 autowrite_all(void) 432 { 433 buf_T *buf; 434 435 if (!(p_aw || p_awa) || !p_write) 436 return; 437 FOR_ALL_BUFFERS(buf) 438 if (bufIsChanged(buf) && !buf->b_p_ro && !bt_dontwrite(buf)) 439 { 440 bufref_T bufref; 441 442 set_bufref(&bufref, buf); 443 444 (void)buf_write_all(buf, FALSE); 445 446 /* an autocommand may have deleted the buffer */ 447 if (!bufref_valid(&bufref)) 448 buf = firstbuf; 449 } 450 } 451 452 /* 453 * Return TRUE if buffer was changed and cannot be abandoned. 454 * For flags use the CCGD_ values. 455 */ 456 int 457 check_changed(buf_T *buf, int flags) 458 { 459 int forceit = (flags & CCGD_FORCEIT); 460 bufref_T bufref; 461 462 set_bufref(&bufref, buf); 463 464 if ( !forceit 465 && bufIsChanged(buf) 466 && ((flags & CCGD_MULTWIN) || buf->b_nwindows <= 1) 467 && (!(flags & CCGD_AW) || autowrite(buf, forceit) == FAIL)) 468 { 469 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 470 if ((p_confirm || cmdmod.confirm) && p_write) 471 { 472 buf_T *buf2; 473 int count = 0; 474 475 if (flags & CCGD_ALLBUF) 476 FOR_ALL_BUFFERS(buf2) 477 if (bufIsChanged(buf2) 478 && (buf2->b_ffname != NULL 479 # ifdef FEAT_BROWSE 480 || cmdmod.browse 481 # endif 482 )) 483 ++count; 484 if (!bufref_valid(&bufref)) 485 /* Autocommand deleted buffer, oops! It's not changed now. */ 486 return FALSE; 487 488 dialog_changed(buf, count > 1); 489 490 if (!bufref_valid(&bufref)) 491 /* Autocommand deleted buffer, oops! It's not changed now. */ 492 return FALSE; 493 return bufIsChanged(buf); 494 } 495 #endif 496 if (flags & CCGD_EXCMD) 497 no_write_message(); 498 else 499 no_write_message_nobang(curbuf); 500 return TRUE; 501 } 502 return FALSE; 503 } 504 505 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) || defined(PROTO) 506 507 #if defined(FEAT_BROWSE) || defined(PROTO) 508 /* 509 * When wanting to write a file without a file name, ask the user for a name. 510 */ 511 void 512 browse_save_fname(buf_T *buf) 513 { 514 if (buf->b_fname == NULL) 515 { 516 char_u *fname; 517 518 fname = do_browse(BROWSE_SAVE, (char_u *)_("Save As"), 519 NULL, NULL, NULL, NULL, buf); 520 if (fname != NULL) 521 { 522 if (setfname(buf, fname, NULL, TRUE) == OK) 523 buf->b_flags |= BF_NOTEDITED; 524 vim_free(fname); 525 } 526 } 527 } 528 #endif 529 530 /* 531 * Ask the user what to do when abandoning a changed buffer. 532 * Must check 'write' option first! 533 */ 534 void 535 dialog_changed( 536 buf_T *buf, 537 int checkall) /* may abandon all changed buffers */ 538 { 539 char_u buff[DIALOG_MSG_SIZE]; 540 int ret; 541 buf_T *buf2; 542 exarg_T ea; 543 544 dialog_msg(buff, _("Save changes to \"%s\"?"), buf->b_fname); 545 if (checkall) 546 ret = vim_dialog_yesnoallcancel(VIM_QUESTION, NULL, buff, 1); 547 else 548 ret = vim_dialog_yesnocancel(VIM_QUESTION, NULL, buff, 1); 549 550 // Init ea pseudo-structure, this is needed for the check_overwrite() 551 // function. 552 vim_memset(&ea, 0, sizeof(ea)); 553 554 if (ret == VIM_YES) 555 { 556 #ifdef FEAT_BROWSE 557 /* May get file name, when there is none */ 558 browse_save_fname(buf); 559 #endif 560 if (buf->b_fname != NULL && check_overwrite(&ea, buf, 561 buf->b_fname, buf->b_ffname, FALSE) == OK) 562 /* didn't hit Cancel */ 563 (void)buf_write_all(buf, FALSE); 564 } 565 else if (ret == VIM_NO) 566 { 567 unchanged(buf, TRUE, FALSE); 568 } 569 else if (ret == VIM_ALL) 570 { 571 /* 572 * Write all modified files that can be written. 573 * Skip readonly buffers, these need to be confirmed 574 * individually. 575 */ 576 FOR_ALL_BUFFERS(buf2) 577 { 578 if (bufIsChanged(buf2) 579 && (buf2->b_ffname != NULL 580 #ifdef FEAT_BROWSE 581 || cmdmod.browse 582 #endif 583 ) 584 && !buf2->b_p_ro) 585 { 586 bufref_T bufref; 587 588 set_bufref(&bufref, buf2); 589 #ifdef FEAT_BROWSE 590 /* May get file name, when there is none */ 591 browse_save_fname(buf2); 592 #endif 593 if (buf2->b_fname != NULL && check_overwrite(&ea, buf2, 594 buf2->b_fname, buf2->b_ffname, FALSE) == OK) 595 /* didn't hit Cancel */ 596 (void)buf_write_all(buf2, FALSE); 597 598 /* an autocommand may have deleted the buffer */ 599 if (!bufref_valid(&bufref)) 600 buf2 = firstbuf; 601 } 602 } 603 } 604 else if (ret == VIM_DISCARDALL) 605 { 606 /* 607 * mark all buffers as unchanged 608 */ 609 FOR_ALL_BUFFERS(buf2) 610 unchanged(buf2, TRUE, FALSE); 611 } 612 } 613 #endif 614 615 /* 616 * Return TRUE if the buffer "buf" can be abandoned, either by making it 617 * hidden, autowriting it or unloading it. 618 */ 619 int 620 can_abandon(buf_T *buf, int forceit) 621 { 622 return ( buf_hide(buf) 623 || !bufIsChanged(buf) 624 || buf->b_nwindows > 1 625 || autowrite(buf, forceit) == OK 626 || forceit); 627 } 628 629 /* 630 * Add a buffer number to "bufnrs", unless it's already there. 631 */ 632 static void 633 add_bufnum(int *bufnrs, int *bufnump, int nr) 634 { 635 int i; 636 637 for (i = 0; i < *bufnump; ++i) 638 if (bufnrs[i] == nr) 639 return; 640 bufnrs[*bufnump] = nr; 641 *bufnump = *bufnump + 1; 642 } 643 644 /* 645 * Return TRUE if any buffer was changed and cannot be abandoned. 646 * That changed buffer becomes the current buffer. 647 * When "unload" is TRUE the current buffer is unloaded instead of making it 648 * hidden. This is used for ":q!". 649 */ 650 int 651 check_changed_any( 652 int hidden, /* Only check hidden buffers */ 653 int unload) 654 { 655 int ret = FALSE; 656 buf_T *buf; 657 int save; 658 int i; 659 int bufnum = 0; 660 int bufcount = 0; 661 int *bufnrs; 662 tabpage_T *tp; 663 win_T *wp; 664 665 /* Make a list of all buffers, with the most important ones first. */ 666 FOR_ALL_BUFFERS(buf) 667 ++bufcount; 668 669 if (bufcount == 0) 670 return FALSE; 671 672 bufnrs = ALLOC_MULT(int, bufcount); 673 if (bufnrs == NULL) 674 return FALSE; 675 676 /* curbuf */ 677 bufnrs[bufnum++] = curbuf->b_fnum; 678 679 /* buffers in current tab */ 680 FOR_ALL_WINDOWS(wp) 681 if (wp->w_buffer != curbuf) 682 add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum); 683 684 /* buffers in other tabs */ 685 FOR_ALL_TABPAGES(tp) 686 if (tp != curtab) 687 for (wp = tp->tp_firstwin; wp != NULL; wp = wp->w_next) 688 add_bufnum(bufnrs, &bufnum, wp->w_buffer->b_fnum); 689 690 /* any other buffer */ 691 FOR_ALL_BUFFERS(buf) 692 add_bufnum(bufnrs, &bufnum, buf->b_fnum); 693 694 for (i = 0; i < bufnum; ++i) 695 { 696 buf = buflist_findnr(bufnrs[i]); 697 if (buf == NULL) 698 continue; 699 if ((!hidden || buf->b_nwindows == 0) && bufIsChanged(buf)) 700 { 701 bufref_T bufref; 702 703 set_bufref(&bufref, buf); 704 #ifdef FEAT_TERMINAL 705 if (term_job_running(buf->b_term)) 706 { 707 if (term_try_stop_job(buf) == FAIL) 708 break; 709 } 710 else 711 #endif 712 /* Try auto-writing the buffer. If this fails but the buffer no 713 * longer exists it's not changed, that's OK. */ 714 if (check_changed(buf, (p_awa ? CCGD_AW : 0) 715 | CCGD_MULTWIN 716 | CCGD_ALLBUF) && bufref_valid(&bufref)) 717 break; /* didn't save - still changes */ 718 } 719 } 720 721 if (i >= bufnum) 722 goto theend; 723 724 /* Get here if "buf" cannot be abandoned. */ 725 ret = TRUE; 726 exiting = FALSE; 727 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 728 /* 729 * When ":confirm" used, don't give an error message. 730 */ 731 if (!(p_confirm || cmdmod.confirm)) 732 #endif 733 { 734 /* There must be a wait_return for this message, do_buffer() 735 * may cause a redraw. But wait_return() is a no-op when vgetc() 736 * is busy (Quit used from window menu), then make sure we don't 737 * cause a scroll up. */ 738 if (vgetc_busy > 0) 739 { 740 msg_row = cmdline_row; 741 msg_col = 0; 742 msg_didout = FALSE; 743 } 744 if ( 745 #ifdef FEAT_TERMINAL 746 term_job_running(buf->b_term) 747 ? semsg(_("E947: Job still running in buffer \"%s\""), 748 buf->b_fname) 749 : 750 #endif 751 semsg(_("E162: No write since last change for buffer \"%s\""), 752 buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname)) 753 { 754 save = no_wait_return; 755 no_wait_return = FALSE; 756 wait_return(FALSE); 757 no_wait_return = save; 758 } 759 } 760 761 /* Try to find a window that contains the buffer. */ 762 if (buf != curbuf) 763 FOR_ALL_TAB_WINDOWS(tp, wp) 764 if (wp->w_buffer == buf) 765 { 766 bufref_T bufref; 767 768 set_bufref(&bufref, buf); 769 770 goto_tabpage_win(tp, wp); 771 772 // Paranoia: did autocmd wipe out the buffer with changes? 773 if (!bufref_valid(&bufref)) 774 goto theend; 775 goto buf_found; 776 } 777 buf_found: 778 779 /* Open the changed buffer in the current window. */ 780 if (buf != curbuf) 781 set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO); 782 783 theend: 784 vim_free(bufnrs); 785 return ret; 786 } 787 788 /* 789 * return FAIL if there is no file name, OK if there is one 790 * give error message for FAIL 791 */ 792 int 793 check_fname(void) 794 { 795 if (curbuf->b_ffname == NULL) 796 { 797 emsg(_(e_noname)); 798 return FAIL; 799 } 800 return OK; 801 } 802 803 /* 804 * flush the contents of a buffer, unless it has no file name 805 * 806 * return FAIL for failure, OK otherwise 807 */ 808 int 809 buf_write_all(buf_T *buf, int forceit) 810 { 811 int retval; 812 buf_T *old_curbuf = curbuf; 813 814 retval = (buf_write(buf, buf->b_ffname, buf->b_fname, 815 (linenr_T)1, buf->b_ml.ml_line_count, NULL, 816 FALSE, forceit, TRUE, FALSE)); 817 if (curbuf != old_curbuf) 818 { 819 msg_source(HL_ATTR(HLF_W)); 820 msg(_("Warning: Entered other buffer unexpectedly (check autocommands)")); 821 } 822 return retval; 823 } 824 825 /* 826 * Code to handle the argument list. 827 */ 828 829 static int do_arglist(char_u *str, int what, int after, int will_edit); 830 static void alist_check_arg_idx(void); 831 static void alist_add_list(int count, char_u **files, int after, int will_edit); 832 #define AL_SET 1 833 #define AL_ADD 2 834 #define AL_DEL 3 835 836 /* 837 * Isolate one argument, taking backticks. 838 * Changes the argument in-place, puts a NUL after it. Backticks remain. 839 * Return a pointer to the start of the next argument. 840 */ 841 static char_u * 842 do_one_arg(char_u *str) 843 { 844 char_u *p; 845 int inbacktick; 846 847 inbacktick = FALSE; 848 for (p = str; *str; ++str) 849 { 850 /* When the backslash is used for escaping the special meaning of a 851 * character we need to keep it until wildcard expansion. */ 852 if (rem_backslash(str)) 853 { 854 *p++ = *str++; 855 *p++ = *str; 856 } 857 else 858 { 859 /* An item ends at a space not in backticks */ 860 if (!inbacktick && vim_isspace(*str)) 861 break; 862 if (*str == '`') 863 inbacktick ^= TRUE; 864 *p++ = *str; 865 } 866 } 867 str = skipwhite(str); 868 *p = NUL; 869 870 return str; 871 } 872 873 /* 874 * Separate the arguments in "str" and return a list of pointers in the 875 * growarray "gap". 876 */ 877 static int 878 get_arglist(garray_T *gap, char_u *str, int escaped) 879 { 880 ga_init2(gap, (int)sizeof(char_u *), 20); 881 while (*str != NUL) 882 { 883 if (ga_grow(gap, 1) == FAIL) 884 { 885 ga_clear(gap); 886 return FAIL; 887 } 888 ((char_u **)gap->ga_data)[gap->ga_len++] = str; 889 890 /* If str is escaped, don't handle backslashes or spaces */ 891 if (!escaped) 892 return OK; 893 894 /* Isolate one argument, change it in-place, put a NUL after it. */ 895 str = do_one_arg(str); 896 } 897 return OK; 898 } 899 900 #if defined(FEAT_QUICKFIX) || defined(FEAT_SYN_HL) || defined(PROTO) 901 /* 902 * Parse a list of arguments (file names), expand them and return in 903 * "fnames[fcountp]". When "wig" is TRUE, removes files matching 'wildignore'. 904 * Return FAIL or OK. 905 */ 906 int 907 get_arglist_exp( 908 char_u *str, 909 int *fcountp, 910 char_u ***fnamesp, 911 int wig) 912 { 913 garray_T ga; 914 int i; 915 916 if (get_arglist(&ga, str, TRUE) == FAIL) 917 return FAIL; 918 if (wig == TRUE) 919 i = expand_wildcards(ga.ga_len, (char_u **)ga.ga_data, 920 fcountp, fnamesp, EW_FILE|EW_NOTFOUND); 921 else 922 i = gen_expand_wildcards(ga.ga_len, (char_u **)ga.ga_data, 923 fcountp, fnamesp, EW_FILE|EW_NOTFOUND); 924 925 ga_clear(&ga); 926 return i; 927 } 928 #endif 929 930 /* 931 * Redefine the argument list. 932 */ 933 void 934 set_arglist(char_u *str) 935 { 936 do_arglist(str, AL_SET, 0, FALSE); 937 } 938 939 /* 940 * "what" == AL_SET: Redefine the argument list to 'str'. 941 * "what" == AL_ADD: add files in 'str' to the argument list after "after". 942 * "what" == AL_DEL: remove files in 'str' from the argument list. 943 * 944 * Return FAIL for failure, OK otherwise. 945 */ 946 static int 947 do_arglist( 948 char_u *str, 949 int what, 950 int after UNUSED, // 0 means before first one 951 int will_edit) // will edit added argument 952 { 953 garray_T new_ga; 954 int exp_count; 955 char_u **exp_files; 956 int i; 957 char_u *p; 958 int match; 959 int arg_escaped = TRUE; 960 961 /* 962 * Set default argument for ":argadd" command. 963 */ 964 if (what == AL_ADD && *str == NUL) 965 { 966 if (curbuf->b_ffname == NULL) 967 return FAIL; 968 str = curbuf->b_fname; 969 arg_escaped = FALSE; 970 } 971 972 /* 973 * Collect all file name arguments in "new_ga". 974 */ 975 if (get_arglist(&new_ga, str, arg_escaped) == FAIL) 976 return FAIL; 977 978 if (what == AL_DEL) 979 { 980 regmatch_T regmatch; 981 int didone; 982 983 /* 984 * Delete the items: use each item as a regexp and find a match in the 985 * argument list. 986 */ 987 regmatch.rm_ic = p_fic; /* ignore case when 'fileignorecase' is set */ 988 for (i = 0; i < new_ga.ga_len && !got_int; ++i) 989 { 990 p = ((char_u **)new_ga.ga_data)[i]; 991 p = file_pat_to_reg_pat(p, NULL, NULL, FALSE); 992 if (p == NULL) 993 break; 994 regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0); 995 if (regmatch.regprog == NULL) 996 { 997 vim_free(p); 998 break; 999 } 1000 1001 didone = FALSE; 1002 for (match = 0; match < ARGCOUNT; ++match) 1003 if (vim_regexec(®match, alist_name(&ARGLIST[match]), 1004 (colnr_T)0)) 1005 { 1006 didone = TRUE; 1007 vim_free(ARGLIST[match].ae_fname); 1008 mch_memmove(ARGLIST + match, ARGLIST + match + 1, 1009 (ARGCOUNT - match - 1) * sizeof(aentry_T)); 1010 --ALIST(curwin)->al_ga.ga_len; 1011 if (curwin->w_arg_idx > match) 1012 --curwin->w_arg_idx; 1013 --match; 1014 } 1015 1016 vim_regfree(regmatch.regprog); 1017 vim_free(p); 1018 if (!didone) 1019 semsg(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]); 1020 } 1021 ga_clear(&new_ga); 1022 } 1023 else 1024 { 1025 i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data, 1026 &exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND); 1027 ga_clear(&new_ga); 1028 if (i == FAIL || exp_count == 0) 1029 { 1030 emsg(_(e_nomatch)); 1031 return FAIL; 1032 } 1033 1034 if (what == AL_ADD) 1035 { 1036 alist_add_list(exp_count, exp_files, after, will_edit); 1037 vim_free(exp_files); 1038 } 1039 else /* what == AL_SET */ 1040 alist_set(ALIST(curwin), exp_count, exp_files, will_edit, NULL, 0); 1041 } 1042 1043 alist_check_arg_idx(); 1044 1045 return OK; 1046 } 1047 1048 /* 1049 * Check the validity of the arg_idx for each other window. 1050 */ 1051 static void 1052 alist_check_arg_idx(void) 1053 { 1054 win_T *win; 1055 tabpage_T *tp; 1056 1057 FOR_ALL_TAB_WINDOWS(tp, win) 1058 if (win->w_alist == curwin->w_alist) 1059 check_arg_idx(win); 1060 } 1061 1062 /* 1063 * Return TRUE if window "win" is editing the file at the current argument 1064 * index. 1065 */ 1066 static int 1067 editing_arg_idx(win_T *win) 1068 { 1069 return !(win->w_arg_idx >= WARGCOUNT(win) 1070 || (win->w_buffer->b_fnum 1071 != WARGLIST(win)[win->w_arg_idx].ae_fnum 1072 && (win->w_buffer->b_ffname == NULL 1073 || !(fullpathcmp( 1074 alist_name(&WARGLIST(win)[win->w_arg_idx]), 1075 win->w_buffer->b_ffname, TRUE, TRUE) & FPC_SAME)))); 1076 } 1077 1078 /* 1079 * Check if window "win" is editing the w_arg_idx file in its argument list. 1080 */ 1081 void 1082 check_arg_idx(win_T *win) 1083 { 1084 if (WARGCOUNT(win) > 1 && !editing_arg_idx(win)) 1085 { 1086 /* We are not editing the current entry in the argument list. 1087 * Set "arg_had_last" if we are editing the last one. */ 1088 win->w_arg_idx_invalid = TRUE; 1089 if (win->w_arg_idx != WARGCOUNT(win) - 1 1090 && arg_had_last == FALSE 1091 && ALIST(win) == &global_alist 1092 && GARGCOUNT > 0 1093 && win->w_arg_idx < GARGCOUNT 1094 && (win->w_buffer->b_fnum == GARGLIST[GARGCOUNT - 1].ae_fnum 1095 || (win->w_buffer->b_ffname != NULL 1096 && (fullpathcmp(alist_name(&GARGLIST[GARGCOUNT - 1]), 1097 win->w_buffer->b_ffname, TRUE, TRUE) & FPC_SAME)))) 1098 arg_had_last = TRUE; 1099 } 1100 else 1101 { 1102 /* We are editing the current entry in the argument list. 1103 * Set "arg_had_last" if it's also the last one */ 1104 win->w_arg_idx_invalid = FALSE; 1105 if (win->w_arg_idx == WARGCOUNT(win) - 1 1106 && win->w_alist == &global_alist) 1107 arg_had_last = TRUE; 1108 } 1109 } 1110 1111 /* 1112 * ":args", ":argslocal" and ":argsglobal". 1113 */ 1114 void 1115 ex_args(exarg_T *eap) 1116 { 1117 int i; 1118 1119 if (eap->cmdidx != CMD_args) 1120 { 1121 alist_unlink(ALIST(curwin)); 1122 if (eap->cmdidx == CMD_argglobal) 1123 ALIST(curwin) = &global_alist; 1124 else /* eap->cmdidx == CMD_arglocal */ 1125 alist_new(); 1126 } 1127 1128 if (*eap->arg != NUL) 1129 { 1130 /* 1131 * ":args file ..": define new argument list, handle like ":next" 1132 * Also for ":argslocal file .." and ":argsglobal file ..". 1133 */ 1134 ex_next(eap); 1135 } 1136 else if (eap->cmdidx == CMD_args) 1137 { 1138 /* 1139 * ":args": list arguments. 1140 */ 1141 if (ARGCOUNT > 0) 1142 { 1143 char_u **items = ALLOC_MULT(char_u *, ARGCOUNT); 1144 1145 if (items != NULL) 1146 { 1147 /* Overwrite the command, for a short list there is no 1148 * scrolling required and no wait_return(). */ 1149 gotocmdline(TRUE); 1150 1151 for (i = 0; i < ARGCOUNT; ++i) 1152 items[i] = alist_name(&ARGLIST[i]); 1153 list_in_columns(items, ARGCOUNT, curwin->w_arg_idx); 1154 vim_free(items); 1155 } 1156 } 1157 } 1158 else if (eap->cmdidx == CMD_arglocal) 1159 { 1160 garray_T *gap = &curwin->w_alist->al_ga; 1161 1162 /* 1163 * ":argslocal": make a local copy of the global argument list. 1164 */ 1165 if (ga_grow(gap, GARGCOUNT) == OK) 1166 for (i = 0; i < GARGCOUNT; ++i) 1167 if (GARGLIST[i].ae_fname != NULL) 1168 { 1169 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname = 1170 vim_strsave(GARGLIST[i].ae_fname); 1171 AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum = 1172 GARGLIST[i].ae_fnum; 1173 ++gap->ga_len; 1174 } 1175 } 1176 } 1177 1178 /* 1179 * ":previous", ":sprevious", ":Next" and ":sNext". 1180 */ 1181 void 1182 ex_previous(exarg_T *eap) 1183 { 1184 /* If past the last one already, go to the last one. */ 1185 if (curwin->w_arg_idx - (int)eap->line2 >= ARGCOUNT) 1186 do_argfile(eap, ARGCOUNT - 1); 1187 else 1188 do_argfile(eap, curwin->w_arg_idx - (int)eap->line2); 1189 } 1190 1191 /* 1192 * ":rewind", ":first", ":sfirst" and ":srewind". 1193 */ 1194 void 1195 ex_rewind(exarg_T *eap) 1196 { 1197 do_argfile(eap, 0); 1198 } 1199 1200 /* 1201 * ":last" and ":slast". 1202 */ 1203 void 1204 ex_last(exarg_T *eap) 1205 { 1206 do_argfile(eap, ARGCOUNT - 1); 1207 } 1208 1209 /* 1210 * ":argument" and ":sargument". 1211 */ 1212 void 1213 ex_argument(exarg_T *eap) 1214 { 1215 int i; 1216 1217 if (eap->addr_count > 0) 1218 i = eap->line2 - 1; 1219 else 1220 i = curwin->w_arg_idx; 1221 do_argfile(eap, i); 1222 } 1223 1224 /* 1225 * Edit file "argn" of the argument lists. 1226 */ 1227 void 1228 do_argfile(exarg_T *eap, int argn) 1229 { 1230 int other; 1231 char_u *p; 1232 int old_arg_idx = curwin->w_arg_idx; 1233 1234 if (ERROR_IF_POPUP_WINDOW) 1235 return; 1236 if (argn < 0 || argn >= ARGCOUNT) 1237 { 1238 if (ARGCOUNT <= 1) 1239 emsg(_("E163: There is only one file to edit")); 1240 else if (argn < 0) 1241 emsg(_("E164: Cannot go before first file")); 1242 else 1243 emsg(_("E165: Cannot go beyond last file")); 1244 } 1245 else 1246 { 1247 setpcmark(); 1248 #ifdef FEAT_GUI 1249 need_mouse_correct = TRUE; 1250 #endif 1251 1252 /* split window or create new tab page first */ 1253 if (*eap->cmd == 's' || cmdmod.tab != 0) 1254 { 1255 if (win_split(0, 0) == FAIL) 1256 return; 1257 RESET_BINDING(curwin); 1258 } 1259 else 1260 { 1261 /* 1262 * if 'hidden' set, only check for changed file when re-editing 1263 * the same buffer 1264 */ 1265 other = TRUE; 1266 if (buf_hide(curbuf)) 1267 { 1268 p = fix_fname(alist_name(&ARGLIST[argn])); 1269 other = otherfile(p); 1270 vim_free(p); 1271 } 1272 if ((!buf_hide(curbuf) || !other) 1273 && check_changed(curbuf, CCGD_AW 1274 | (other ? 0 : CCGD_MULTWIN) 1275 | (eap->forceit ? CCGD_FORCEIT : 0) 1276 | CCGD_EXCMD)) 1277 return; 1278 } 1279 1280 curwin->w_arg_idx = argn; 1281 if (argn == ARGCOUNT - 1 && curwin->w_alist == &global_alist) 1282 arg_had_last = TRUE; 1283 1284 /* Edit the file; always use the last known line number. 1285 * When it fails (e.g. Abort for already edited file) restore the 1286 * argument index. */ 1287 if (do_ecmd(0, alist_name(&ARGLIST[curwin->w_arg_idx]), NULL, 1288 eap, ECMD_LAST, 1289 (buf_hide(curwin->w_buffer) ? ECMD_HIDE : 0) 1290 + (eap->forceit ? ECMD_FORCEIT : 0), curwin) == FAIL) 1291 curwin->w_arg_idx = old_arg_idx; 1292 /* like Vi: set the mark where the cursor is in the file. */ 1293 else if (eap->cmdidx != CMD_argdo) 1294 setmark('\''); 1295 } 1296 } 1297 1298 /* 1299 * ":next", and commands that behave like it. 1300 */ 1301 void 1302 ex_next(exarg_T *eap) 1303 { 1304 int i; 1305 1306 /* 1307 * check for changed buffer now, if this fails the argument list is not 1308 * redefined. 1309 */ 1310 if ( buf_hide(curbuf) 1311 || eap->cmdidx == CMD_snext 1312 || !check_changed(curbuf, CCGD_AW 1313 | (eap->forceit ? CCGD_FORCEIT : 0) 1314 | CCGD_EXCMD)) 1315 { 1316 if (*eap->arg != NUL) /* redefine file list */ 1317 { 1318 if (do_arglist(eap->arg, AL_SET, 0, TRUE) == FAIL) 1319 return; 1320 i = 0; 1321 } 1322 else 1323 i = curwin->w_arg_idx + (int)eap->line2; 1324 do_argfile(eap, i); 1325 } 1326 } 1327 1328 /* 1329 * ":argedit" 1330 */ 1331 void 1332 ex_argedit(exarg_T *eap) 1333 { 1334 int i = eap->addr_count ? (int)eap->line2 : curwin->w_arg_idx + 1; 1335 // Whether curbuf will be reused, curbuf->b_ffname will be set. 1336 int curbuf_is_reusable = curbuf_reusable(); 1337 1338 if (do_arglist(eap->arg, AL_ADD, i, TRUE) == FAIL) 1339 return; 1340 #ifdef FEAT_TITLE 1341 maketitle(); 1342 #endif 1343 1344 if (curwin->w_arg_idx == 0 1345 && (curbuf->b_ml.ml_flags & ML_EMPTY) 1346 && (curbuf->b_ffname == NULL || curbuf_is_reusable)) 1347 i = 0; 1348 /* Edit the argument. */ 1349 if (i < ARGCOUNT) 1350 do_argfile(eap, i); 1351 } 1352 1353 /* 1354 * ":argadd" 1355 */ 1356 void 1357 ex_argadd(exarg_T *eap) 1358 { 1359 do_arglist(eap->arg, AL_ADD, 1360 eap->addr_count > 0 ? (int)eap->line2 : curwin->w_arg_idx + 1, 1361 FALSE); 1362 #ifdef FEAT_TITLE 1363 maketitle(); 1364 #endif 1365 } 1366 1367 /* 1368 * ":argdelete" 1369 */ 1370 void 1371 ex_argdelete(exarg_T *eap) 1372 { 1373 int i; 1374 int n; 1375 1376 if (eap->addr_count > 0) 1377 { 1378 /* ":1,4argdel": Delete all arguments in the range. */ 1379 if (eap->line2 > ARGCOUNT) 1380 eap->line2 = ARGCOUNT; 1381 n = eap->line2 - eap->line1 + 1; 1382 if (*eap->arg != NUL) 1383 /* Can't have both a range and an argument. */ 1384 emsg(_(e_invarg)); 1385 else if (n <= 0) 1386 { 1387 /* Don't give an error for ":%argdel" if the list is empty. */ 1388 if (eap->line1 != 1 || eap->line2 != 0) 1389 emsg(_(e_invrange)); 1390 } 1391 else 1392 { 1393 for (i = eap->line1; i <= eap->line2; ++i) 1394 vim_free(ARGLIST[i - 1].ae_fname); 1395 mch_memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2, 1396 (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T))); 1397 ALIST(curwin)->al_ga.ga_len -= n; 1398 if (curwin->w_arg_idx >= eap->line2) 1399 curwin->w_arg_idx -= n; 1400 else if (curwin->w_arg_idx > eap->line1) 1401 curwin->w_arg_idx = eap->line1; 1402 if (ARGCOUNT == 0) 1403 curwin->w_arg_idx = 0; 1404 else if (curwin->w_arg_idx >= ARGCOUNT) 1405 curwin->w_arg_idx = ARGCOUNT - 1; 1406 } 1407 } 1408 else if (*eap->arg == NUL) 1409 emsg(_(e_argreq)); 1410 else 1411 do_arglist(eap->arg, AL_DEL, 0, FALSE); 1412 #ifdef FEAT_TITLE 1413 maketitle(); 1414 #endif 1415 } 1416 1417 /* 1418 * ":argdo", ":windo", ":bufdo", ":tabdo", ":cdo", ":ldo", ":cfdo" and ":lfdo" 1419 */ 1420 void 1421 ex_listdo(exarg_T *eap) 1422 { 1423 int i; 1424 win_T *wp; 1425 tabpage_T *tp; 1426 buf_T *buf = curbuf; 1427 int next_fnum = 0; 1428 #if defined(FEAT_SYN_HL) 1429 char_u *save_ei = NULL; 1430 #endif 1431 char_u *p_shm_save; 1432 #ifdef FEAT_QUICKFIX 1433 int qf_size = 0; 1434 int qf_idx; 1435 #endif 1436 1437 #ifndef FEAT_QUICKFIX 1438 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo || 1439 eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) 1440 { 1441 ex_ni(eap); 1442 return; 1443 } 1444 #endif 1445 1446 #if defined(FEAT_SYN_HL) 1447 if (eap->cmdidx != CMD_windo && eap->cmdidx != CMD_tabdo) 1448 { 1449 /* Don't do syntax HL autocommands. Skipping the syntax file is a 1450 * great speed improvement. */ 1451 save_ei = au_event_disable(",Syntax"); 1452 1453 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 1454 buf->b_flags &= ~BF_SYN_SET; 1455 buf = curbuf; 1456 } 1457 #endif 1458 #ifdef FEAT_CLIPBOARD 1459 start_global_changes(); 1460 #endif 1461 1462 if (eap->cmdidx == CMD_windo 1463 || eap->cmdidx == CMD_tabdo 1464 || buf_hide(curbuf) 1465 || !check_changed(curbuf, CCGD_AW 1466 | (eap->forceit ? CCGD_FORCEIT : 0) 1467 | CCGD_EXCMD)) 1468 { 1469 i = 0; 1470 /* start at the eap->line1 argument/window/buffer */ 1471 wp = firstwin; 1472 tp = first_tabpage; 1473 switch (eap->cmdidx) 1474 { 1475 case CMD_windo: 1476 for ( ; wp != NULL && i + 1 < eap->line1; wp = wp->w_next) 1477 i++; 1478 break; 1479 case CMD_tabdo: 1480 for( ; tp != NULL && i + 1 < eap->line1; tp = tp->tp_next) 1481 i++; 1482 break; 1483 case CMD_argdo: 1484 i = eap->line1 - 1; 1485 break; 1486 default: 1487 break; 1488 } 1489 /* set pcmark now */ 1490 if (eap->cmdidx == CMD_bufdo) 1491 { 1492 /* Advance to the first listed buffer after "eap->line1". */ 1493 for (buf = firstbuf; buf != NULL && (buf->b_fnum < eap->line1 1494 || !buf->b_p_bl); buf = buf->b_next) 1495 if (buf->b_fnum > eap->line2) 1496 { 1497 buf = NULL; 1498 break; 1499 } 1500 if (buf != NULL) 1501 goto_buffer(eap, DOBUF_FIRST, FORWARD, buf->b_fnum); 1502 } 1503 #ifdef FEAT_QUICKFIX 1504 else if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo 1505 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) 1506 { 1507 qf_size = qf_get_valid_size(eap); 1508 if (qf_size <= 0 || eap->line1 > qf_size) 1509 buf = NULL; 1510 else 1511 { 1512 ex_cc(eap); 1513 1514 buf = curbuf; 1515 i = eap->line1 - 1; 1516 if (eap->addr_count <= 0) 1517 /* default is all the quickfix/location list entries */ 1518 eap->line2 = qf_size; 1519 } 1520 } 1521 #endif 1522 else 1523 setpcmark(); 1524 listcmd_busy = TRUE; /* avoids setting pcmark below */ 1525 1526 while (!got_int && buf != NULL) 1527 { 1528 if (eap->cmdidx == CMD_argdo) 1529 { 1530 /* go to argument "i" */ 1531 if (i == ARGCOUNT) 1532 break; 1533 /* Don't call do_argfile() when already there, it will try 1534 * reloading the file. */ 1535 if (curwin->w_arg_idx != i || !editing_arg_idx(curwin)) 1536 { 1537 /* Clear 'shm' to avoid that the file message overwrites 1538 * any output from the command. */ 1539 p_shm_save = vim_strsave(p_shm); 1540 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0); 1541 do_argfile(eap, i); 1542 set_option_value((char_u *)"shm", 0L, p_shm_save, 0); 1543 vim_free(p_shm_save); 1544 } 1545 if (curwin->w_arg_idx != i) 1546 break; 1547 } 1548 else if (eap->cmdidx == CMD_windo) 1549 { 1550 /* go to window "wp" */ 1551 if (!win_valid(wp)) 1552 break; 1553 win_goto(wp); 1554 if (curwin != wp) 1555 break; /* something must be wrong */ 1556 wp = curwin->w_next; 1557 } 1558 else if (eap->cmdidx == CMD_tabdo) 1559 { 1560 /* go to window "tp" */ 1561 if (!valid_tabpage(tp)) 1562 break; 1563 goto_tabpage_tp(tp, TRUE, TRUE); 1564 tp = tp->tp_next; 1565 } 1566 else if (eap->cmdidx == CMD_bufdo) 1567 { 1568 /* Remember the number of the next listed buffer, in case 1569 * ":bwipe" is used or autocommands do something strange. */ 1570 next_fnum = -1; 1571 for (buf = curbuf->b_next; buf != NULL; buf = buf->b_next) 1572 if (buf->b_p_bl) 1573 { 1574 next_fnum = buf->b_fnum; 1575 break; 1576 } 1577 } 1578 1579 ++i; 1580 1581 /* execute the command */ 1582 do_cmdline(eap->arg, eap->getline, eap->cookie, 1583 DOCMD_VERBOSE + DOCMD_NOWAIT); 1584 1585 if (eap->cmdidx == CMD_bufdo) 1586 { 1587 /* Done? */ 1588 if (next_fnum < 0 || next_fnum > eap->line2) 1589 break; 1590 /* Check if the buffer still exists. */ 1591 FOR_ALL_BUFFERS(buf) 1592 if (buf->b_fnum == next_fnum) 1593 break; 1594 if (buf == NULL) 1595 break; 1596 1597 /* Go to the next buffer. Clear 'shm' to avoid that the file 1598 * message overwrites any output from the command. */ 1599 p_shm_save = vim_strsave(p_shm); 1600 set_option_value((char_u *)"shm", 0L, (char_u *)"", 0); 1601 goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum); 1602 set_option_value((char_u *)"shm", 0L, p_shm_save, 0); 1603 vim_free(p_shm_save); 1604 1605 /* If autocommands took us elsewhere, quit here. */ 1606 if (curbuf->b_fnum != next_fnum) 1607 break; 1608 } 1609 1610 #ifdef FEAT_QUICKFIX 1611 if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo 1612 || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) 1613 { 1614 if (i >= qf_size || i >= eap->line2) 1615 break; 1616 1617 qf_idx = qf_get_cur_idx(eap); 1618 1619 ex_cnext(eap); 1620 1621 /* If jumping to the next quickfix entry fails, quit here */ 1622 if (qf_get_cur_idx(eap) == qf_idx) 1623 break; 1624 } 1625 #endif 1626 1627 if (eap->cmdidx == CMD_windo) 1628 { 1629 validate_cursor(); /* cursor may have moved */ 1630 1631 /* required when 'scrollbind' has been set */ 1632 if (curwin->w_p_scb) 1633 do_check_scrollbind(TRUE); 1634 } 1635 1636 if (eap->cmdidx == CMD_windo || eap->cmdidx == CMD_tabdo) 1637 if (i+1 > eap->line2) 1638 break; 1639 if (eap->cmdidx == CMD_argdo && i >= eap->line2) 1640 break; 1641 } 1642 listcmd_busy = FALSE; 1643 } 1644 1645 #if defined(FEAT_SYN_HL) 1646 if (save_ei != NULL) 1647 { 1648 buf_T *bnext; 1649 aco_save_T aco; 1650 1651 au_event_restore(save_ei); 1652 1653 for (buf = firstbuf; buf != NULL; buf = bnext) 1654 { 1655 bnext = buf->b_next; 1656 if (buf->b_nwindows > 0 && (buf->b_flags & BF_SYN_SET)) 1657 { 1658 buf->b_flags &= ~BF_SYN_SET; 1659 1660 // buffer was opened while Syntax autocommands were disabled, 1661 // need to trigger them now. 1662 if (buf == curbuf) 1663 apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, 1664 curbuf->b_fname, TRUE, curbuf); 1665 else 1666 { 1667 aucmd_prepbuf(&aco, buf); 1668 apply_autocmds(EVENT_SYNTAX, buf->b_p_syn, 1669 buf->b_fname, TRUE, buf); 1670 aucmd_restbuf(&aco); 1671 } 1672 1673 // start over, in case autocommands messed things up. 1674 bnext = firstbuf; 1675 } 1676 } 1677 } 1678 #endif 1679 #ifdef FEAT_CLIPBOARD 1680 end_global_changes(); 1681 #endif 1682 } 1683 1684 /* 1685 * Add files[count] to the arglist of the current window after arg "after". 1686 * The file names in files[count] must have been allocated and are taken over. 1687 * Files[] itself is not taken over. 1688 */ 1689 static void 1690 alist_add_list( 1691 int count, 1692 char_u **files, 1693 int after, // where to add: 0 = before first one 1694 int will_edit) // will edit adding argument 1695 { 1696 int i; 1697 int old_argcount = ARGCOUNT; 1698 1699 if (ga_grow(&ALIST(curwin)->al_ga, count) == OK) 1700 { 1701 if (after < 0) 1702 after = 0; 1703 if (after > ARGCOUNT) 1704 after = ARGCOUNT; 1705 if (after < ARGCOUNT) 1706 mch_memmove(&(ARGLIST[after + count]), &(ARGLIST[after]), 1707 (ARGCOUNT - after) * sizeof(aentry_T)); 1708 for (i = 0; i < count; ++i) 1709 { 1710 int flags = BLN_LISTED | (will_edit ? BLN_CURBUF : 0); 1711 1712 ARGLIST[after + i].ae_fname = files[i]; 1713 ARGLIST[after + i].ae_fnum = buflist_add(files[i], flags); 1714 } 1715 ALIST(curwin)->al_ga.ga_len += count; 1716 if (old_argcount > 0 && curwin->w_arg_idx >= after) 1717 curwin->w_arg_idx += count; 1718 return; 1719 } 1720 1721 for (i = 0; i < count; ++i) 1722 vim_free(files[i]); 1723 } 1724 1725 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 1726 /* 1727 * Function given to ExpandGeneric() to obtain the possible arguments of the 1728 * argedit and argdelete commands. 1729 */ 1730 char_u * 1731 get_arglist_name(expand_T *xp UNUSED, int idx) 1732 { 1733 if (idx >= ARGCOUNT) 1734 return NULL; 1735 1736 return alist_name(&ARGLIST[idx]); 1737 } 1738 #endif 1739 1740 1741 #ifdef FEAT_EVAL 1742 /* 1743 * ":compiler[!] {name}" 1744 */ 1745 void 1746 ex_compiler(exarg_T *eap) 1747 { 1748 char_u *buf; 1749 char_u *old_cur_comp = NULL; 1750 char_u *p; 1751 1752 if (*eap->arg == NUL) 1753 { 1754 /* List all compiler scripts. */ 1755 do_cmdline_cmd((char_u *)"echo globpath(&rtp, 'compiler/*.vim')"); 1756 /* ) keep the indenter happy... */ 1757 } 1758 else 1759 { 1760 buf = alloc(STRLEN(eap->arg) + 14); 1761 if (buf != NULL) 1762 { 1763 if (eap->forceit) 1764 { 1765 /* ":compiler! {name}" sets global options */ 1766 do_cmdline_cmd((char_u *) 1767 "command -nargs=* CompilerSet set <args>"); 1768 } 1769 else 1770 { 1771 /* ":compiler! {name}" sets local options. 1772 * To remain backwards compatible "current_compiler" is always 1773 * used. A user's compiler plugin may set it, the distributed 1774 * plugin will then skip the settings. Afterwards set 1775 * "b:current_compiler" and restore "current_compiler". 1776 * Explicitly prepend "g:" to make it work in a function. */ 1777 old_cur_comp = get_var_value((char_u *)"g:current_compiler"); 1778 if (old_cur_comp != NULL) 1779 old_cur_comp = vim_strsave(old_cur_comp); 1780 do_cmdline_cmd((char_u *) 1781 "command -nargs=* CompilerSet setlocal <args>"); 1782 } 1783 do_unlet((char_u *)"g:current_compiler", TRUE); 1784 do_unlet((char_u *)"b:current_compiler", TRUE); 1785 1786 sprintf((char *)buf, "compiler/%s.vim", eap->arg); 1787 if (source_runtime(buf, DIP_ALL) == FAIL) 1788 semsg(_("E666: compiler not supported: %s"), eap->arg); 1789 vim_free(buf); 1790 1791 do_cmdline_cmd((char_u *)":delcommand CompilerSet"); 1792 1793 /* Set "b:current_compiler" from "current_compiler". */ 1794 p = get_var_value((char_u *)"g:current_compiler"); 1795 if (p != NULL) 1796 set_internal_string_var((char_u *)"b:current_compiler", p); 1797 1798 /* Restore "current_compiler" for ":compiler {name}". */ 1799 if (!eap->forceit) 1800 { 1801 if (old_cur_comp != NULL) 1802 { 1803 set_internal_string_var((char_u *)"g:current_compiler", 1804 old_cur_comp); 1805 vim_free(old_cur_comp); 1806 } 1807 else 1808 do_unlet((char_u *)"g:current_compiler", TRUE); 1809 } 1810 } 1811 } 1812 } 1813 #endif 1814 1815 /* 1816 * ":runtime [what] {name}" 1817 */ 1818 void 1819 ex_runtime(exarg_T *eap) 1820 { 1821 char_u *arg = eap->arg; 1822 char_u *p = skiptowhite(arg); 1823 int len = (int)(p - arg); 1824 int flags = eap->forceit ? DIP_ALL : 0; 1825 1826 if (STRNCMP(arg, "START", len) == 0) 1827 { 1828 flags += DIP_START + DIP_NORTP; 1829 arg = skipwhite(arg + len); 1830 } 1831 else if (STRNCMP(arg, "OPT", len) == 0) 1832 { 1833 flags += DIP_OPT + DIP_NORTP; 1834 arg = skipwhite(arg + len); 1835 } 1836 else if (STRNCMP(arg, "PACK", len) == 0) 1837 { 1838 flags += DIP_START + DIP_OPT + DIP_NORTP; 1839 arg = skipwhite(arg + len); 1840 } 1841 else if (STRNCMP(arg, "ALL", len) == 0) 1842 { 1843 flags += DIP_START + DIP_OPT; 1844 arg = skipwhite(arg + len); 1845 } 1846 1847 source_runtime(arg, flags); 1848 } 1849 1850 static void 1851 source_callback(char_u *fname, void *cookie UNUSED) 1852 { 1853 (void)do_source(fname, FALSE, DOSO_NONE); 1854 } 1855 1856 /* 1857 * Find the file "name" in all directories in "path" and invoke 1858 * "callback(fname, cookie)". 1859 * "name" can contain wildcards. 1860 * When "flags" has DIP_ALL: source all files, otherwise only the first one. 1861 * When "flags" has DIP_DIR: find directories instead of files. 1862 * When "flags" has DIP_ERR: give an error message if there is no match. 1863 * 1864 * return FAIL when no file could be sourced, OK otherwise. 1865 */ 1866 int 1867 do_in_path( 1868 char_u *path, 1869 char_u *name, 1870 int flags, 1871 void (*callback)(char_u *fname, void *ck), 1872 void *cookie) 1873 { 1874 char_u *rtp; 1875 char_u *np; 1876 char_u *buf; 1877 char_u *rtp_copy; 1878 char_u *tail; 1879 int num_files; 1880 char_u **files; 1881 int i; 1882 int did_one = FALSE; 1883 #ifdef AMIGA 1884 struct Process *proc = (struct Process *)FindTask(0L); 1885 APTR save_winptr = proc->pr_WindowPtr; 1886 1887 /* Avoid a requester here for a volume that doesn't exist. */ 1888 proc->pr_WindowPtr = (APTR)-1L; 1889 #endif 1890 1891 /* Make a copy of 'runtimepath'. Invoking the callback may change the 1892 * value. */ 1893 rtp_copy = vim_strsave(path); 1894 buf = alloc(MAXPATHL); 1895 if (buf != NULL && rtp_copy != NULL) 1896 { 1897 if (p_verbose > 1 && name != NULL) 1898 { 1899 verbose_enter(); 1900 smsg(_("Searching for \"%s\" in \"%s\""), 1901 (char *)name, (char *)path); 1902 verbose_leave(); 1903 } 1904 1905 /* Loop over all entries in 'runtimepath'. */ 1906 rtp = rtp_copy; 1907 while (*rtp != NUL && ((flags & DIP_ALL) || !did_one)) 1908 { 1909 size_t buflen; 1910 1911 /* Copy the path from 'runtimepath' to buf[]. */ 1912 copy_option_part(&rtp, buf, MAXPATHL, ","); 1913 buflen = STRLEN(buf); 1914 1915 /* Skip after or non-after directories. */ 1916 if (flags & (DIP_NOAFTER | DIP_AFTER)) 1917 { 1918 int is_after = buflen >= 5 1919 && STRCMP(buf + buflen - 5, "after") == 0; 1920 1921 if ((is_after && (flags & DIP_NOAFTER)) 1922 || (!is_after && (flags & DIP_AFTER))) 1923 continue; 1924 } 1925 1926 if (name == NULL) 1927 { 1928 (*callback)(buf, (void *) &cookie); 1929 if (!did_one) 1930 did_one = (cookie == NULL); 1931 } 1932 else if (buflen + STRLEN(name) + 2 < MAXPATHL) 1933 { 1934 add_pathsep(buf); 1935 tail = buf + STRLEN(buf); 1936 1937 /* Loop over all patterns in "name" */ 1938 np = name; 1939 while (*np != NUL && ((flags & DIP_ALL) || !did_one)) 1940 { 1941 /* Append the pattern from "name" to buf[]. */ 1942 copy_option_part(&np, tail, (int)(MAXPATHL - (tail - buf)), 1943 "\t "); 1944 1945 if (p_verbose > 2) 1946 { 1947 verbose_enter(); 1948 smsg(_("Searching for \"%s\""), buf); 1949 verbose_leave(); 1950 } 1951 1952 /* Expand wildcards, invoke the callback for each match. */ 1953 if (gen_expand_wildcards(1, &buf, &num_files, &files, 1954 (flags & DIP_DIR) ? EW_DIR : EW_FILE) == OK) 1955 { 1956 for (i = 0; i < num_files; ++i) 1957 { 1958 (*callback)(files[i], cookie); 1959 did_one = TRUE; 1960 if (!(flags & DIP_ALL)) 1961 break; 1962 } 1963 FreeWild(num_files, files); 1964 } 1965 } 1966 } 1967 } 1968 } 1969 vim_free(buf); 1970 vim_free(rtp_copy); 1971 if (!did_one && name != NULL) 1972 { 1973 char *basepath = path == p_rtp ? "runtimepath" : "packpath"; 1974 1975 if (flags & DIP_ERR) 1976 semsg(_(e_dirnotf), basepath, name); 1977 else if (p_verbose > 0) 1978 { 1979 verbose_enter(); 1980 smsg(_("not found in '%s': \"%s\""), basepath, name); 1981 verbose_leave(); 1982 } 1983 } 1984 1985 #ifdef AMIGA 1986 proc->pr_WindowPtr = save_winptr; 1987 #endif 1988 1989 return did_one ? OK : FAIL; 1990 } 1991 1992 /* 1993 * Find "name" in "path". When found, invoke the callback function for 1994 * it: callback(fname, "cookie") 1995 * When "flags" has DIP_ALL repeat for all matches, otherwise only the first 1996 * one is used. 1997 * Returns OK when at least one match found, FAIL otherwise. 1998 * 1999 * If "name" is NULL calls callback for each entry in "path". Cookie is 2000 * passed by reference in this case, setting it to NULL indicates that callback 2001 * has done its job. 2002 */ 2003 static int 2004 do_in_path_and_pp( 2005 char_u *path, 2006 char_u *name, 2007 int flags, 2008 void (*callback)(char_u *fname, void *ck), 2009 void *cookie) 2010 { 2011 int done = FAIL; 2012 char_u *s; 2013 int len; 2014 char *start_dir = "pack/*/start/*/%s"; 2015 char *opt_dir = "pack/*/opt/*/%s"; 2016 2017 if ((flags & DIP_NORTP) == 0) 2018 done = do_in_path(path, name, flags, callback, cookie); 2019 2020 if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START)) 2021 { 2022 len = (int)(STRLEN(start_dir) + STRLEN(name)); 2023 s = alloc(len); 2024 if (s == NULL) 2025 return FAIL; 2026 vim_snprintf((char *)s, len, start_dir, name); 2027 done = do_in_path(p_pp, s, flags, callback, cookie); 2028 vim_free(s); 2029 } 2030 2031 if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_OPT)) 2032 { 2033 len = (int)(STRLEN(opt_dir) + STRLEN(name)); 2034 s = alloc(len); 2035 if (s == NULL) 2036 return FAIL; 2037 vim_snprintf((char *)s, len, opt_dir, name); 2038 done = do_in_path(p_pp, s, flags, callback, cookie); 2039 vim_free(s); 2040 } 2041 2042 return done; 2043 } 2044 2045 /* 2046 * Just like do_in_path_and_pp(), using 'runtimepath' for "path". 2047 */ 2048 int 2049 do_in_runtimepath( 2050 char_u *name, 2051 int flags, 2052 void (*callback)(char_u *fname, void *ck), 2053 void *cookie) 2054 { 2055 return do_in_path_and_pp(p_rtp, name, flags, callback, cookie); 2056 } 2057 2058 /* 2059 * Source the file "name" from all directories in 'runtimepath'. 2060 * "name" can contain wildcards. 2061 * When "flags" has DIP_ALL: source all files, otherwise only the first one. 2062 * 2063 * return FAIL when no file could be sourced, OK otherwise. 2064 */ 2065 int 2066 source_runtime(char_u *name, int flags) 2067 { 2068 return source_in_path(p_rtp, name, flags); 2069 } 2070 2071 /* 2072 * Just like source_runtime(), but use "path" instead of 'runtimepath'. 2073 */ 2074 int 2075 source_in_path(char_u *path, char_u *name, int flags) 2076 { 2077 return do_in_path_and_pp(path, name, flags, source_callback, NULL); 2078 } 2079 2080 2081 #if defined(FEAT_EVAL) || defined(PROTO) 2082 2083 /* 2084 * Expand wildcards in "pat" and invoke do_source() for each match. 2085 */ 2086 static void 2087 source_all_matches(char_u *pat) 2088 { 2089 int num_files; 2090 char_u **files; 2091 int i; 2092 2093 if (gen_expand_wildcards(1, &pat, &num_files, &files, EW_FILE) == OK) 2094 { 2095 for (i = 0; i < num_files; ++i) 2096 (void)do_source(files[i], FALSE, DOSO_NONE); 2097 FreeWild(num_files, files); 2098 } 2099 } 2100 2101 /* 2102 * Add the package directory to 'runtimepath'. 2103 */ 2104 static int 2105 add_pack_dir_to_rtp(char_u *fname) 2106 { 2107 char_u *p4, *p3, *p2, *p1, *p; 2108 char_u *entry; 2109 char_u *insp = NULL; 2110 int c; 2111 char_u *new_rtp; 2112 int keep; 2113 size_t oldlen; 2114 size_t addlen; 2115 size_t new_rtp_len; 2116 char_u *afterdir = NULL; 2117 size_t afterlen = 0; 2118 char_u *after_insp = NULL; 2119 char_u *ffname = NULL; 2120 size_t fname_len; 2121 char_u *buf = NULL; 2122 char_u *rtp_ffname; 2123 int match; 2124 int retval = FAIL; 2125 2126 p4 = p3 = p2 = p1 = get_past_head(fname); 2127 for (p = p1; *p; MB_PTR_ADV(p)) 2128 if (vim_ispathsep_nocolon(*p)) 2129 { 2130 p4 = p3; p3 = p2; p2 = p1; p1 = p; 2131 } 2132 2133 /* now we have: 2134 * rtp/pack/name/start/name 2135 * p4 p3 p2 p1 2136 * 2137 * find the part up to "pack" in 'runtimepath' */ 2138 c = *++p4; /* append pathsep in order to expand symlink */ 2139 *p4 = NUL; 2140 ffname = fix_fname(fname); 2141 *p4 = c; 2142 if (ffname == NULL) 2143 return FAIL; 2144 2145 // Find "ffname" in "p_rtp", ignoring '/' vs '\' differences. 2146 // Also stop at the first "after" directory. 2147 fname_len = STRLEN(ffname); 2148 buf = alloc(MAXPATHL); 2149 if (buf == NULL) 2150 goto theend; 2151 for (entry = p_rtp; *entry != NUL; ) 2152 { 2153 char_u *cur_entry = entry; 2154 2155 copy_option_part(&entry, buf, MAXPATHL, ","); 2156 if (insp == NULL) 2157 { 2158 add_pathsep(buf); 2159 rtp_ffname = fix_fname(buf); 2160 if (rtp_ffname == NULL) 2161 goto theend; 2162 match = vim_fnamencmp(rtp_ffname, ffname, fname_len) == 0; 2163 vim_free(rtp_ffname); 2164 if (match) 2165 // Insert "ffname" after this entry (and comma). 2166 insp = entry; 2167 } 2168 2169 if ((p = (char_u *)strstr((char *)buf, "after")) != NULL 2170 && p > buf 2171 && vim_ispathsep(p[-1]) 2172 && (vim_ispathsep(p[5]) || p[5] == NUL || p[5] == ',')) 2173 { 2174 if (insp == NULL) 2175 // Did not find "ffname" before the first "after" directory, 2176 // insert it before this entry. 2177 insp = cur_entry; 2178 after_insp = cur_entry; 2179 break; 2180 } 2181 } 2182 2183 if (insp == NULL) 2184 // Both "fname" and "after" not found, append at the end. 2185 insp = p_rtp + STRLEN(p_rtp); 2186 2187 // check if rtp/pack/name/start/name/after exists 2188 afterdir = concat_fnames(fname, (char_u *)"after", TRUE); 2189 if (afterdir != NULL && mch_isdir(afterdir)) 2190 afterlen = STRLEN(afterdir) + 1; // add one for comma 2191 2192 oldlen = STRLEN(p_rtp); 2193 addlen = STRLEN(fname) + 1; // add one for comma 2194 new_rtp = alloc(oldlen + addlen + afterlen + 1); // add one for NUL 2195 if (new_rtp == NULL) 2196 goto theend; 2197 2198 // We now have 'rtp' parts: {keep}{keep_after}{rest}. 2199 // Create new_rtp, first: {keep},{fname} 2200 keep = (int)(insp - p_rtp); 2201 mch_memmove(new_rtp, p_rtp, keep); 2202 new_rtp_len = keep; 2203 if (*insp == NUL) 2204 new_rtp[new_rtp_len++] = ','; // add comma before 2205 mch_memmove(new_rtp + new_rtp_len, fname, addlen - 1); 2206 new_rtp_len += addlen - 1; 2207 if (*insp != NUL) 2208 new_rtp[new_rtp_len++] = ','; // add comma after 2209 2210 if (afterlen > 0 && after_insp != NULL) 2211 { 2212 int keep_after = (int)(after_insp - p_rtp); 2213 2214 // Add to new_rtp: {keep},{fname}{keep_after},{afterdir} 2215 mch_memmove(new_rtp + new_rtp_len, p_rtp + keep, 2216 keep_after - keep); 2217 new_rtp_len += keep_after - keep; 2218 mch_memmove(new_rtp + new_rtp_len, afterdir, afterlen - 1); 2219 new_rtp_len += afterlen - 1; 2220 new_rtp[new_rtp_len++] = ','; 2221 keep = keep_after; 2222 } 2223 2224 if (p_rtp[keep] != NUL) 2225 // Append rest: {keep},{fname}{keep_after},{afterdir}{rest} 2226 mch_memmove(new_rtp + new_rtp_len, p_rtp + keep, oldlen - keep + 1); 2227 else 2228 new_rtp[new_rtp_len] = NUL; 2229 2230 if (afterlen > 0 && after_insp == NULL) 2231 { 2232 // Append afterdir when "after" was not found: 2233 // {keep},{fname}{rest},{afterdir} 2234 STRCAT(new_rtp, ","); 2235 STRCAT(new_rtp, afterdir); 2236 } 2237 2238 set_option_value((char_u *)"rtp", 0L, new_rtp, 0); 2239 vim_free(new_rtp); 2240 retval = OK; 2241 2242 theend: 2243 vim_free(buf); 2244 vim_free(ffname); 2245 vim_free(afterdir); 2246 return retval; 2247 } 2248 2249 /* 2250 * Load scripts in "plugin" and "ftdetect" directories of the package. 2251 */ 2252 static int 2253 load_pack_plugin(char_u *fname) 2254 { 2255 static char *plugpat = "%s/plugin/**/*.vim"; 2256 static char *ftpat = "%s/ftdetect/*.vim"; 2257 int len; 2258 char_u *ffname = fix_fname(fname); 2259 char_u *pat = NULL; 2260 int retval = FAIL; 2261 2262 if (ffname == NULL) 2263 return FAIL; 2264 len = (int)STRLEN(ffname) + (int)STRLEN(ftpat); 2265 pat = alloc(len); 2266 if (pat == NULL) 2267 goto theend; 2268 vim_snprintf((char *)pat, len, plugpat, ffname); 2269 source_all_matches(pat); 2270 2271 { 2272 char_u *cmd = vim_strsave((char_u *)"g:did_load_filetypes"); 2273 2274 /* If runtime/filetype.vim wasn't loaded yet, the scripts will be 2275 * found when it loads. */ 2276 if (cmd != NULL && eval_to_number(cmd) > 0) 2277 { 2278 do_cmdline_cmd((char_u *)"augroup filetypedetect"); 2279 vim_snprintf((char *)pat, len, ftpat, ffname); 2280 source_all_matches(pat); 2281 do_cmdline_cmd((char_u *)"augroup END"); 2282 } 2283 vim_free(cmd); 2284 } 2285 vim_free(pat); 2286 retval = OK; 2287 2288 theend: 2289 vim_free(ffname); 2290 return retval; 2291 } 2292 2293 /* used for "cookie" of add_pack_plugin() */ 2294 static int APP_ADD_DIR; 2295 static int APP_LOAD; 2296 static int APP_BOTH; 2297 2298 static void 2299 add_pack_plugin(char_u *fname, void *cookie) 2300 { 2301 if (cookie != &APP_LOAD) 2302 { 2303 char_u *buf = alloc(MAXPATHL); 2304 char_u *p; 2305 int found = FALSE; 2306 2307 if (buf == NULL) 2308 return; 2309 p = p_rtp; 2310 while (*p != NUL) 2311 { 2312 copy_option_part(&p, buf, MAXPATHL, ","); 2313 if (pathcmp((char *)buf, (char *)fname, -1) == 0) 2314 { 2315 found = TRUE; 2316 break; 2317 } 2318 } 2319 vim_free(buf); 2320 if (!found) 2321 /* directory is not yet in 'runtimepath', add it */ 2322 if (add_pack_dir_to_rtp(fname) == FAIL) 2323 return; 2324 } 2325 2326 if (cookie != &APP_ADD_DIR) 2327 load_pack_plugin(fname); 2328 } 2329 2330 /* 2331 * Add all packages in the "start" directory to 'runtimepath'. 2332 */ 2333 void 2334 add_pack_start_dirs(void) 2335 { 2336 do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, 2337 add_pack_plugin, &APP_ADD_DIR); 2338 } 2339 2340 /* 2341 * Load plugins from all packages in the "start" directory. 2342 */ 2343 void 2344 load_start_packages(void) 2345 { 2346 did_source_packages = TRUE; 2347 do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, 2348 add_pack_plugin, &APP_LOAD); 2349 } 2350 2351 /* 2352 * ":packloadall" 2353 * Find plugins in the package directories and source them. 2354 */ 2355 void 2356 ex_packloadall(exarg_T *eap) 2357 { 2358 if (!did_source_packages || eap->forceit) 2359 { 2360 /* First do a round to add all directories to 'runtimepath', then load 2361 * the plugins. This allows for plugins to use an autoload directory 2362 * of another plugin. */ 2363 add_pack_start_dirs(); 2364 load_start_packages(); 2365 } 2366 } 2367 2368 /* 2369 * ":packadd[!] {name}" 2370 */ 2371 void 2372 ex_packadd(exarg_T *eap) 2373 { 2374 static char *plugpat = "pack/*/%s/%s"; 2375 int len; 2376 char *pat; 2377 int round; 2378 int res = OK; 2379 2380 /* Round 1: use "start", round 2: use "opt". */ 2381 for (round = 1; round <= 2; ++round) 2382 { 2383 /* Only look under "start" when loading packages wasn't done yet. */ 2384 if (round == 1 && did_source_packages) 2385 continue; 2386 2387 len = (int)STRLEN(plugpat) + (int)STRLEN(eap->arg) + 5; 2388 pat = alloc(len); 2389 if (pat == NULL) 2390 return; 2391 vim_snprintf(pat, len, plugpat, round == 1 ? "start" : "opt", eap->arg); 2392 /* The first round don't give a "not found" error, in the second round 2393 * only when nothing was found in the first round. */ 2394 res = do_in_path(p_pp, (char_u *)pat, 2395 DIP_ALL + DIP_DIR + (round == 2 && res == FAIL ? DIP_ERR : 0), 2396 add_pack_plugin, eap->forceit ? &APP_ADD_DIR : &APP_BOTH); 2397 vim_free(pat); 2398 } 2399 } 2400 #endif 2401 2402 #if defined(FEAT_EVAL) || defined(PROTO) 2403 /* 2404 * ":options" 2405 */ 2406 void 2407 ex_options( 2408 exarg_T *eap UNUSED) 2409 { 2410 vim_setenv((char_u *)"OPTWIN_CMD", 2411 (char_u *)(cmdmod.tab ? "tab" 2412 : (cmdmod.split & WSP_VERT) ? "vert" : "")); 2413 cmd_source((char_u *)SYS_OPTWIN_FILE, NULL); 2414 } 2415 #endif 2416 2417 #if defined(FEAT_PYTHON3) || defined(FEAT_PYTHON) || defined(PROTO) 2418 2419 # if (defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)) || defined(PROTO) 2420 /* 2421 * Detect Python 3 or 2, and initialize 'pyxversion'. 2422 */ 2423 void 2424 init_pyxversion(void) 2425 { 2426 if (p_pyx == 0) 2427 { 2428 if (python3_enabled(FALSE)) 2429 p_pyx = 3; 2430 else if (python_enabled(FALSE)) 2431 p_pyx = 2; 2432 } 2433 } 2434 # endif 2435 2436 /* 2437 * Does a file contain one of the following strings at the beginning of any 2438 * line? 2439 * "#!(any string)python2" => returns 2 2440 * "#!(any string)python3" => returns 3 2441 * "# requires python 2.x" => returns 2 2442 * "# requires python 3.x" => returns 3 2443 * otherwise return 0. 2444 */ 2445 static int 2446 requires_py_version(char_u *filename) 2447 { 2448 FILE *file; 2449 int requires_py_version = 0; 2450 int i, lines; 2451 2452 lines = (int)p_mls; 2453 if (lines < 0) 2454 lines = 5; 2455 2456 file = mch_fopen((char *)filename, "r"); 2457 if (file != NULL) 2458 { 2459 for (i = 0; i < lines; i++) 2460 { 2461 if (vim_fgets(IObuff, IOSIZE, file)) 2462 break; 2463 if (i == 0 && IObuff[0] == '#' && IObuff[1] == '!') 2464 { 2465 /* Check shebang. */ 2466 if (strstr((char *)IObuff + 2, "python2") != NULL) 2467 { 2468 requires_py_version = 2; 2469 break; 2470 } 2471 if (strstr((char *)IObuff + 2, "python3") != NULL) 2472 { 2473 requires_py_version = 3; 2474 break; 2475 } 2476 } 2477 IObuff[21] = '\0'; 2478 if (STRCMP("# requires python 2.x", IObuff) == 0) 2479 { 2480 requires_py_version = 2; 2481 break; 2482 } 2483 if (STRCMP("# requires python 3.x", IObuff) == 0) 2484 { 2485 requires_py_version = 3; 2486 break; 2487 } 2488 } 2489 fclose(file); 2490 } 2491 return requires_py_version; 2492 } 2493 2494 2495 /* 2496 * Source a python file using the requested python version. 2497 */ 2498 static void 2499 source_pyx_file(exarg_T *eap, char_u *fname) 2500 { 2501 exarg_T ex; 2502 int v = requires_py_version(fname); 2503 2504 # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3) 2505 init_pyxversion(); 2506 # endif 2507 if (v == 0) 2508 { 2509 # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3) 2510 /* user didn't choose a preference, 'pyx' is used */ 2511 v = p_pyx; 2512 # elif defined(FEAT_PYTHON) 2513 v = 2; 2514 # elif defined(FEAT_PYTHON3) 2515 v = 3; 2516 # endif 2517 } 2518 2519 /* 2520 * now source, if required python version is not supported show 2521 * unobtrusive message. 2522 */ 2523 if (eap == NULL) 2524 vim_memset(&ex, 0, sizeof(ex)); 2525 else 2526 ex = *eap; 2527 ex.arg = fname; 2528 ex.cmd = (char_u *)(v == 2 ? "pyfile" : "pyfile3"); 2529 2530 if (v == 2) 2531 { 2532 # ifdef FEAT_PYTHON 2533 ex_pyfile(&ex); 2534 # else 2535 vim_snprintf((char *)IObuff, IOSIZE, 2536 _("W20: Required python version 2.x not supported, ignoring file: %s"), 2537 fname); 2538 msg((char *)IObuff); 2539 # endif 2540 return; 2541 } 2542 else 2543 { 2544 # ifdef FEAT_PYTHON3 2545 ex_py3file(&ex); 2546 # else 2547 vim_snprintf((char *)IObuff, IOSIZE, 2548 _("W21: Required python version 3.x not supported, ignoring file: %s"), 2549 fname); 2550 msg((char *)IObuff); 2551 # endif 2552 return; 2553 } 2554 } 2555 2556 /* 2557 * ":pyxfile {fname}" 2558 */ 2559 void 2560 ex_pyxfile(exarg_T *eap) 2561 { 2562 source_pyx_file(eap, eap->arg); 2563 } 2564 2565 /* 2566 * ":pyx" 2567 */ 2568 void 2569 ex_pyx(exarg_T *eap) 2570 { 2571 # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3) 2572 init_pyxversion(); 2573 if (p_pyx == 2) 2574 ex_python(eap); 2575 else 2576 ex_py3(eap); 2577 # elif defined(FEAT_PYTHON) 2578 ex_python(eap); 2579 # elif defined(FEAT_PYTHON3) 2580 ex_py3(eap); 2581 # endif 2582 } 2583 2584 /* 2585 * ":pyxdo" 2586 */ 2587 void 2588 ex_pyxdo(exarg_T *eap) 2589 { 2590 # if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3) 2591 init_pyxversion(); 2592 if (p_pyx == 2) 2593 ex_pydo(eap); 2594 else 2595 ex_py3do(eap); 2596 # elif defined(FEAT_PYTHON) 2597 ex_pydo(eap); 2598 # elif defined(FEAT_PYTHON3) 2599 ex_py3do(eap); 2600 # endif 2601 } 2602 2603 #endif 2604 2605 /* 2606 * ":source {fname}" 2607 */ 2608 void 2609 ex_source(exarg_T *eap) 2610 { 2611 #ifdef FEAT_BROWSE 2612 if (cmdmod.browse) 2613 { 2614 char_u *fname = NULL; 2615 2616 fname = do_browse(0, (char_u *)_("Source Vim script"), eap->arg, 2617 NULL, NULL, 2618 (char_u *)_(BROWSE_FILTER_MACROS), NULL); 2619 if (fname != NULL) 2620 { 2621 cmd_source(fname, eap); 2622 vim_free(fname); 2623 } 2624 } 2625 else 2626 #endif 2627 cmd_source(eap->arg, eap); 2628 } 2629 2630 static void 2631 cmd_source(char_u *fname, exarg_T *eap) 2632 { 2633 if (*fname == NUL) 2634 emsg(_(e_argreq)); 2635 2636 else if (eap != NULL && eap->forceit) 2637 /* ":source!": read Normal mode commands 2638 * Need to execute the commands directly. This is required at least 2639 * for: 2640 * - ":g" command busy 2641 * - after ":argdo", ":windo" or ":bufdo" 2642 * - another command follows 2643 * - inside a loop 2644 */ 2645 openscript(fname, global_busy || listcmd_busy || eap->nextcmd != NULL 2646 #ifdef FEAT_EVAL 2647 || eap->cstack->cs_idx >= 0 2648 #endif 2649 ); 2650 2651 /* ":source" read ex commands */ 2652 else if (do_source(fname, FALSE, DOSO_NONE) == FAIL) 2653 semsg(_(e_notopen), fname); 2654 } 2655 2656 /* 2657 * ":source" and associated commands. 2658 */ 2659 /* 2660 * Structure used to store info for each sourced file. 2661 * It is shared between do_source() and getsourceline(). 2662 * This is required, because it needs to be handed to do_cmdline() and 2663 * sourcing can be done recursively. 2664 */ 2665 struct source_cookie 2666 { 2667 FILE *fp; // opened file for sourcing 2668 char_u *nextline; // if not NULL: line that was read ahead 2669 linenr_T sourcing_lnum; // line number of the source file 2670 int finished; // ":finish" used 2671 #ifdef USE_CRNL 2672 int fileformat; // EOL_UNKNOWN, EOL_UNIX or EOL_DOS 2673 int error; // TRUE if LF found after CR-LF 2674 #endif 2675 #ifdef FEAT_EVAL 2676 linenr_T breakpoint; // next line with breakpoint or zero 2677 char_u *fname; // name of sourced file 2678 int dbg_tick; // debug_tick when breakpoint was set 2679 int level; // top nesting level of sourced file 2680 #endif 2681 vimconv_T conv; // type of conversion 2682 }; 2683 2684 #ifdef FEAT_EVAL 2685 /* 2686 * Return the address holding the next breakpoint line for a source cookie. 2687 */ 2688 linenr_T * 2689 source_breakpoint(void *cookie) 2690 { 2691 return &((struct source_cookie *)cookie)->breakpoint; 2692 } 2693 2694 /* 2695 * Return the address holding the debug tick for a source cookie. 2696 */ 2697 int * 2698 source_dbg_tick(void *cookie) 2699 { 2700 return &((struct source_cookie *)cookie)->dbg_tick; 2701 } 2702 2703 /* 2704 * Return the nesting level for a source cookie. 2705 */ 2706 int 2707 source_level(void *cookie) 2708 { 2709 return ((struct source_cookie *)cookie)->level; 2710 } 2711 #endif 2712 2713 static char_u *get_one_sourceline(struct source_cookie *sp); 2714 2715 #if (defined(MSWIN) && defined(FEAT_CSCOPE)) || defined(HAVE_FD_CLOEXEC) 2716 # define USE_FOPEN_NOINH 2717 /* 2718 * Special function to open a file without handle inheritance. 2719 * When possible the handle is closed on exec(). 2720 */ 2721 static FILE * 2722 fopen_noinh_readbin(char *filename) 2723 { 2724 # ifdef MSWIN 2725 int fd_tmp = mch_open(filename, O_RDONLY | O_BINARY | O_NOINHERIT, 0); 2726 # else 2727 int fd_tmp = mch_open(filename, O_RDONLY, 0); 2728 # endif 2729 2730 if (fd_tmp == -1) 2731 return NULL; 2732 2733 # ifdef HAVE_FD_CLOEXEC 2734 { 2735 int fdflags = fcntl(fd_tmp, F_GETFD); 2736 if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) 2737 (void)fcntl(fd_tmp, F_SETFD, fdflags | FD_CLOEXEC); 2738 } 2739 # endif 2740 2741 return fdopen(fd_tmp, READBIN); 2742 } 2743 #endif 2744 2745 /* 2746 * do_source: Read the file "fname" and execute its lines as EX commands. 2747 * 2748 * This function may be called recursively! 2749 * 2750 * return FAIL if file could not be opened, OK otherwise 2751 */ 2752 int 2753 do_source( 2754 char_u *fname, 2755 int check_other, /* check for .vimrc and _vimrc */ 2756 int is_vimrc) /* DOSO_ value */ 2757 { 2758 struct source_cookie cookie; 2759 char_u *save_sourcing_name; 2760 linenr_T save_sourcing_lnum; 2761 char_u *p; 2762 char_u *fname_exp; 2763 char_u *firstline = NULL; 2764 int retval = FAIL; 2765 #ifdef FEAT_EVAL 2766 sctx_T save_current_sctx; 2767 static scid_T last_current_SID = 0; 2768 static int last_current_SID_seq = 0; 2769 funccal_entry_T funccalp_entry; 2770 int save_debug_break_level = debug_break_level; 2771 scriptitem_T *si = NULL; 2772 # ifdef UNIX 2773 stat_T st; 2774 int stat_ok; 2775 # endif 2776 #endif 2777 #ifdef STARTUPTIME 2778 struct timeval tv_rel; 2779 struct timeval tv_start; 2780 #endif 2781 #ifdef FEAT_PROFILE 2782 proftime_T wait_start; 2783 #endif 2784 int trigger_source_post = FALSE; 2785 2786 p = expand_env_save(fname); 2787 if (p == NULL) 2788 return retval; 2789 fname_exp = fix_fname(p); 2790 vim_free(p); 2791 if (fname_exp == NULL) 2792 return retval; 2793 if (mch_isdir(fname_exp)) 2794 { 2795 smsg(_("Cannot source a directory: \"%s\""), fname); 2796 goto theend; 2797 } 2798 2799 /* Apply SourceCmd autocommands, they should get the file and source it. */ 2800 if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL) 2801 && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp, 2802 FALSE, curbuf)) 2803 { 2804 #ifdef FEAT_EVAL 2805 retval = aborting() ? FAIL : OK; 2806 #else 2807 retval = OK; 2808 #endif 2809 if (retval == OK) 2810 // Apply SourcePost autocommands. 2811 apply_autocmds(EVENT_SOURCEPOST, fname_exp, fname_exp, 2812 FALSE, curbuf); 2813 goto theend; 2814 } 2815 2816 /* Apply SourcePre autocommands, they may get the file. */ 2817 apply_autocmds(EVENT_SOURCEPRE, fname_exp, fname_exp, FALSE, curbuf); 2818 2819 #ifdef USE_FOPEN_NOINH 2820 cookie.fp = fopen_noinh_readbin((char *)fname_exp); 2821 #else 2822 cookie.fp = mch_fopen((char *)fname_exp, READBIN); 2823 #endif 2824 if (cookie.fp == NULL && check_other) 2825 { 2826 /* 2827 * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa, 2828 * and ".exrc" by "_exrc" or vice versa. 2829 */ 2830 p = gettail(fname_exp); 2831 if ((*p == '.' || *p == '_') 2832 && (STRICMP(p + 1, "vimrc") == 0 2833 || STRICMP(p + 1, "gvimrc") == 0 2834 || STRICMP(p + 1, "exrc") == 0)) 2835 { 2836 if (*p == '_') 2837 *p = '.'; 2838 else 2839 *p = '_'; 2840 #ifdef USE_FOPEN_NOINH 2841 cookie.fp = fopen_noinh_readbin((char *)fname_exp); 2842 #else 2843 cookie.fp = mch_fopen((char *)fname_exp, READBIN); 2844 #endif 2845 } 2846 } 2847 2848 if (cookie.fp == NULL) 2849 { 2850 if (p_verbose > 0) 2851 { 2852 verbose_enter(); 2853 if (sourcing_name == NULL) 2854 smsg(_("could not source \"%s\""), fname); 2855 else 2856 smsg(_("line %ld: could not source \"%s\""), 2857 sourcing_lnum, fname); 2858 verbose_leave(); 2859 } 2860 goto theend; 2861 } 2862 2863 /* 2864 * The file exists. 2865 * - In verbose mode, give a message. 2866 * - For a vimrc file, may want to set 'compatible', call vimrc_found(). 2867 */ 2868 if (p_verbose > 1) 2869 { 2870 verbose_enter(); 2871 if (sourcing_name == NULL) 2872 smsg(_("sourcing \"%s\""), fname); 2873 else 2874 smsg(_("line %ld: sourcing \"%s\""), 2875 sourcing_lnum, fname); 2876 verbose_leave(); 2877 } 2878 if (is_vimrc == DOSO_VIMRC) 2879 vimrc_found(fname_exp, (char_u *)"MYVIMRC"); 2880 else if (is_vimrc == DOSO_GVIMRC) 2881 vimrc_found(fname_exp, (char_u *)"MYGVIMRC"); 2882 2883 #ifdef USE_CRNL 2884 /* If no automatic file format: Set default to CR-NL. */ 2885 if (*p_ffs == NUL) 2886 cookie.fileformat = EOL_DOS; 2887 else 2888 cookie.fileformat = EOL_UNKNOWN; 2889 cookie.error = FALSE; 2890 #endif 2891 2892 cookie.nextline = NULL; 2893 cookie.sourcing_lnum = 0; 2894 cookie.finished = FALSE; 2895 2896 #ifdef FEAT_EVAL 2897 /* 2898 * Check if this script has a breakpoint. 2899 */ 2900 cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0); 2901 cookie.fname = fname_exp; 2902 cookie.dbg_tick = debug_tick; 2903 2904 cookie.level = ex_nesting_level; 2905 #endif 2906 2907 /* 2908 * Keep the sourcing name/lnum, for recursive calls. 2909 */ 2910 save_sourcing_name = sourcing_name; 2911 sourcing_name = fname_exp; 2912 save_sourcing_lnum = sourcing_lnum; 2913 sourcing_lnum = 0; 2914 2915 #ifdef STARTUPTIME 2916 if (time_fd != NULL) 2917 time_push(&tv_rel, &tv_start); 2918 #endif 2919 2920 #ifdef FEAT_EVAL 2921 # ifdef FEAT_PROFILE 2922 if (do_profiling == PROF_YES) 2923 prof_child_enter(&wait_start); /* entering a child now */ 2924 # endif 2925 2926 /* Don't use local function variables, if called from a function. 2927 * Also starts profiling timer for nested script. */ 2928 save_funccal(&funccalp_entry); 2929 2930 save_current_sctx = current_sctx; 2931 current_sctx.sc_lnum = 0; 2932 current_sctx.sc_version = 1; 2933 2934 // Check if this script was sourced before to finds its SID. 2935 // If it's new, generate a new SID. 2936 // Always use a new sequence number. 2937 current_sctx.sc_seq = ++last_current_SID_seq; 2938 # ifdef UNIX 2939 stat_ok = (mch_stat((char *)fname_exp, &st) >= 0); 2940 # endif 2941 for (current_sctx.sc_sid = script_items.ga_len; current_sctx.sc_sid > 0; 2942 --current_sctx.sc_sid) 2943 { 2944 si = &SCRIPT_ITEM(current_sctx.sc_sid); 2945 if (si->sn_name != NULL 2946 && ( 2947 # ifdef UNIX 2948 /* Compare dev/ino when possible, it catches symbolic 2949 * links. Also compare file names, the inode may change 2950 * when the file was edited. */ 2951 ((stat_ok && si->sn_dev_valid) 2952 && (si->sn_dev == st.st_dev 2953 && si->sn_ino == st.st_ino)) || 2954 # endif 2955 fnamecmp(si->sn_name, fname_exp) == 0)) 2956 break; 2957 } 2958 if (current_sctx.sc_sid == 0) 2959 { 2960 current_sctx.sc_sid = ++last_current_SID; 2961 if (ga_grow(&script_items, 2962 (int)(current_sctx.sc_sid - script_items.ga_len)) == FAIL) 2963 goto almosttheend; 2964 while (script_items.ga_len < current_sctx.sc_sid) 2965 { 2966 ++script_items.ga_len; 2967 SCRIPT_ITEM(script_items.ga_len).sn_name = NULL; 2968 # ifdef FEAT_PROFILE 2969 SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE; 2970 # endif 2971 } 2972 si = &SCRIPT_ITEM(current_sctx.sc_sid); 2973 si->sn_name = fname_exp; 2974 fname_exp = vim_strsave(si->sn_name); // used for autocmd 2975 # ifdef UNIX 2976 if (stat_ok) 2977 { 2978 si->sn_dev_valid = TRUE; 2979 si->sn_dev = st.st_dev; 2980 si->sn_ino = st.st_ino; 2981 } 2982 else 2983 si->sn_dev_valid = FALSE; 2984 # endif 2985 2986 /* Allocate the local script variables to use for this script. */ 2987 new_script_vars(current_sctx.sc_sid); 2988 } 2989 2990 # ifdef FEAT_PROFILE 2991 if (do_profiling == PROF_YES) 2992 { 2993 int forceit; 2994 2995 /* Check if we do profiling for this script. */ 2996 if (!si->sn_prof_on && has_profiling(TRUE, si->sn_name, &forceit)) 2997 { 2998 script_do_profile(si); 2999 si->sn_pr_force = forceit; 3000 } 3001 if (si->sn_prof_on) 3002 { 3003 ++si->sn_pr_count; 3004 profile_start(&si->sn_pr_start); 3005 profile_zero(&si->sn_pr_children); 3006 } 3007 } 3008 # endif 3009 #endif 3010 3011 cookie.conv.vc_type = CONV_NONE; /* no conversion */ 3012 3013 /* Read the first line so we can check for a UTF-8 BOM. */ 3014 firstline = getsourceline(0, (void *)&cookie, 0, TRUE); 3015 if (firstline != NULL && STRLEN(firstline) >= 3 && firstline[0] == 0xef 3016 && firstline[1] == 0xbb && firstline[2] == 0xbf) 3017 { 3018 /* Found BOM; setup conversion, skip over BOM and recode the line. */ 3019 convert_setup(&cookie.conv, (char_u *)"utf-8", p_enc); 3020 p = string_convert(&cookie.conv, firstline + 3, NULL); 3021 if (p == NULL) 3022 p = vim_strsave(firstline + 3); 3023 if (p != NULL) 3024 { 3025 vim_free(firstline); 3026 firstline = p; 3027 } 3028 } 3029 3030 /* 3031 * Call do_cmdline, which will call getsourceline() to get the lines. 3032 */ 3033 do_cmdline(firstline, getsourceline, (void *)&cookie, 3034 DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT); 3035 retval = OK; 3036 3037 #ifdef FEAT_PROFILE 3038 if (do_profiling == PROF_YES) 3039 { 3040 /* Get "si" again, "script_items" may have been reallocated. */ 3041 si = &SCRIPT_ITEM(current_sctx.sc_sid); 3042 if (si->sn_prof_on) 3043 { 3044 profile_end(&si->sn_pr_start); 3045 profile_sub_wait(&wait_start, &si->sn_pr_start); 3046 profile_add(&si->sn_pr_total, &si->sn_pr_start); 3047 profile_self(&si->sn_pr_self, &si->sn_pr_start, 3048 &si->sn_pr_children); 3049 } 3050 } 3051 #endif 3052 3053 if (got_int) 3054 emsg(_(e_interr)); 3055 sourcing_name = save_sourcing_name; 3056 sourcing_lnum = save_sourcing_lnum; 3057 if (p_verbose > 1) 3058 { 3059 verbose_enter(); 3060 smsg(_("finished sourcing %s"), fname); 3061 if (sourcing_name != NULL) 3062 smsg(_("continuing in %s"), sourcing_name); 3063 verbose_leave(); 3064 } 3065 #ifdef STARTUPTIME 3066 if (time_fd != NULL) 3067 { 3068 vim_snprintf((char *)IObuff, IOSIZE, "sourcing %s", fname); 3069 time_msg((char *)IObuff, &tv_start); 3070 time_pop(&tv_rel); 3071 } 3072 #endif 3073 3074 if (!got_int) 3075 trigger_source_post = TRUE; 3076 3077 #ifdef FEAT_EVAL 3078 /* 3079 * After a "finish" in debug mode, need to break at first command of next 3080 * sourced file. 3081 */ 3082 if (save_debug_break_level > ex_nesting_level 3083 && debug_break_level == ex_nesting_level) 3084 ++debug_break_level; 3085 #endif 3086 3087 #ifdef FEAT_EVAL 3088 almosttheend: 3089 current_sctx = save_current_sctx; 3090 restore_funccal(); 3091 # ifdef FEAT_PROFILE 3092 if (do_profiling == PROF_YES) 3093 prof_child_exit(&wait_start); /* leaving a child now */ 3094 # endif 3095 #endif 3096 fclose(cookie.fp); 3097 vim_free(cookie.nextline); 3098 vim_free(firstline); 3099 convert_setup(&cookie.conv, NULL, NULL); 3100 3101 if (trigger_source_post) 3102 apply_autocmds(EVENT_SOURCEPOST, fname_exp, fname_exp, FALSE, curbuf); 3103 3104 theend: 3105 vim_free(fname_exp); 3106 return retval; 3107 } 3108 3109 #if defined(FEAT_EVAL) || defined(PROTO) 3110 3111 /* 3112 * ":scriptnames" 3113 */ 3114 void 3115 ex_scriptnames(exarg_T *eap) 3116 { 3117 int i; 3118 3119 if (eap->addr_count > 0) 3120 { 3121 // :script {scriptId}: edit the script 3122 if (eap->line2 < 1 || eap->line2 > script_items.ga_len) 3123 emsg(_(e_invarg)); 3124 else 3125 { 3126 eap->arg = SCRIPT_ITEM(eap->line2).sn_name; 3127 do_exedit(eap, NULL); 3128 } 3129 return; 3130 } 3131 3132 for (i = 1; i <= script_items.ga_len && !got_int; ++i) 3133 if (SCRIPT_ITEM(i).sn_name != NULL) 3134 { 3135 home_replace(NULL, SCRIPT_ITEM(i).sn_name, 3136 NameBuff, MAXPATHL, TRUE); 3137 smsg("%3d: %s", i, NameBuff); 3138 } 3139 } 3140 3141 # if defined(BACKSLASH_IN_FILENAME) || defined(PROTO) 3142 /* 3143 * Fix slashes in the list of script names for 'shellslash'. 3144 */ 3145 void 3146 scriptnames_slash_adjust(void) 3147 { 3148 int i; 3149 3150 for (i = 1; i <= script_items.ga_len; ++i) 3151 if (SCRIPT_ITEM(i).sn_name != NULL) 3152 slash_adjust(SCRIPT_ITEM(i).sn_name); 3153 } 3154 # endif 3155 3156 /* 3157 * Get a pointer to a script name. Used for ":verbose set". 3158 */ 3159 char_u * 3160 get_scriptname(scid_T id) 3161 { 3162 if (id == SID_MODELINE) 3163 return (char_u *)_("modeline"); 3164 if (id == SID_CMDARG) 3165 return (char_u *)_("--cmd argument"); 3166 if (id == SID_CARG) 3167 return (char_u *)_("-c argument"); 3168 if (id == SID_ENV) 3169 return (char_u *)_("environment variable"); 3170 if (id == SID_ERROR) 3171 return (char_u *)_("error handler"); 3172 return SCRIPT_ITEM(id).sn_name; 3173 } 3174 3175 # if defined(EXITFREE) || defined(PROTO) 3176 void 3177 free_scriptnames(void) 3178 { 3179 int i; 3180 3181 for (i = script_items.ga_len; i > 0; --i) 3182 vim_free(SCRIPT_ITEM(i).sn_name); 3183 ga_clear(&script_items); 3184 } 3185 # endif 3186 3187 #endif 3188 3189 linenr_T 3190 get_sourced_lnum(char_u *(*fgetline)(int, void *, int, int), void *cookie) 3191 { 3192 return fgetline == getsourceline 3193 ? ((struct source_cookie *)cookie)->sourcing_lnum 3194 : sourcing_lnum; 3195 } 3196 3197 /* 3198 * Get one full line from a sourced file. 3199 * Called by do_cmdline() when it's called from do_source(). 3200 * 3201 * Return a pointer to the line in allocated memory. 3202 * Return NULL for end-of-file or some error. 3203 */ 3204 char_u * 3205 getsourceline(int c UNUSED, void *cookie, int indent UNUSED, int do_concat) 3206 { 3207 struct source_cookie *sp = (struct source_cookie *)cookie; 3208 char_u *line; 3209 char_u *p; 3210 3211 #ifdef FEAT_EVAL 3212 /* If breakpoints have been added/deleted need to check for it. */ 3213 if (sp->dbg_tick < debug_tick) 3214 { 3215 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum); 3216 sp->dbg_tick = debug_tick; 3217 } 3218 # ifdef FEAT_PROFILE 3219 if (do_profiling == PROF_YES) 3220 script_line_end(); 3221 # endif 3222 #endif 3223 3224 // Set the current sourcing line number. 3225 sourcing_lnum = sp->sourcing_lnum + 1; 3226 3227 /* 3228 * Get current line. If there is a read-ahead line, use it, otherwise get 3229 * one now. 3230 */ 3231 if (sp->finished) 3232 line = NULL; 3233 else if (sp->nextline == NULL) 3234 line = get_one_sourceline(sp); 3235 else 3236 { 3237 line = sp->nextline; 3238 sp->nextline = NULL; 3239 ++sp->sourcing_lnum; 3240 } 3241 #ifdef FEAT_PROFILE 3242 if (line != NULL && do_profiling == PROF_YES) 3243 script_line_start(); 3244 #endif 3245 3246 /* Only concatenate lines starting with a \ when 'cpoptions' doesn't 3247 * contain the 'C' flag. */ 3248 if (line != NULL && do_concat && vim_strchr(p_cpo, CPO_CONCAT) == NULL) 3249 { 3250 /* compensate for the one line read-ahead */ 3251 --sp->sourcing_lnum; 3252 3253 // Get the next line and concatenate it when it starts with a 3254 // backslash. We always need to read the next line, keep it in 3255 // sp->nextline. 3256 /* Also check for a comment in between continuation lines: "\ */ 3257 sp->nextline = get_one_sourceline(sp); 3258 if (sp->nextline != NULL 3259 && (*(p = skipwhite(sp->nextline)) == '\\' 3260 || (p[0] == '"' && p[1] == '\\' && p[2] == ' '))) 3261 { 3262 garray_T ga; 3263 3264 ga_init2(&ga, (int)sizeof(char_u), 400); 3265 ga_concat(&ga, line); 3266 if (*p == '\\') 3267 ga_concat(&ga, p + 1); 3268 for (;;) 3269 { 3270 vim_free(sp->nextline); 3271 sp->nextline = get_one_sourceline(sp); 3272 if (sp->nextline == NULL) 3273 break; 3274 p = skipwhite(sp->nextline); 3275 if (*p == '\\') 3276 { 3277 // Adjust the growsize to the current length to speed up 3278 // concatenating many lines. 3279 if (ga.ga_len > 400) 3280 { 3281 if (ga.ga_len > 8000) 3282 ga.ga_growsize = 8000; 3283 else 3284 ga.ga_growsize = ga.ga_len; 3285 } 3286 ga_concat(&ga, p + 1); 3287 } 3288 else if (p[0] != '"' || p[1] != '\\' || p[2] != ' ') 3289 break; 3290 } 3291 ga_append(&ga, NUL); 3292 vim_free(line); 3293 line = ga.ga_data; 3294 } 3295 } 3296 3297 if (line != NULL && sp->conv.vc_type != CONV_NONE) 3298 { 3299 char_u *s; 3300 3301 /* Convert the encoding of the script line. */ 3302 s = string_convert(&sp->conv, line, NULL); 3303 if (s != NULL) 3304 { 3305 vim_free(line); 3306 line = s; 3307 } 3308 } 3309 3310 #ifdef FEAT_EVAL 3311 /* Did we encounter a breakpoint? */ 3312 if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum) 3313 { 3314 dbg_breakpoint(sp->fname, sourcing_lnum); 3315 /* Find next breakpoint. */ 3316 sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum); 3317 sp->dbg_tick = debug_tick; 3318 } 3319 #endif 3320 3321 return line; 3322 } 3323 3324 static char_u * 3325 get_one_sourceline(struct source_cookie *sp) 3326 { 3327 garray_T ga; 3328 int len; 3329 int c; 3330 char_u *buf; 3331 #ifdef USE_CRNL 3332 int has_cr; /* CR-LF found */ 3333 #endif 3334 int have_read = FALSE; 3335 3336 /* use a growarray to store the sourced line */ 3337 ga_init2(&ga, 1, 250); 3338 3339 /* 3340 * Loop until there is a finished line (or end-of-file). 3341 */ 3342 ++sp->sourcing_lnum; 3343 for (;;) 3344 { 3345 /* make room to read at least 120 (more) characters */ 3346 if (ga_grow(&ga, 120) == FAIL) 3347 break; 3348 buf = (char_u *)ga.ga_data; 3349 3350 if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len, 3351 sp->fp) == NULL) 3352 break; 3353 len = ga.ga_len + (int)STRLEN(buf + ga.ga_len); 3354 #ifdef USE_CRNL 3355 /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the 3356 * CTRL-Z by its own, or after a NL. */ 3357 if ( (len == 1 || (len >= 2 && buf[len - 2] == '\n')) 3358 && sp->fileformat == EOL_DOS 3359 && buf[len - 1] == Ctrl_Z) 3360 { 3361 buf[len - 1] = NUL; 3362 break; 3363 } 3364 #endif 3365 3366 have_read = TRUE; 3367 ga.ga_len = len; 3368 3369 /* If the line was longer than the buffer, read more. */ 3370 if (ga.ga_maxlen - ga.ga_len == 1 && buf[len - 1] != '\n') 3371 continue; 3372 3373 if (len >= 1 && buf[len - 1] == '\n') /* remove trailing NL */ 3374 { 3375 #ifdef USE_CRNL 3376 has_cr = (len >= 2 && buf[len - 2] == '\r'); 3377 if (sp->fileformat == EOL_UNKNOWN) 3378 { 3379 if (has_cr) 3380 sp->fileformat = EOL_DOS; 3381 else 3382 sp->fileformat = EOL_UNIX; 3383 } 3384 3385 if (sp->fileformat == EOL_DOS) 3386 { 3387 if (has_cr) /* replace trailing CR */ 3388 { 3389 buf[len - 2] = '\n'; 3390 --len; 3391 --ga.ga_len; 3392 } 3393 else /* lines like ":map xx yy^M" will have failed */ 3394 { 3395 if (!sp->error) 3396 { 3397 msg_source(HL_ATTR(HLF_W)); 3398 emsg(_("W15: Warning: Wrong line separator, ^M may be missing")); 3399 } 3400 sp->error = TRUE; 3401 sp->fileformat = EOL_UNIX; 3402 } 3403 } 3404 #endif 3405 /* The '\n' is escaped if there is an odd number of ^V's just 3406 * before it, first set "c" just before the 'V's and then check 3407 * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */ 3408 for (c = len - 2; c >= 0 && buf[c] == Ctrl_V; c--) 3409 ; 3410 if ((len & 1) != (c & 1)) /* escaped NL, read more */ 3411 { 3412 ++sp->sourcing_lnum; 3413 continue; 3414 } 3415 3416 buf[len - 1] = NUL; /* remove the NL */ 3417 } 3418 3419 /* 3420 * Check for ^C here now and then, so recursive :so can be broken. 3421 */ 3422 line_breakcheck(); 3423 break; 3424 } 3425 3426 if (have_read) 3427 return (char_u *)ga.ga_data; 3428 3429 vim_free(ga.ga_data); 3430 return NULL; 3431 } 3432 3433 /* 3434 * ":scriptencoding": Set encoding conversion for a sourced script. 3435 */ 3436 void 3437 ex_scriptencoding(exarg_T *eap) 3438 { 3439 struct source_cookie *sp; 3440 char_u *name; 3441 3442 if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 3443 { 3444 emsg(_("E167: :scriptencoding used outside of a sourced file")); 3445 return; 3446 } 3447 3448 if (*eap->arg != NUL) 3449 { 3450 name = enc_canonize(eap->arg); 3451 if (name == NULL) /* out of memory */ 3452 return; 3453 } 3454 else 3455 name = eap->arg; 3456 3457 /* Setup for conversion from the specified encoding to 'encoding'. */ 3458 sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie); 3459 convert_setup(&sp->conv, name, p_enc); 3460 3461 if (name != eap->arg) 3462 vim_free(name); 3463 } 3464 3465 /* 3466 * ":scriptversion": Set Vim script version for a sourced script. 3467 */ 3468 void 3469 ex_scriptversion(exarg_T *eap UNUSED) 3470 { 3471 #ifdef FEAT_EVAL 3472 int nr; 3473 3474 if (!getline_equal(eap->getline, eap->cookie, getsourceline)) 3475 { 3476 emsg(_("E984: :scriptversion used outside of a sourced file")); 3477 return; 3478 } 3479 3480 nr = getdigits(&eap->arg); 3481 if (nr == 0 || *eap->arg != NUL) 3482 emsg(_(e_invarg)); 3483 else if (nr > 3) 3484 semsg(_("E999: scriptversion not supported: %d"), nr); 3485 else 3486 current_sctx.sc_version = nr; 3487 #endif 3488 } 3489 3490 #if defined(FEAT_EVAL) || defined(PROTO) 3491 /* 3492 * ":finish": Mark a sourced file as finished. 3493 */ 3494 void 3495 ex_finish(exarg_T *eap) 3496 { 3497 if (getline_equal(eap->getline, eap->cookie, getsourceline)) 3498 do_finish(eap, FALSE); 3499 else 3500 emsg(_("E168: :finish used outside of a sourced file")); 3501 } 3502 3503 /* 3504 * Mark a sourced file as finished. Possibly makes the ":finish" pending. 3505 * Also called for a pending finish at the ":endtry" or after returning from 3506 * an extra do_cmdline(). "reanimate" is used in the latter case. 3507 */ 3508 void 3509 do_finish(exarg_T *eap, int reanimate) 3510 { 3511 int idx; 3512 3513 if (reanimate) 3514 ((struct source_cookie *)getline_cookie(eap->getline, 3515 eap->cookie))->finished = FALSE; 3516 3517 /* 3518 * Cleanup (and inactivate) conditionals, but stop when a try conditional 3519 * not in its finally clause (which then is to be executed next) is found. 3520 * In this case, make the ":finish" pending for execution at the ":endtry". 3521 * Otherwise, finish normally. 3522 */ 3523 idx = cleanup_conditionals(eap->cstack, 0, TRUE); 3524 if (idx >= 0) 3525 { 3526 eap->cstack->cs_pending[idx] = CSTP_FINISH; 3527 report_make_pending(CSTP_FINISH, NULL); 3528 } 3529 else 3530 ((struct source_cookie *)getline_cookie(eap->getline, 3531 eap->cookie))->finished = TRUE; 3532 } 3533 3534 3535 /* 3536 * Return TRUE when a sourced file had the ":finish" command: Don't give error 3537 * message for missing ":endif". 3538 * Return FALSE when not sourcing a file. 3539 */ 3540 int 3541 source_finished( 3542 char_u *(*fgetline)(int, void *, int, int), 3543 void *cookie) 3544 { 3545 return (getline_equal(fgetline, cookie, getsourceline) 3546 && ((struct source_cookie *)getline_cookie( 3547 fgetline, cookie))->finished); 3548 } 3549 #endif 3550 3551 /* 3552 * ":checktime [buffer]" 3553 */ 3554 void 3555 ex_checktime(exarg_T *eap) 3556 { 3557 buf_T *buf; 3558 int save_no_check_timestamps = no_check_timestamps; 3559 3560 no_check_timestamps = 0; 3561 if (eap->addr_count == 0) /* default is all buffers */ 3562 check_timestamps(FALSE); 3563 else 3564 { 3565 buf = buflist_findnr((int)eap->line2); 3566 if (buf != NULL) /* cannot happen? */ 3567 (void)buf_check_timestamp(buf, FALSE); 3568 } 3569 no_check_timestamps = save_no_check_timestamps; 3570 } 3571 3572 #if (defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 3573 && (defined(FEAT_EVAL) || defined(FEAT_MULTI_LANG)) 3574 # define HAVE_GET_LOCALE_VAL 3575 static char_u * 3576 get_locale_val(int what) 3577 { 3578 char_u *loc; 3579 3580 /* Obtain the locale value from the libraries. */ 3581 loc = (char_u *)setlocale(what, NULL); 3582 3583 # ifdef MSWIN 3584 if (loc != NULL) 3585 { 3586 char_u *p; 3587 3588 /* setocale() returns something like "LC_COLLATE=<name>;LC_..." when 3589 * one of the values (e.g., LC_CTYPE) differs. */ 3590 p = vim_strchr(loc, '='); 3591 if (p != NULL) 3592 { 3593 loc = ++p; 3594 while (*p != NUL) /* remove trailing newline */ 3595 { 3596 if (*p < ' ' || *p == ';') 3597 { 3598 *p = NUL; 3599 break; 3600 } 3601 ++p; 3602 } 3603 } 3604 } 3605 # endif 3606 3607 return loc; 3608 } 3609 #endif 3610 3611 3612 #ifdef MSWIN 3613 /* 3614 * On MS-Windows locale names are strings like "German_Germany.1252", but 3615 * gettext expects "de". Try to translate one into another here for a few 3616 * supported languages. 3617 */ 3618 static char_u * 3619 gettext_lang(char_u *name) 3620 { 3621 int i; 3622 static char *(mtable[]) = { 3623 "afrikaans", "af", 3624 "czech", "cs", 3625 "dutch", "nl", 3626 "german", "de", 3627 "english_united kingdom", "en_GB", 3628 "spanish", "es", 3629 "french", "fr", 3630 "italian", "it", 3631 "japanese", "ja", 3632 "korean", "ko", 3633 "norwegian", "no", 3634 "polish", "pl", 3635 "russian", "ru", 3636 "slovak", "sk", 3637 "swedish", "sv", 3638 "ukrainian", "uk", 3639 "chinese_china", "zh_CN", 3640 "chinese_taiwan", "zh_TW", 3641 NULL}; 3642 3643 for (i = 0; mtable[i] != NULL; i += 2) 3644 if (STRNICMP(mtable[i], name, STRLEN(mtable[i])) == 0) 3645 return (char_u *)mtable[i + 1]; 3646 return name; 3647 } 3648 #endif 3649 3650 #if defined(FEAT_MULTI_LANG) || defined(PROTO) 3651 /* 3652 * Return TRUE when "lang" starts with a valid language name. 3653 * Rejects NULL, empty string, "C", "C.UTF-8" and others. 3654 */ 3655 static int 3656 is_valid_mess_lang(char_u *lang) 3657 { 3658 return lang != NULL && ASCII_ISALPHA(lang[0]) && ASCII_ISALPHA(lang[1]); 3659 } 3660 3661 /* 3662 * Obtain the current messages language. Used to set the default for 3663 * 'helplang'. May return NULL or an empty string. 3664 */ 3665 char_u * 3666 get_mess_lang(void) 3667 { 3668 char_u *p; 3669 3670 # ifdef HAVE_GET_LOCALE_VAL 3671 # if defined(LC_MESSAGES) 3672 p = get_locale_val(LC_MESSAGES); 3673 # else 3674 /* This is necessary for Win32, where LC_MESSAGES is not defined and $LANG 3675 * may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME 3676 * and LC_MONETARY may be set differently for a Japanese working in the 3677 * US. */ 3678 p = get_locale_val(LC_COLLATE); 3679 # endif 3680 # else 3681 p = mch_getenv((char_u *)"LC_ALL"); 3682 if (!is_valid_mess_lang(p)) 3683 { 3684 p = mch_getenv((char_u *)"LC_MESSAGES"); 3685 if (!is_valid_mess_lang(p)) 3686 p = mch_getenv((char_u *)"LANG"); 3687 } 3688 # endif 3689 # ifdef MSWIN 3690 p = gettext_lang(p); 3691 # endif 3692 return is_valid_mess_lang(p) ? p : NULL; 3693 } 3694 #endif 3695 3696 /* Complicated #if; matches with where get_mess_env() is used below. */ 3697 #if (defined(FEAT_EVAL) && !((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 3698 && defined(LC_MESSAGES))) \ 3699 || ((defined(HAVE_LOCALE_H) || defined(X_LOCALE)) \ 3700 && !defined(LC_MESSAGES)) 3701 /* 3702 * Get the language used for messages from the environment. 3703 */ 3704 static char_u * 3705 get_mess_env(void) 3706 { 3707 char_u *p; 3708 3709 p = mch_getenv((char_u *)"LC_ALL"); 3710 if (p == NULL || *p == NUL) 3711 { 3712 p = mch_getenv((char_u *)"LC_MESSAGES"); 3713 if (p == NULL || *p == NUL) 3714 { 3715 p = mch_getenv((char_u *)"LANG"); 3716 if (p != NULL && VIM_ISDIGIT(*p)) 3717 p = NULL; /* ignore something like "1043" */ 3718 # ifdef HAVE_GET_LOCALE_VAL 3719 if (p == NULL || *p == NUL) 3720 p = get_locale_val(LC_CTYPE); 3721 # endif 3722 } 3723 } 3724 return p; 3725 } 3726 #endif 3727 3728 #if defined(FEAT_EVAL) || defined(PROTO) 3729 3730 /* 3731 * Set the "v:lang" variable according to the current locale setting. 3732 * Also do "v:lc_time"and "v:ctype". 3733 */ 3734 void 3735 set_lang_var(void) 3736 { 3737 char_u *loc; 3738 3739 # ifdef HAVE_GET_LOCALE_VAL 3740 loc = get_locale_val(LC_CTYPE); 3741 # else 3742 /* setlocale() not supported: use the default value */ 3743 loc = (char_u *)"C"; 3744 # endif 3745 set_vim_var_string(VV_CTYPE, loc, -1); 3746 3747 /* When LC_MESSAGES isn't defined use the value from $LC_MESSAGES, fall 3748 * back to LC_CTYPE if it's empty. */ 3749 # if defined(HAVE_GET_LOCALE_VAL) && defined(LC_MESSAGES) 3750 loc = get_locale_val(LC_MESSAGES); 3751 # else 3752 loc = get_mess_env(); 3753 # endif 3754 set_vim_var_string(VV_LANG, loc, -1); 3755 3756 # ifdef HAVE_GET_LOCALE_VAL 3757 loc = get_locale_val(LC_TIME); 3758 # endif 3759 set_vim_var_string(VV_LC_TIME, loc, -1); 3760 } 3761 #endif 3762 3763 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) \ 3764 /* 3765 * ":language": Set the language (locale). 3766 */ 3767 void 3768 ex_language(exarg_T *eap) 3769 { 3770 char *loc; 3771 char_u *p; 3772 char_u *name; 3773 int what = LC_ALL; 3774 char *whatstr = ""; 3775 #ifdef LC_MESSAGES 3776 # define VIM_LC_MESSAGES LC_MESSAGES 3777 #else 3778 # define VIM_LC_MESSAGES 6789 3779 #endif 3780 3781 name = eap->arg; 3782 3783 /* Check for "messages {name}", "ctype {name}" or "time {name}" argument. 3784 * Allow abbreviation, but require at least 3 characters to avoid 3785 * confusion with a two letter language name "me" or "ct". */ 3786 p = skiptowhite(eap->arg); 3787 if ((*p == NUL || VIM_ISWHITE(*p)) && p - eap->arg >= 3) 3788 { 3789 if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0) 3790 { 3791 what = VIM_LC_MESSAGES; 3792 name = skipwhite(p); 3793 whatstr = "messages "; 3794 } 3795 else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0) 3796 { 3797 what = LC_CTYPE; 3798 name = skipwhite(p); 3799 whatstr = "ctype "; 3800 } 3801 else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0) 3802 { 3803 what = LC_TIME; 3804 name = skipwhite(p); 3805 whatstr = "time "; 3806 } 3807 } 3808 3809 if (*name == NUL) 3810 { 3811 #ifndef LC_MESSAGES 3812 if (what == VIM_LC_MESSAGES) 3813 p = get_mess_env(); 3814 else 3815 #endif 3816 p = (char_u *)setlocale(what, NULL); 3817 if (p == NULL || *p == NUL) 3818 p = (char_u *)"Unknown"; 3819 smsg(_("Current %slanguage: \"%s\""), whatstr, p); 3820 } 3821 else 3822 { 3823 #ifndef LC_MESSAGES 3824 if (what == VIM_LC_MESSAGES) 3825 loc = ""; 3826 else 3827 #endif 3828 { 3829 loc = setlocale(what, (char *)name); 3830 #if defined(FEAT_FLOAT) && defined(LC_NUMERIC) 3831 /* Make sure strtod() uses a decimal point, not a comma. */ 3832 setlocale(LC_NUMERIC, "C"); 3833 #endif 3834 } 3835 if (loc == NULL) 3836 semsg(_("E197: Cannot set language to \"%s\""), name); 3837 else 3838 { 3839 #ifdef HAVE_NL_MSG_CAT_CNTR 3840 /* Need to do this for GNU gettext, otherwise cached translations 3841 * will be used again. */ 3842 extern int _nl_msg_cat_cntr; 3843 3844 ++_nl_msg_cat_cntr; 3845 #endif 3846 /* Reset $LC_ALL, otherwise it would overrule everything. */ 3847 vim_setenv((char_u *)"LC_ALL", (char_u *)""); 3848 3849 if (what != LC_TIME) 3850 { 3851 /* Tell gettext() what to translate to. It apparently doesn't 3852 * use the currently effective locale. Also do this when 3853 * FEAT_GETTEXT isn't defined, so that shell commands use this 3854 * value. */ 3855 if (what == LC_ALL) 3856 { 3857 vim_setenv((char_u *)"LANG", name); 3858 3859 /* Clear $LANGUAGE because GNU gettext uses it. */ 3860 vim_setenv((char_u *)"LANGUAGE", (char_u *)""); 3861 # ifdef MSWIN 3862 /* Apparently MS-Windows printf() may cause a crash when 3863 * we give it 8-bit text while it's expecting text in the 3864 * current locale. This call avoids that. */ 3865 setlocale(LC_CTYPE, "C"); 3866 # endif 3867 } 3868 if (what != LC_CTYPE) 3869 { 3870 char_u *mname; 3871 #ifdef MSWIN 3872 mname = gettext_lang(name); 3873 #else 3874 mname = name; 3875 #endif 3876 vim_setenv((char_u *)"LC_MESSAGES", mname); 3877 #ifdef FEAT_MULTI_LANG 3878 set_helplang_default(mname); 3879 #endif 3880 } 3881 } 3882 3883 # ifdef FEAT_EVAL 3884 /* Set v:lang, v:lc_time and v:ctype to the final result. */ 3885 set_lang_var(); 3886 # endif 3887 # ifdef FEAT_TITLE 3888 maketitle(); 3889 # endif 3890 } 3891 } 3892 } 3893 3894 # if defined(FEAT_CMDL_COMPL) || defined(PROTO) 3895 3896 static char_u **locales = NULL; /* Array of all available locales */ 3897 3898 # ifndef MSWIN 3899 static int did_init_locales = FALSE; 3900 3901 /* Return an array of strings for all available locales + NULL for the 3902 * last element. Return NULL in case of error. */ 3903 static char_u ** 3904 find_locales(void) 3905 { 3906 garray_T locales_ga; 3907 char_u *loc; 3908 3909 /* Find all available locales by running command "locale -a". If this 3910 * doesn't work we won't have completion. */ 3911 char_u *locale_a = get_cmd_output((char_u *)"locale -a", 3912 NULL, SHELL_SILENT, NULL); 3913 if (locale_a == NULL) 3914 return NULL; 3915 ga_init2(&locales_ga, sizeof(char_u *), 20); 3916 3917 /* Transform locale_a string where each locale is separated by "\n" 3918 * into an array of locale strings. */ 3919 loc = (char_u *)strtok((char *)locale_a, "\n"); 3920 3921 while (loc != NULL) 3922 { 3923 if (ga_grow(&locales_ga, 1) == FAIL) 3924 break; 3925 loc = vim_strsave(loc); 3926 if (loc == NULL) 3927 break; 3928 3929 ((char_u **)locales_ga.ga_data)[locales_ga.ga_len++] = loc; 3930 loc = (char_u *)strtok(NULL, "\n"); 3931 } 3932 vim_free(locale_a); 3933 if (ga_grow(&locales_ga, 1) == FAIL) 3934 { 3935 ga_clear(&locales_ga); 3936 return NULL; 3937 } 3938 ((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL; 3939 return (char_u **)locales_ga.ga_data; 3940 } 3941 # endif 3942 3943 /* 3944 * Lazy initialization of all available locales. 3945 */ 3946 static void 3947 init_locales(void) 3948 { 3949 # ifndef MSWIN 3950 if (!did_init_locales) 3951 { 3952 did_init_locales = TRUE; 3953 locales = find_locales(); 3954 } 3955 # endif 3956 } 3957 3958 # if defined(EXITFREE) || defined(PROTO) 3959 void 3960 free_locales(void) 3961 { 3962 int i; 3963 if (locales != NULL) 3964 { 3965 for (i = 0; locales[i] != NULL; i++) 3966 vim_free(locales[i]); 3967 VIM_CLEAR(locales); 3968 } 3969 } 3970 # endif 3971 3972 /* 3973 * Function given to ExpandGeneric() to obtain the possible arguments of the 3974 * ":language" command. 3975 */ 3976 char_u * 3977 get_lang_arg(expand_T *xp UNUSED, int idx) 3978 { 3979 if (idx == 0) 3980 return (char_u *)"messages"; 3981 if (idx == 1) 3982 return (char_u *)"ctype"; 3983 if (idx == 2) 3984 return (char_u *)"time"; 3985 3986 init_locales(); 3987 if (locales == NULL) 3988 return NULL; 3989 return locales[idx - 3]; 3990 } 3991 3992 /* 3993 * Function given to ExpandGeneric() to obtain the available locales. 3994 */ 3995 char_u * 3996 get_locales(expand_T *xp UNUSED, int idx) 3997 { 3998 init_locales(); 3999 if (locales == NULL) 4000 return NULL; 4001 return locales[idx]; 4002 } 4003 # endif 4004 4005 #endif 4006