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 * misc1.c: functions that didn't seem to fit elsewhere 12 */ 13 14 #include "vim.h" 15 #include "version.h" 16 17 #if defined(FEAT_CMDL_COMPL) && defined(WIN3264) 18 # include <lm.h> 19 #endif 20 21 static char_u *vim_version_dir(char_u *vimdir); 22 static char_u *remove_tail(char_u *p, char_u *pend, char_u *name); 23 24 /* All user names (for ~user completion as done by shell). */ 25 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 26 static garray_T ga_users; 27 #endif 28 29 /* 30 * Count the size (in window cells) of the indent in the current line. 31 */ 32 int 33 get_indent(void) 34 { 35 #ifdef FEAT_VARTABS 36 return get_indent_str_vtab(ml_get_curline(), (int)curbuf->b_p_ts, 37 curbuf->b_p_vts_array, FALSE); 38 #else 39 return get_indent_str(ml_get_curline(), (int)curbuf->b_p_ts, FALSE); 40 #endif 41 } 42 43 /* 44 * Count the size (in window cells) of the indent in line "lnum". 45 */ 46 int 47 get_indent_lnum(linenr_T lnum) 48 { 49 #ifdef FEAT_VARTABS 50 return get_indent_str_vtab(ml_get(lnum), (int)curbuf->b_p_ts, 51 curbuf->b_p_vts_array, FALSE); 52 #else 53 return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts, FALSE); 54 #endif 55 } 56 57 #if defined(FEAT_FOLDING) || defined(PROTO) 58 /* 59 * Count the size (in window cells) of the indent in line "lnum" of buffer 60 * "buf". 61 */ 62 int 63 get_indent_buf(buf_T *buf, linenr_T lnum) 64 { 65 #ifdef FEAT_VARTABS 66 return get_indent_str_vtab(ml_get_buf(buf, lnum, FALSE), 67 (int)curbuf->b_p_ts, buf->b_p_vts_array, FALSE); 68 #else 69 return get_indent_str(ml_get_buf(buf, lnum, FALSE), (int)buf->b_p_ts, FALSE); 70 #endif 71 } 72 #endif 73 74 /* 75 * count the size (in window cells) of the indent in line "ptr", with 76 * 'tabstop' at "ts" 77 */ 78 int 79 get_indent_str( 80 char_u *ptr, 81 int ts, 82 int list) /* if TRUE, count only screen size for tabs */ 83 { 84 int count = 0; 85 86 for ( ; *ptr; ++ptr) 87 { 88 if (*ptr == TAB) 89 { 90 if (!list || lcs_tab1) /* count a tab for what it is worth */ 91 count += ts - (count % ts); 92 else 93 /* In list mode, when tab is not set, count screen char width 94 * for Tab, displays: ^I */ 95 count += ptr2cells(ptr); 96 } 97 else if (*ptr == ' ') 98 ++count; /* count a space for one */ 99 else 100 break; 101 } 102 return count; 103 } 104 105 #ifdef FEAT_VARTABS 106 /* 107 * Count the size (in window cells) of the indent in line "ptr", using 108 * variable tabstops. 109 * if "list" is TRUE, count only screen size for tabs. 110 */ 111 int 112 get_indent_str_vtab(char_u *ptr, int ts, int *vts, int list) 113 { 114 int count = 0; 115 116 for ( ; *ptr; ++ptr) 117 { 118 if (*ptr == TAB) /* count a tab for what it is worth */ 119 { 120 if (!list || lcs_tab1) 121 count += tabstop_padding(count, ts, vts); 122 else 123 /* In list mode, when tab is not set, count screen char width 124 * for Tab, displays: ^I */ 125 count += ptr2cells(ptr); 126 } 127 else if (*ptr == ' ') 128 ++count; /* count a space for one */ 129 else 130 break; 131 } 132 return count; 133 } 134 #endif 135 136 /* 137 * Set the indent of the current line. 138 * Leaves the cursor on the first non-blank in the line. 139 * Caller must take care of undo. 140 * "flags": 141 * SIN_CHANGED: call changed_bytes() if the line was changed. 142 * SIN_INSERT: insert the indent in front of the line. 143 * SIN_UNDO: save line for undo before changing it. 144 * Returns TRUE if the line was changed. 145 */ 146 int 147 set_indent( 148 int size, /* measured in spaces */ 149 int flags) 150 { 151 char_u *p; 152 char_u *newline; 153 char_u *oldline; 154 char_u *s; 155 int todo; 156 int ind_len; /* measured in characters */ 157 int line_len; 158 int doit = FALSE; 159 int ind_done = 0; /* measured in spaces */ 160 #ifdef FEAT_VARTABS 161 int ind_col = 0; 162 #endif 163 int tab_pad; 164 int retval = FALSE; 165 int orig_char_len = -1; /* number of initial whitespace chars when 166 'et' and 'pi' are both set */ 167 168 /* 169 * First check if there is anything to do and compute the number of 170 * characters needed for the indent. 171 */ 172 todo = size; 173 ind_len = 0; 174 p = oldline = ml_get_curline(); 175 176 /* Calculate the buffer size for the new indent, and check to see if it 177 * isn't already set */ 178 179 /* if 'expandtab' isn't set: use TABs; if both 'expandtab' and 180 * 'preserveindent' are set count the number of characters at the 181 * beginning of the line to be copied */ 182 if (!curbuf->b_p_et || (!(flags & SIN_INSERT) && curbuf->b_p_pi)) 183 { 184 /* If 'preserveindent' is set then reuse as much as possible of 185 * the existing indent structure for the new indent */ 186 if (!(flags & SIN_INSERT) && curbuf->b_p_pi) 187 { 188 ind_done = 0; 189 190 /* count as many characters as we can use */ 191 while (todo > 0 && VIM_ISWHITE(*p)) 192 { 193 if (*p == TAB) 194 { 195 #ifdef FEAT_VARTABS 196 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, 197 curbuf->b_p_vts_array); 198 #else 199 tab_pad = (int)curbuf->b_p_ts 200 - (ind_done % (int)curbuf->b_p_ts); 201 #endif 202 /* stop if this tab will overshoot the target */ 203 if (todo < tab_pad) 204 break; 205 todo -= tab_pad; 206 ++ind_len; 207 ind_done += tab_pad; 208 } 209 else 210 { 211 --todo; 212 ++ind_len; 213 ++ind_done; 214 } 215 ++p; 216 } 217 218 #ifdef FEAT_VARTABS 219 /* These diverge from this point. */ 220 ind_col = ind_done; 221 #endif 222 /* Set initial number of whitespace chars to copy if we are 223 * preserving indent but expandtab is set */ 224 if (curbuf->b_p_et) 225 orig_char_len = ind_len; 226 227 /* Fill to next tabstop with a tab, if possible */ 228 #ifdef FEAT_VARTABS 229 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, 230 curbuf->b_p_vts_array); 231 #else 232 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); 233 #endif 234 if (todo >= tab_pad && orig_char_len == -1) 235 { 236 doit = TRUE; 237 todo -= tab_pad; 238 ++ind_len; 239 /* ind_done += tab_pad; */ 240 #ifdef FEAT_VARTABS 241 ind_col += tab_pad; 242 #endif 243 } 244 } 245 246 /* count tabs required for indent */ 247 #ifdef FEAT_VARTABS 248 for (;;) 249 { 250 tab_pad = tabstop_padding(ind_col, curbuf->b_p_ts, 251 curbuf->b_p_vts_array); 252 if (todo < tab_pad) 253 break; 254 if (*p != TAB) 255 doit = TRUE; 256 else 257 ++p; 258 todo -= tab_pad; 259 ++ind_len; 260 ind_col += tab_pad; 261 } 262 #else 263 while (todo >= (int)curbuf->b_p_ts) 264 { 265 if (*p != TAB) 266 doit = TRUE; 267 else 268 ++p; 269 todo -= (int)curbuf->b_p_ts; 270 ++ind_len; 271 /* ind_done += (int)curbuf->b_p_ts; */ 272 } 273 #endif 274 } 275 /* count spaces required for indent */ 276 while (todo > 0) 277 { 278 if (*p != ' ') 279 doit = TRUE; 280 else 281 ++p; 282 --todo; 283 ++ind_len; 284 /* ++ind_done; */ 285 } 286 287 /* Return if the indent is OK already. */ 288 if (!doit && !VIM_ISWHITE(*p) && !(flags & SIN_INSERT)) 289 return FALSE; 290 291 /* Allocate memory for the new line. */ 292 if (flags & SIN_INSERT) 293 p = oldline; 294 else 295 p = skipwhite(p); 296 line_len = (int)STRLEN(p) + 1; 297 298 /* If 'preserveindent' and 'expandtab' are both set keep the original 299 * characters and allocate accordingly. We will fill the rest with spaces 300 * after the if (!curbuf->b_p_et) below. */ 301 if (orig_char_len != -1) 302 { 303 newline = alloc(orig_char_len + size - ind_done + line_len); 304 if (newline == NULL) 305 return FALSE; 306 todo = size - ind_done; 307 ind_len = orig_char_len + todo; /* Set total length of indent in 308 * characters, which may have been 309 * undercounted until now */ 310 p = oldline; 311 s = newline; 312 while (orig_char_len > 0) 313 { 314 *s++ = *p++; 315 orig_char_len--; 316 } 317 318 /* Skip over any additional white space (useful when newindent is less 319 * than old) */ 320 while (VIM_ISWHITE(*p)) 321 ++p; 322 323 } 324 else 325 { 326 todo = size; 327 newline = alloc(ind_len + line_len); 328 if (newline == NULL) 329 return FALSE; 330 s = newline; 331 } 332 333 /* Put the characters in the new line. */ 334 /* if 'expandtab' isn't set: use TABs */ 335 if (!curbuf->b_p_et) 336 { 337 /* If 'preserveindent' is set then reuse as much as possible of 338 * the existing indent structure for the new indent */ 339 if (!(flags & SIN_INSERT) && curbuf->b_p_pi) 340 { 341 p = oldline; 342 ind_done = 0; 343 344 while (todo > 0 && VIM_ISWHITE(*p)) 345 { 346 if (*p == TAB) 347 { 348 #ifdef FEAT_VARTABS 349 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, 350 curbuf->b_p_vts_array); 351 #else 352 tab_pad = (int)curbuf->b_p_ts 353 - (ind_done % (int)curbuf->b_p_ts); 354 #endif 355 /* stop if this tab will overshoot the target */ 356 if (todo < tab_pad) 357 break; 358 todo -= tab_pad; 359 ind_done += tab_pad; 360 } 361 else 362 { 363 --todo; 364 ++ind_done; 365 } 366 *s++ = *p++; 367 } 368 369 /* Fill to next tabstop with a tab, if possible */ 370 #ifdef FEAT_VARTABS 371 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, 372 curbuf->b_p_vts_array); 373 #else 374 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); 375 #endif 376 if (todo >= tab_pad) 377 { 378 *s++ = TAB; 379 todo -= tab_pad; 380 #ifdef FEAT_VARTABS 381 ind_done += tab_pad; 382 #endif 383 } 384 385 p = skipwhite(p); 386 } 387 388 #ifdef FEAT_VARTABS 389 for (;;) 390 { 391 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, 392 curbuf->b_p_vts_array); 393 if (todo < tab_pad) 394 break; 395 *s++ = TAB; 396 todo -= tab_pad; 397 ind_done += tab_pad; 398 } 399 #else 400 while (todo >= (int)curbuf->b_p_ts) 401 { 402 *s++ = TAB; 403 todo -= (int)curbuf->b_p_ts; 404 } 405 #endif 406 } 407 while (todo > 0) 408 { 409 *s++ = ' '; 410 --todo; 411 } 412 mch_memmove(s, p, (size_t)line_len); 413 414 // Replace the line (unless undo fails). 415 if (!(flags & SIN_UNDO) || u_savesub(curwin->w_cursor.lnum) == OK) 416 { 417 ml_replace(curwin->w_cursor.lnum, newline, FALSE); 418 if (flags & SIN_CHANGED) 419 changed_bytes(curwin->w_cursor.lnum, 0); 420 421 // Correct saved cursor position if it is in this line. 422 if (saved_cursor.lnum == curwin->w_cursor.lnum) 423 { 424 if (saved_cursor.col >= (colnr_T)(p - oldline)) 425 // cursor was after the indent, adjust for the number of 426 // bytes added/removed 427 saved_cursor.col += ind_len - (colnr_T)(p - oldline); 428 else if (saved_cursor.col >= (colnr_T)(s - newline)) 429 // cursor was in the indent, and is now after it, put it back 430 // at the start of the indent (replacing spaces with TAB) 431 saved_cursor.col = (colnr_T)(s - newline); 432 } 433 #ifdef FEAT_TEXT_PROP 434 adjust_prop_columns(curwin->w_cursor.lnum, (colnr_T)(p - oldline), 435 ind_len - (colnr_T)(p - oldline)); 436 #endif 437 retval = TRUE; 438 } 439 else 440 vim_free(newline); 441 442 curwin->w_cursor.col = ind_len; 443 return retval; 444 } 445 446 /* 447 * Copy the indent from ptr to the current line (and fill to size) 448 * Leaves the cursor on the first non-blank in the line. 449 * Returns TRUE if the line was changed. 450 */ 451 static int 452 copy_indent(int size, char_u *src) 453 { 454 char_u *p = NULL; 455 char_u *line = NULL; 456 char_u *s; 457 int todo; 458 int ind_len; 459 int line_len = 0; 460 int tab_pad; 461 int ind_done; 462 int round; 463 #ifdef FEAT_VARTABS 464 int ind_col; 465 #endif 466 467 /* Round 1: compute the number of characters needed for the indent 468 * Round 2: copy the characters. */ 469 for (round = 1; round <= 2; ++round) 470 { 471 todo = size; 472 ind_len = 0; 473 ind_done = 0; 474 #ifdef FEAT_VARTABS 475 ind_col = 0; 476 #endif 477 s = src; 478 479 /* Count/copy the usable portion of the source line */ 480 while (todo > 0 && VIM_ISWHITE(*s)) 481 { 482 if (*s == TAB) 483 { 484 #ifdef FEAT_VARTABS 485 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, 486 curbuf->b_p_vts_array); 487 #else 488 tab_pad = (int)curbuf->b_p_ts 489 - (ind_done % (int)curbuf->b_p_ts); 490 #endif 491 /* Stop if this tab will overshoot the target */ 492 if (todo < tab_pad) 493 break; 494 todo -= tab_pad; 495 ind_done += tab_pad; 496 #ifdef FEAT_VARTABS 497 ind_col += tab_pad; 498 #endif 499 } 500 else 501 { 502 --todo; 503 ++ind_done; 504 #ifdef FEAT_VARTABS 505 ++ind_col; 506 #endif 507 } 508 ++ind_len; 509 if (p != NULL) 510 *p++ = *s; 511 ++s; 512 } 513 514 /* Fill to next tabstop with a tab, if possible */ 515 #ifdef FEAT_VARTABS 516 tab_pad = tabstop_padding(ind_done, curbuf->b_p_ts, 517 curbuf->b_p_vts_array); 518 #else 519 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); 520 #endif 521 if (todo >= tab_pad && !curbuf->b_p_et) 522 { 523 todo -= tab_pad; 524 ++ind_len; 525 #ifdef FEAT_VARTABS 526 ind_col += tab_pad; 527 #endif 528 if (p != NULL) 529 *p++ = TAB; 530 } 531 532 /* Add tabs required for indent */ 533 if (!curbuf->b_p_et) 534 { 535 #ifdef FEAT_VARTABS 536 for (;;) 537 { 538 tab_pad = tabstop_padding(ind_col, curbuf->b_p_ts, 539 curbuf->b_p_vts_array); 540 if (todo < tab_pad) 541 break; 542 todo -= tab_pad; 543 ++ind_len; 544 ind_col += tab_pad; 545 if (p != NULL) 546 *p++ = TAB; 547 } 548 #else 549 while (todo >= (int)curbuf->b_p_ts) 550 { 551 todo -= (int)curbuf->b_p_ts; 552 ++ind_len; 553 if (p != NULL) 554 *p++ = TAB; 555 } 556 #endif 557 } 558 559 /* Count/add spaces required for indent */ 560 while (todo > 0) 561 { 562 --todo; 563 ++ind_len; 564 if (p != NULL) 565 *p++ = ' '; 566 } 567 568 if (p == NULL) 569 { 570 /* Allocate memory for the result: the copied indent, new indent 571 * and the rest of the line. */ 572 line_len = (int)STRLEN(ml_get_curline()) + 1; 573 line = alloc(ind_len + line_len); 574 if (line == NULL) 575 return FALSE; 576 p = line; 577 } 578 } 579 580 /* Append the original line */ 581 mch_memmove(p, ml_get_curline(), (size_t)line_len); 582 583 /* Replace the line */ 584 ml_replace(curwin->w_cursor.lnum, line, FALSE); 585 586 /* Put the cursor after the indent. */ 587 curwin->w_cursor.col = ind_len; 588 return TRUE; 589 } 590 591 /* 592 * Return the indent of the current line after a number. Return -1 if no 593 * number was found. Used for 'n' in 'formatoptions': numbered list. 594 * Since a pattern is used it can actually handle more than numbers. 595 */ 596 int 597 get_number_indent(linenr_T lnum) 598 { 599 colnr_T col; 600 pos_T pos; 601 602 regmatch_T regmatch; 603 int lead_len = 0; /* length of comment leader */ 604 605 if (lnum > curbuf->b_ml.ml_line_count) 606 return -1; 607 pos.lnum = 0; 608 609 #ifdef FEAT_COMMENTS 610 /* In format_lines() (i.e. not insert mode), fo+=q is needed too... */ 611 if ((State & INSERT) || has_format_option(FO_Q_COMS)) 612 lead_len = get_leader_len(ml_get(lnum), NULL, FALSE, TRUE); 613 #endif 614 regmatch.regprog = vim_regcomp(curbuf->b_p_flp, RE_MAGIC); 615 if (regmatch.regprog != NULL) 616 { 617 regmatch.rm_ic = FALSE; 618 619 /* vim_regexec() expects a pointer to a line. This lets us 620 * start matching for the flp beyond any comment leader... */ 621 if (vim_regexec(®match, ml_get(lnum) + lead_len, (colnr_T)0)) 622 { 623 pos.lnum = lnum; 624 pos.col = (colnr_T)(*regmatch.endp - ml_get(lnum)); 625 pos.coladd = 0; 626 } 627 vim_regfree(regmatch.regprog); 628 } 629 630 if (pos.lnum == 0 || *ml_get_pos(&pos) == NUL) 631 return -1; 632 getvcol(curwin, &pos, &col, NULL, NULL); 633 return (int)col; 634 } 635 636 #if defined(FEAT_LINEBREAK) || defined(PROTO) 637 /* 638 * Return appropriate space number for breakindent, taking influencing 639 * parameters into account. Window must be specified, since it is not 640 * necessarily always the current one. 641 */ 642 int 643 get_breakindent_win( 644 win_T *wp, 645 char_u *line) /* start of the line */ 646 { 647 static int prev_indent = 0; /* cached indent value */ 648 static long prev_ts = 0L; /* cached tabstop value */ 649 static char_u *prev_line = NULL; /* cached pointer to line */ 650 static varnumber_T prev_tick = 0; /* changedtick of cached value */ 651 #ifdef FEAT_VARTABS 652 static int *prev_vts = NULL; /* cached vartabs values */ 653 #endif 654 int bri = 0; 655 /* window width minus window margin space, i.e. what rests for text */ 656 const int eff_wwidth = wp->w_width 657 - ((wp->w_p_nu || wp->w_p_rnu) 658 && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL) 659 ? number_width(wp) + 1 : 0); 660 661 /* used cached indent, unless pointer or 'tabstop' changed */ 662 if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts 663 || prev_tick != CHANGEDTICK(wp->w_buffer) 664 #ifdef FEAT_VARTABS 665 || prev_vts != wp->w_buffer->b_p_vts_array 666 #endif 667 ) 668 { 669 prev_line = line; 670 prev_ts = wp->w_buffer->b_p_ts; 671 prev_tick = CHANGEDTICK(wp->w_buffer); 672 #ifdef FEAT_VARTABS 673 prev_vts = wp->w_buffer->b_p_vts_array; 674 prev_indent = get_indent_str_vtab(line, 675 (int)wp->w_buffer->b_p_ts, 676 wp->w_buffer->b_p_vts_array, wp->w_p_list); 677 #else 678 prev_indent = get_indent_str(line, 679 (int)wp->w_buffer->b_p_ts, wp->w_p_list); 680 #endif 681 } 682 bri = prev_indent + wp->w_p_brishift; 683 684 /* indent minus the length of the showbreak string */ 685 if (wp->w_p_brisbr) 686 bri -= vim_strsize(p_sbr); 687 688 /* Add offset for number column, if 'n' is in 'cpoptions' */ 689 bri += win_col_off2(wp); 690 691 /* never indent past left window margin */ 692 if (bri < 0) 693 bri = 0; 694 /* always leave at least bri_min characters on the left, 695 * if text width is sufficient */ 696 else if (bri > eff_wwidth - wp->w_p_brimin) 697 bri = (eff_wwidth - wp->w_p_brimin < 0) 698 ? 0 : eff_wwidth - wp->w_p_brimin; 699 700 return bri; 701 } 702 #endif 703 704 705 /* 706 * open_line: Add a new line below or above the current line. 707 * 708 * For VREPLACE mode, we only add a new line when we get to the end of the 709 * file, otherwise we just start replacing the next line. 710 * 711 * Caller must take care of undo. Since VREPLACE may affect any number of 712 * lines however, it may call u_save_cursor() again when starting to change a 713 * new line. 714 * "flags": OPENLINE_DELSPACES delete spaces after cursor 715 * OPENLINE_DO_COM format comments 716 * OPENLINE_KEEPTRAIL keep trailing spaces 717 * OPENLINE_MARKFIX adjust mark positions after the line break 718 * OPENLINE_COM_LIST format comments with list or 2nd line indent 719 * 720 * "second_line_indent": indent for after ^^D in Insert mode or if flag 721 * OPENLINE_COM_LIST 722 * 723 * Return OK for success, FAIL for failure 724 */ 725 int 726 open_line( 727 int dir, /* FORWARD or BACKWARD */ 728 int flags, 729 int second_line_indent) 730 { 731 char_u *saved_line; /* copy of the original line */ 732 char_u *next_line = NULL; /* copy of the next line */ 733 char_u *p_extra = NULL; /* what goes to next line */ 734 int less_cols = 0; /* less columns for mark in new line */ 735 int less_cols_off = 0; /* columns to skip for mark adjust */ 736 pos_T old_cursor; /* old cursor position */ 737 int newcol = 0; /* new cursor column */ 738 int newindent = 0; /* auto-indent of the new line */ 739 int n; 740 int trunc_line = FALSE; /* truncate current line afterwards */ 741 int retval = FAIL; /* return value */ 742 #ifdef FEAT_COMMENTS 743 int extra_len = 0; /* length of p_extra string */ 744 int lead_len; /* length of comment leader */ 745 char_u *lead_flags; /* position in 'comments' for comment leader */ 746 char_u *leader = NULL; /* copy of comment leader */ 747 #endif 748 char_u *allocated = NULL; /* allocated memory */ 749 char_u *p; 750 int saved_char = NUL; /* init for GCC */ 751 #if defined(FEAT_SMARTINDENT) || defined(FEAT_COMMENTS) 752 pos_T *pos; 753 #endif 754 #ifdef FEAT_SMARTINDENT 755 int do_si = (!p_paste && curbuf->b_p_si 756 # ifdef FEAT_CINDENT 757 && !curbuf->b_p_cin 758 # endif 759 # ifdef FEAT_EVAL 760 && *curbuf->b_p_inde == NUL 761 # endif 762 ); 763 int no_si = FALSE; /* reset did_si afterwards */ 764 int first_char = NUL; /* init for GCC */ 765 #endif 766 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) 767 int vreplace_mode; 768 #endif 769 int did_append; /* appended a new line */ 770 int saved_pi = curbuf->b_p_pi; /* copy of preserveindent setting */ 771 772 /* 773 * make a copy of the current line so we can mess with it 774 */ 775 saved_line = vim_strsave(ml_get_curline()); 776 if (saved_line == NULL) /* out of memory! */ 777 return FALSE; 778 779 if (State & VREPLACE_FLAG) 780 { 781 /* 782 * With VREPLACE we make a copy of the next line, which we will be 783 * starting to replace. First make the new line empty and let vim play 784 * with the indenting and comment leader to its heart's content. Then 785 * we grab what it ended up putting on the new line, put back the 786 * original line, and call ins_char() to put each new character onto 787 * the line, replacing what was there before and pushing the right 788 * stuff onto the replace stack. -- webb. 789 */ 790 if (curwin->w_cursor.lnum < orig_line_count) 791 next_line = vim_strsave(ml_get(curwin->w_cursor.lnum + 1)); 792 else 793 next_line = vim_strsave((char_u *)""); 794 if (next_line == NULL) /* out of memory! */ 795 goto theend; 796 797 /* 798 * In VREPLACE mode, a NL replaces the rest of the line, and starts 799 * replacing the next line, so push all of the characters left on the 800 * line onto the replace stack. We'll push any other characters that 801 * might be replaced at the start of the next line (due to autoindent 802 * etc) a bit later. 803 */ 804 replace_push(NUL); /* Call twice because BS over NL expects it */ 805 replace_push(NUL); 806 p = saved_line + curwin->w_cursor.col; 807 while (*p != NUL) 808 { 809 if (has_mbyte) 810 p += replace_push_mb(p); 811 else 812 replace_push(*p++); 813 } 814 saved_line[curwin->w_cursor.col] = NUL; 815 } 816 817 if ((State & INSERT) && !(State & VREPLACE_FLAG)) 818 { 819 p_extra = saved_line + curwin->w_cursor.col; 820 #ifdef FEAT_SMARTINDENT 821 if (do_si) /* need first char after new line break */ 822 { 823 p = skipwhite(p_extra); 824 first_char = *p; 825 } 826 #endif 827 #ifdef FEAT_COMMENTS 828 extra_len = (int)STRLEN(p_extra); 829 #endif 830 saved_char = *p_extra; 831 *p_extra = NUL; 832 } 833 834 u_clearline(); /* cannot do "U" command when adding lines */ 835 #ifdef FEAT_SMARTINDENT 836 did_si = FALSE; 837 #endif 838 ai_col = 0; 839 840 /* 841 * If we just did an auto-indent, then we didn't type anything on 842 * the prior line, and it should be truncated. Do this even if 'ai' is not 843 * set because automatically inserting a comment leader also sets did_ai. 844 */ 845 if (dir == FORWARD && did_ai) 846 trunc_line = TRUE; 847 848 /* 849 * If 'autoindent' and/or 'smartindent' is set, try to figure out what 850 * indent to use for the new line. 851 */ 852 if (curbuf->b_p_ai 853 #ifdef FEAT_SMARTINDENT 854 || do_si 855 #endif 856 ) 857 { 858 /* 859 * count white space on current line 860 */ 861 #ifdef FEAT_VARTABS 862 newindent = get_indent_str_vtab(saved_line, curbuf->b_p_ts, 863 curbuf->b_p_vts_array, FALSE); 864 #else 865 newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts, FALSE); 866 #endif 867 if (newindent == 0 && !(flags & OPENLINE_COM_LIST)) 868 newindent = second_line_indent; /* for ^^D command in insert mode */ 869 870 #ifdef FEAT_SMARTINDENT 871 /* 872 * Do smart indenting. 873 * In insert/replace mode (only when dir == FORWARD) 874 * we may move some text to the next line. If it starts with '{' 875 * don't add an indent. Fixes inserting a NL before '{' in line 876 * "if (condition) {" 877 */ 878 if (!trunc_line && do_si && *saved_line != NUL 879 && (p_extra == NULL || first_char != '{')) 880 { 881 char_u *ptr; 882 char_u last_char; 883 884 old_cursor = curwin->w_cursor; 885 ptr = saved_line; 886 # ifdef FEAT_COMMENTS 887 if (flags & OPENLINE_DO_COM) 888 lead_len = get_leader_len(ptr, NULL, FALSE, TRUE); 889 else 890 lead_len = 0; 891 # endif 892 if (dir == FORWARD) 893 { 894 /* 895 * Skip preprocessor directives, unless they are 896 * recognised as comments. 897 */ 898 if ( 899 # ifdef FEAT_COMMENTS 900 lead_len == 0 && 901 # endif 902 ptr[0] == '#') 903 { 904 while (ptr[0] == '#' && curwin->w_cursor.lnum > 1) 905 ptr = ml_get(--curwin->w_cursor.lnum); 906 newindent = get_indent(); 907 } 908 # ifdef FEAT_COMMENTS 909 if (flags & OPENLINE_DO_COM) 910 lead_len = get_leader_len(ptr, NULL, FALSE, TRUE); 911 else 912 lead_len = 0; 913 if (lead_len > 0) 914 { 915 /* 916 * This case gets the following right: 917 * \* 918 * * A comment (read '\' as '/'). 919 * *\ 920 * #define IN_THE_WAY 921 * This should line up here; 922 */ 923 p = skipwhite(ptr); 924 if (p[0] == '/' && p[1] == '*') 925 p++; 926 if (p[0] == '*') 927 { 928 for (p++; *p; p++) 929 { 930 if (p[0] == '/' && p[-1] == '*') 931 { 932 /* 933 * End of C comment, indent should line up 934 * with the line containing the start of 935 * the comment 936 */ 937 curwin->w_cursor.col = (colnr_T)(p - ptr); 938 if ((pos = findmatch(NULL, NUL)) != NULL) 939 { 940 curwin->w_cursor.lnum = pos->lnum; 941 newindent = get_indent(); 942 } 943 } 944 } 945 } 946 } 947 else /* Not a comment line */ 948 # endif 949 { 950 /* Find last non-blank in line */ 951 p = ptr + STRLEN(ptr) - 1; 952 while (p > ptr && VIM_ISWHITE(*p)) 953 --p; 954 last_char = *p; 955 956 /* 957 * find the character just before the '{' or ';' 958 */ 959 if (last_char == '{' || last_char == ';') 960 { 961 if (p > ptr) 962 --p; 963 while (p > ptr && VIM_ISWHITE(*p)) 964 --p; 965 } 966 /* 967 * Try to catch lines that are split over multiple 968 * lines. eg: 969 * if (condition && 970 * condition) { 971 * Should line up here! 972 * } 973 */ 974 if (*p == ')') 975 { 976 curwin->w_cursor.col = (colnr_T)(p - ptr); 977 if ((pos = findmatch(NULL, '(')) != NULL) 978 { 979 curwin->w_cursor.lnum = pos->lnum; 980 newindent = get_indent(); 981 ptr = ml_get_curline(); 982 } 983 } 984 /* 985 * If last character is '{' do indent, without 986 * checking for "if" and the like. 987 */ 988 if (last_char == '{') 989 { 990 did_si = TRUE; /* do indent */ 991 no_si = TRUE; /* don't delete it when '{' typed */ 992 } 993 /* 994 * Look for "if" and the like, use 'cinwords'. 995 * Don't do this if the previous line ended in ';' or 996 * '}'. 997 */ 998 else if (last_char != ';' && last_char != '}' 999 && cin_is_cinword(ptr)) 1000 did_si = TRUE; 1001 } 1002 } 1003 else /* dir == BACKWARD */ 1004 { 1005 /* 1006 * Skip preprocessor directives, unless they are 1007 * recognised as comments. 1008 */ 1009 if ( 1010 # ifdef FEAT_COMMENTS 1011 lead_len == 0 && 1012 # endif 1013 ptr[0] == '#') 1014 { 1015 int was_backslashed = FALSE; 1016 1017 while ((ptr[0] == '#' || was_backslashed) && 1018 curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) 1019 { 1020 if (*ptr && ptr[STRLEN(ptr) - 1] == '\\') 1021 was_backslashed = TRUE; 1022 else 1023 was_backslashed = FALSE; 1024 ptr = ml_get(++curwin->w_cursor.lnum); 1025 } 1026 if (was_backslashed) 1027 newindent = 0; /* Got to end of file */ 1028 else 1029 newindent = get_indent(); 1030 } 1031 p = skipwhite(ptr); 1032 if (*p == '}') /* if line starts with '}': do indent */ 1033 did_si = TRUE; 1034 else /* can delete indent when '{' typed */ 1035 can_si_back = TRUE; 1036 } 1037 curwin->w_cursor = old_cursor; 1038 } 1039 if (do_si) 1040 can_si = TRUE; 1041 #endif /* FEAT_SMARTINDENT */ 1042 1043 did_ai = TRUE; 1044 } 1045 1046 #ifdef FEAT_COMMENTS 1047 /* 1048 * Find out if the current line starts with a comment leader. 1049 * This may then be inserted in front of the new line. 1050 */ 1051 end_comment_pending = NUL; 1052 if (flags & OPENLINE_DO_COM) 1053 lead_len = get_leader_len(saved_line, &lead_flags, dir == BACKWARD, TRUE); 1054 else 1055 lead_len = 0; 1056 if (lead_len > 0) 1057 { 1058 char_u *lead_repl = NULL; /* replaces comment leader */ 1059 int lead_repl_len = 0; /* length of *lead_repl */ 1060 char_u lead_middle[COM_MAX_LEN]; /* middle-comment string */ 1061 char_u lead_end[COM_MAX_LEN]; /* end-comment string */ 1062 char_u *comment_end = NULL; /* where lead_end has been found */ 1063 int extra_space = FALSE; /* append extra space */ 1064 int current_flag; 1065 int require_blank = FALSE; /* requires blank after middle */ 1066 char_u *p2; 1067 1068 /* 1069 * If the comment leader has the start, middle or end flag, it may not 1070 * be used or may be replaced with the middle leader. 1071 */ 1072 for (p = lead_flags; *p && *p != ':'; ++p) 1073 { 1074 if (*p == COM_BLANK) 1075 { 1076 require_blank = TRUE; 1077 continue; 1078 } 1079 if (*p == COM_START || *p == COM_MIDDLE) 1080 { 1081 current_flag = *p; 1082 if (*p == COM_START) 1083 { 1084 /* 1085 * Doing "O" on a start of comment does not insert leader. 1086 */ 1087 if (dir == BACKWARD) 1088 { 1089 lead_len = 0; 1090 break; 1091 } 1092 1093 /* find start of middle part */ 1094 (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ","); 1095 require_blank = FALSE; 1096 } 1097 1098 /* 1099 * Isolate the strings of the middle and end leader. 1100 */ 1101 while (*p && p[-1] != ':') /* find end of middle flags */ 1102 { 1103 if (*p == COM_BLANK) 1104 require_blank = TRUE; 1105 ++p; 1106 } 1107 (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ","); 1108 1109 while (*p && p[-1] != ':') /* find end of end flags */ 1110 { 1111 /* Check whether we allow automatic ending of comments */ 1112 if (*p == COM_AUTO_END) 1113 end_comment_pending = -1; /* means we want to set it */ 1114 ++p; 1115 } 1116 n = copy_option_part(&p, lead_end, COM_MAX_LEN, ","); 1117 1118 if (end_comment_pending == -1) /* we can set it now */ 1119 end_comment_pending = lead_end[n - 1]; 1120 1121 /* 1122 * If the end of the comment is in the same line, don't use 1123 * the comment leader. 1124 */ 1125 if (dir == FORWARD) 1126 { 1127 for (p = saved_line + lead_len; *p; ++p) 1128 if (STRNCMP(p, lead_end, n) == 0) 1129 { 1130 comment_end = p; 1131 lead_len = 0; 1132 break; 1133 } 1134 } 1135 1136 /* 1137 * Doing "o" on a start of comment inserts the middle leader. 1138 */ 1139 if (lead_len > 0) 1140 { 1141 if (current_flag == COM_START) 1142 { 1143 lead_repl = lead_middle; 1144 lead_repl_len = (int)STRLEN(lead_middle); 1145 } 1146 1147 /* 1148 * If we have hit RETURN immediately after the start 1149 * comment leader, then put a space after the middle 1150 * comment leader on the next line. 1151 */ 1152 if (!VIM_ISWHITE(saved_line[lead_len - 1]) 1153 && ((p_extra != NULL 1154 && (int)curwin->w_cursor.col == lead_len) 1155 || (p_extra == NULL 1156 && saved_line[lead_len] == NUL) 1157 || require_blank)) 1158 extra_space = TRUE; 1159 } 1160 break; 1161 } 1162 if (*p == COM_END) 1163 { 1164 /* 1165 * Doing "o" on the end of a comment does not insert leader. 1166 * Remember where the end is, might want to use it to find the 1167 * start (for C-comments). 1168 */ 1169 if (dir == FORWARD) 1170 { 1171 comment_end = skipwhite(saved_line); 1172 lead_len = 0; 1173 break; 1174 } 1175 1176 /* 1177 * Doing "O" on the end of a comment inserts the middle leader. 1178 * Find the string for the middle leader, searching backwards. 1179 */ 1180 while (p > curbuf->b_p_com && *p != ',') 1181 --p; 1182 for (lead_repl = p; lead_repl > curbuf->b_p_com 1183 && lead_repl[-1] != ':'; --lead_repl) 1184 ; 1185 lead_repl_len = (int)(p - lead_repl); 1186 1187 /* We can probably always add an extra space when doing "O" on 1188 * the comment-end */ 1189 extra_space = TRUE; 1190 1191 /* Check whether we allow automatic ending of comments */ 1192 for (p2 = p; *p2 && *p2 != ':'; p2++) 1193 { 1194 if (*p2 == COM_AUTO_END) 1195 end_comment_pending = -1; /* means we want to set it */ 1196 } 1197 if (end_comment_pending == -1) 1198 { 1199 /* Find last character in end-comment string */ 1200 while (*p2 && *p2 != ',') 1201 p2++; 1202 end_comment_pending = p2[-1]; 1203 } 1204 break; 1205 } 1206 if (*p == COM_FIRST) 1207 { 1208 /* 1209 * Comment leader for first line only: Don't repeat leader 1210 * when using "O", blank out leader when using "o". 1211 */ 1212 if (dir == BACKWARD) 1213 lead_len = 0; 1214 else 1215 { 1216 lead_repl = (char_u *)""; 1217 lead_repl_len = 0; 1218 } 1219 break; 1220 } 1221 } 1222 if (lead_len) 1223 { 1224 /* allocate buffer (may concatenate p_extra later) */ 1225 leader = alloc(lead_len + lead_repl_len + extra_space + extra_len 1226 + (second_line_indent > 0 ? second_line_indent : 0) + 1); 1227 allocated = leader; /* remember to free it later */ 1228 1229 if (leader == NULL) 1230 lead_len = 0; 1231 else 1232 { 1233 vim_strncpy(leader, saved_line, lead_len); 1234 1235 /* 1236 * Replace leader with lead_repl, right or left adjusted 1237 */ 1238 if (lead_repl != NULL) 1239 { 1240 int c = 0; 1241 int off = 0; 1242 1243 for (p = lead_flags; *p != NUL && *p != ':'; ) 1244 { 1245 if (*p == COM_RIGHT || *p == COM_LEFT) 1246 c = *p++; 1247 else if (VIM_ISDIGIT(*p) || *p == '-') 1248 off = getdigits(&p); 1249 else 1250 ++p; 1251 } 1252 if (c == COM_RIGHT) /* right adjusted leader */ 1253 { 1254 /* find last non-white in the leader to line up with */ 1255 for (p = leader + lead_len - 1; p > leader 1256 && VIM_ISWHITE(*p); --p) 1257 ; 1258 ++p; 1259 1260 /* Compute the length of the replaced characters in 1261 * screen characters, not bytes. */ 1262 { 1263 int repl_size = vim_strnsize(lead_repl, 1264 lead_repl_len); 1265 int old_size = 0; 1266 char_u *endp = p; 1267 int l; 1268 1269 while (old_size < repl_size && p > leader) 1270 { 1271 MB_PTR_BACK(leader, p); 1272 old_size += ptr2cells(p); 1273 } 1274 l = lead_repl_len - (int)(endp - p); 1275 if (l != 0) 1276 mch_memmove(endp + l, endp, 1277 (size_t)((leader + lead_len) - endp)); 1278 lead_len += l; 1279 } 1280 mch_memmove(p, lead_repl, (size_t)lead_repl_len); 1281 if (p + lead_repl_len > leader + lead_len) 1282 p[lead_repl_len] = NUL; 1283 1284 /* blank-out any other chars from the old leader. */ 1285 while (--p >= leader) 1286 { 1287 int l = mb_head_off(leader, p); 1288 1289 if (l > 1) 1290 { 1291 p -= l; 1292 if (ptr2cells(p) > 1) 1293 { 1294 p[1] = ' '; 1295 --l; 1296 } 1297 mch_memmove(p + 1, p + l + 1, 1298 (size_t)((leader + lead_len) - (p + l + 1))); 1299 lead_len -= l; 1300 *p = ' '; 1301 } 1302 else if (!VIM_ISWHITE(*p)) 1303 *p = ' '; 1304 } 1305 } 1306 else /* left adjusted leader */ 1307 { 1308 p = skipwhite(leader); 1309 1310 /* Compute the length of the replaced characters in 1311 * screen characters, not bytes. Move the part that is 1312 * not to be overwritten. */ 1313 { 1314 int repl_size = vim_strnsize(lead_repl, 1315 lead_repl_len); 1316 int i; 1317 int l; 1318 1319 for (i = 0; i < lead_len && p[i] != NUL; i += l) 1320 { 1321 l = (*mb_ptr2len)(p + i); 1322 if (vim_strnsize(p, i + l) > repl_size) 1323 break; 1324 } 1325 if (i != lead_repl_len) 1326 { 1327 mch_memmove(p + lead_repl_len, p + i, 1328 (size_t)(lead_len - i - (p - leader))); 1329 lead_len += lead_repl_len - i; 1330 } 1331 } 1332 mch_memmove(p, lead_repl, (size_t)lead_repl_len); 1333 1334 /* Replace any remaining non-white chars in the old 1335 * leader by spaces. Keep Tabs, the indent must 1336 * remain the same. */ 1337 for (p += lead_repl_len; p < leader + lead_len; ++p) 1338 if (!VIM_ISWHITE(*p)) 1339 { 1340 /* Don't put a space before a TAB. */ 1341 if (p + 1 < leader + lead_len && p[1] == TAB) 1342 { 1343 --lead_len; 1344 mch_memmove(p, p + 1, 1345 (leader + lead_len) - p); 1346 } 1347 else 1348 { 1349 int l = (*mb_ptr2len)(p); 1350 1351 if (l > 1) 1352 { 1353 if (ptr2cells(p) > 1) 1354 { 1355 /* Replace a double-wide char with 1356 * two spaces */ 1357 --l; 1358 *p++ = ' '; 1359 } 1360 mch_memmove(p + 1, p + l, 1361 (leader + lead_len) - p); 1362 lead_len -= l - 1; 1363 } 1364 *p = ' '; 1365 } 1366 } 1367 *p = NUL; 1368 } 1369 1370 /* Recompute the indent, it may have changed. */ 1371 if (curbuf->b_p_ai 1372 #ifdef FEAT_SMARTINDENT 1373 || do_si 1374 #endif 1375 ) 1376 #ifdef FEAT_VARTABS 1377 newindent = get_indent_str_vtab(leader, curbuf->b_p_ts, 1378 curbuf->b_p_vts_array, FALSE); 1379 #else 1380 newindent = get_indent_str(leader, 1381 (int)curbuf->b_p_ts, FALSE); 1382 #endif 1383 1384 /* Add the indent offset */ 1385 if (newindent + off < 0) 1386 { 1387 off = -newindent; 1388 newindent = 0; 1389 } 1390 else 1391 newindent += off; 1392 1393 /* Correct trailing spaces for the shift, so that 1394 * alignment remains equal. */ 1395 while (off > 0 && lead_len > 0 1396 && leader[lead_len - 1] == ' ') 1397 { 1398 /* Don't do it when there is a tab before the space */ 1399 if (vim_strchr(skipwhite(leader), '\t') != NULL) 1400 break; 1401 --lead_len; 1402 --off; 1403 } 1404 1405 /* If the leader ends in white space, don't add an 1406 * extra space */ 1407 if (lead_len > 0 && VIM_ISWHITE(leader[lead_len - 1])) 1408 extra_space = FALSE; 1409 leader[lead_len] = NUL; 1410 } 1411 1412 if (extra_space) 1413 { 1414 leader[lead_len++] = ' '; 1415 leader[lead_len] = NUL; 1416 } 1417 1418 newcol = lead_len; 1419 1420 /* 1421 * if a new indent will be set below, remove the indent that 1422 * is in the comment leader 1423 */ 1424 if (newindent 1425 #ifdef FEAT_SMARTINDENT 1426 || did_si 1427 #endif 1428 ) 1429 { 1430 while (lead_len && VIM_ISWHITE(*leader)) 1431 { 1432 --lead_len; 1433 --newcol; 1434 ++leader; 1435 } 1436 } 1437 1438 } 1439 #ifdef FEAT_SMARTINDENT 1440 did_si = can_si = FALSE; 1441 #endif 1442 } 1443 else if (comment_end != NULL) 1444 { 1445 /* 1446 * We have finished a comment, so we don't use the leader. 1447 * If this was a C-comment and 'ai' or 'si' is set do a normal 1448 * indent to align with the line containing the start of the 1449 * comment. 1450 */ 1451 if (comment_end[0] == '*' && comment_end[1] == '/' && 1452 (curbuf->b_p_ai 1453 #ifdef FEAT_SMARTINDENT 1454 || do_si 1455 #endif 1456 )) 1457 { 1458 old_cursor = curwin->w_cursor; 1459 curwin->w_cursor.col = (colnr_T)(comment_end - saved_line); 1460 if ((pos = findmatch(NULL, NUL)) != NULL) 1461 { 1462 curwin->w_cursor.lnum = pos->lnum; 1463 newindent = get_indent(); 1464 } 1465 curwin->w_cursor = old_cursor; 1466 } 1467 } 1468 } 1469 #endif 1470 1471 /* (State == INSERT || State == REPLACE), only when dir == FORWARD */ 1472 if (p_extra != NULL) 1473 { 1474 *p_extra = saved_char; /* restore char that NUL replaced */ 1475 1476 /* 1477 * When 'ai' set or "flags" has OPENLINE_DELSPACES, skip to the first 1478 * non-blank. 1479 * 1480 * When in REPLACE mode, put the deleted blanks on the replace stack, 1481 * preceded by a NUL, so they can be put back when a BS is entered. 1482 */ 1483 if (REPLACE_NORMAL(State)) 1484 replace_push(NUL); /* end of extra blanks */ 1485 if (curbuf->b_p_ai || (flags & OPENLINE_DELSPACES)) 1486 { 1487 while ((*p_extra == ' ' || *p_extra == '\t') 1488 && (!enc_utf8 1489 || !utf_iscomposing(utf_ptr2char(p_extra + 1)))) 1490 { 1491 if (REPLACE_NORMAL(State)) 1492 replace_push(*p_extra); 1493 ++p_extra; 1494 ++less_cols_off; 1495 } 1496 } 1497 if (*p_extra != NUL) 1498 did_ai = FALSE; /* append some text, don't truncate now */ 1499 1500 /* columns for marks adjusted for removed columns */ 1501 less_cols = (int)(p_extra - saved_line); 1502 } 1503 1504 if (p_extra == NULL) 1505 p_extra = (char_u *)""; /* append empty line */ 1506 1507 #ifdef FEAT_COMMENTS 1508 /* concatenate leader and p_extra, if there is a leader */ 1509 if (lead_len) 1510 { 1511 if (flags & OPENLINE_COM_LIST && second_line_indent > 0) 1512 { 1513 int i; 1514 int padding = second_line_indent 1515 - (newindent + (int)STRLEN(leader)); 1516 1517 /* Here whitespace is inserted after the comment char. 1518 * Below, set_indent(newindent, SIN_INSERT) will insert the 1519 * whitespace needed before the comment char. */ 1520 for (i = 0; i < padding; i++) 1521 { 1522 STRCAT(leader, " "); 1523 less_cols--; 1524 newcol++; 1525 } 1526 } 1527 STRCAT(leader, p_extra); 1528 p_extra = leader; 1529 did_ai = TRUE; /* So truncating blanks works with comments */ 1530 less_cols -= lead_len; 1531 } 1532 else 1533 end_comment_pending = NUL; /* turns out there was no leader */ 1534 #endif 1535 1536 old_cursor = curwin->w_cursor; 1537 if (dir == BACKWARD) 1538 --curwin->w_cursor.lnum; 1539 if (!(State & VREPLACE_FLAG) || old_cursor.lnum >= orig_line_count) 1540 { 1541 if (ml_append(curwin->w_cursor.lnum, p_extra, (colnr_T)0, FALSE) 1542 == FAIL) 1543 goto theend; 1544 /* Postpone calling changed_lines(), because it would mess up folding 1545 * with markers. 1546 * Skip mark_adjust when adding a line after the last one, there can't 1547 * be marks there. But still needed in diff mode. */ 1548 if (curwin->w_cursor.lnum + 1 < curbuf->b_ml.ml_line_count 1549 #ifdef FEAT_DIFF 1550 || curwin->w_p_diff 1551 #endif 1552 ) 1553 mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L); 1554 did_append = TRUE; 1555 } 1556 else 1557 { 1558 /* 1559 * In VREPLACE mode we are starting to replace the next line. 1560 */ 1561 curwin->w_cursor.lnum++; 1562 if (curwin->w_cursor.lnum >= Insstart.lnum + vr_lines_changed) 1563 { 1564 /* In case we NL to a new line, BS to the previous one, and NL 1565 * again, we don't want to save the new line for undo twice. 1566 */ 1567 (void)u_save_cursor(); /* errors are ignored! */ 1568 vr_lines_changed++; 1569 } 1570 ml_replace(curwin->w_cursor.lnum, p_extra, TRUE); 1571 changed_bytes(curwin->w_cursor.lnum, 0); 1572 curwin->w_cursor.lnum--; 1573 did_append = FALSE; 1574 } 1575 1576 if (newindent 1577 #ifdef FEAT_SMARTINDENT 1578 || did_si 1579 #endif 1580 ) 1581 { 1582 ++curwin->w_cursor.lnum; 1583 #ifdef FEAT_SMARTINDENT 1584 if (did_si) 1585 { 1586 int sw = (int)get_sw_value(curbuf); 1587 1588 if (p_sr) 1589 newindent -= newindent % sw; 1590 newindent += sw; 1591 } 1592 #endif 1593 /* Copy the indent */ 1594 if (curbuf->b_p_ci) 1595 { 1596 (void)copy_indent(newindent, saved_line); 1597 1598 /* 1599 * Set the 'preserveindent' option so that any further screwing 1600 * with the line doesn't entirely destroy our efforts to preserve 1601 * it. It gets restored at the function end. 1602 */ 1603 curbuf->b_p_pi = TRUE; 1604 } 1605 else 1606 (void)set_indent(newindent, SIN_INSERT); 1607 less_cols -= curwin->w_cursor.col; 1608 1609 ai_col = curwin->w_cursor.col; 1610 1611 /* 1612 * In REPLACE mode, for each character in the new indent, there must 1613 * be a NUL on the replace stack, for when it is deleted with BS 1614 */ 1615 if (REPLACE_NORMAL(State)) 1616 for (n = 0; n < (int)curwin->w_cursor.col; ++n) 1617 replace_push(NUL); 1618 newcol += curwin->w_cursor.col; 1619 #ifdef FEAT_SMARTINDENT 1620 if (no_si) 1621 did_si = FALSE; 1622 #endif 1623 } 1624 1625 #ifdef FEAT_COMMENTS 1626 /* 1627 * In REPLACE mode, for each character in the extra leader, there must be 1628 * a NUL on the replace stack, for when it is deleted with BS. 1629 */ 1630 if (REPLACE_NORMAL(State)) 1631 while (lead_len-- > 0) 1632 replace_push(NUL); 1633 #endif 1634 1635 curwin->w_cursor = old_cursor; 1636 1637 if (dir == FORWARD) 1638 { 1639 if (trunc_line || (State & INSERT)) 1640 { 1641 /* truncate current line at cursor */ 1642 saved_line[curwin->w_cursor.col] = NUL; 1643 /* Remove trailing white space, unless OPENLINE_KEEPTRAIL used. */ 1644 if (trunc_line && !(flags & OPENLINE_KEEPTRAIL)) 1645 truncate_spaces(saved_line); 1646 ml_replace(curwin->w_cursor.lnum, saved_line, FALSE); 1647 saved_line = NULL; 1648 if (did_append) 1649 { 1650 changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col, 1651 curwin->w_cursor.lnum + 1, 1L); 1652 did_append = FALSE; 1653 1654 /* Move marks after the line break to the new line. */ 1655 if (flags & OPENLINE_MARKFIX) 1656 mark_col_adjust(curwin->w_cursor.lnum, 1657 curwin->w_cursor.col + less_cols_off, 1658 1L, (long)-less_cols, 0); 1659 } 1660 else 1661 changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); 1662 } 1663 1664 /* 1665 * Put the cursor on the new line. Careful: the scrollup() above may 1666 * have moved w_cursor, we must use old_cursor. 1667 */ 1668 curwin->w_cursor.lnum = old_cursor.lnum + 1; 1669 } 1670 if (did_append) 1671 changed_lines(curwin->w_cursor.lnum, 0, curwin->w_cursor.lnum, 1L); 1672 1673 curwin->w_cursor.col = newcol; 1674 curwin->w_cursor.coladd = 0; 1675 1676 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) 1677 /* 1678 * In VREPLACE mode, we are handling the replace stack ourselves, so stop 1679 * fixthisline() from doing it (via change_indent()) by telling it we're in 1680 * normal INSERT mode. 1681 */ 1682 if (State & VREPLACE_FLAG) 1683 { 1684 vreplace_mode = State; /* So we know to put things right later */ 1685 State = INSERT; 1686 } 1687 else 1688 vreplace_mode = 0; 1689 #endif 1690 #ifdef FEAT_LISP 1691 /* 1692 * May do lisp indenting. 1693 */ 1694 if (!p_paste 1695 # ifdef FEAT_COMMENTS 1696 && leader == NULL 1697 # endif 1698 && curbuf->b_p_lisp 1699 && curbuf->b_p_ai) 1700 { 1701 fixthisline(get_lisp_indent); 1702 ai_col = (colnr_T)getwhitecols_curline(); 1703 } 1704 #endif 1705 #ifdef FEAT_CINDENT 1706 /* 1707 * May do indenting after opening a new line. 1708 */ 1709 if (!p_paste 1710 && (curbuf->b_p_cin 1711 # ifdef FEAT_EVAL 1712 || *curbuf->b_p_inde != NUL 1713 # endif 1714 ) 1715 && in_cinkeys(dir == FORWARD 1716 ? KEY_OPEN_FORW 1717 : KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum))) 1718 { 1719 do_c_expr_indent(); 1720 ai_col = (colnr_T)getwhitecols_curline(); 1721 } 1722 #endif 1723 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) 1724 if (vreplace_mode != 0) 1725 State = vreplace_mode; 1726 #endif 1727 1728 /* 1729 * Finally, VREPLACE gets the stuff on the new line, then puts back the 1730 * original line, and inserts the new stuff char by char, pushing old stuff 1731 * onto the replace stack (via ins_char()). 1732 */ 1733 if (State & VREPLACE_FLAG) 1734 { 1735 /* Put new line in p_extra */ 1736 p_extra = vim_strsave(ml_get_curline()); 1737 if (p_extra == NULL) 1738 goto theend; 1739 1740 /* Put back original line */ 1741 ml_replace(curwin->w_cursor.lnum, next_line, FALSE); 1742 1743 /* Insert new stuff into line again */ 1744 curwin->w_cursor.col = 0; 1745 curwin->w_cursor.coladd = 0; 1746 ins_bytes(p_extra); /* will call changed_bytes() */ 1747 vim_free(p_extra); 1748 next_line = NULL; 1749 } 1750 1751 retval = OK; /* success! */ 1752 theend: 1753 curbuf->b_p_pi = saved_pi; 1754 vim_free(saved_line); 1755 vim_free(next_line); 1756 vim_free(allocated); 1757 return retval; 1758 } 1759 1760 #if defined(FEAT_COMMENTS) || defined(PROTO) 1761 /* 1762 * get_leader_len() returns the length in bytes of the prefix of the given 1763 * string which introduces a comment. If this string is not a comment then 1764 * 0 is returned. 1765 * When "flags" is not NULL, it is set to point to the flags of the recognized 1766 * comment leader. 1767 * "backward" must be true for the "O" command. 1768 * If "include_space" is set, include trailing whitespace while calculating the 1769 * length. 1770 */ 1771 int 1772 get_leader_len( 1773 char_u *line, 1774 char_u **flags, 1775 int backward, 1776 int include_space) 1777 { 1778 int i, j; 1779 int result; 1780 int got_com = FALSE; 1781 int found_one; 1782 char_u part_buf[COM_MAX_LEN]; /* buffer for one option part */ 1783 char_u *string; /* pointer to comment string */ 1784 char_u *list; 1785 int middle_match_len = 0; 1786 char_u *prev_list; 1787 char_u *saved_flags = NULL; 1788 1789 result = i = 0; 1790 while (VIM_ISWHITE(line[i])) /* leading white space is ignored */ 1791 ++i; 1792 1793 /* 1794 * Repeat to match several nested comment strings. 1795 */ 1796 while (line[i] != NUL) 1797 { 1798 /* 1799 * scan through the 'comments' option for a match 1800 */ 1801 found_one = FALSE; 1802 for (list = curbuf->b_p_com; *list; ) 1803 { 1804 /* Get one option part into part_buf[]. Advance "list" to next 1805 * one. Put "string" at start of string. */ 1806 if (!got_com && flags != NULL) 1807 *flags = list; /* remember where flags started */ 1808 prev_list = list; 1809 (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ","); 1810 string = vim_strchr(part_buf, ':'); 1811 if (string == NULL) /* missing ':', ignore this part */ 1812 continue; 1813 *string++ = NUL; /* isolate flags from string */ 1814 1815 /* If we found a middle match previously, use that match when this 1816 * is not a middle or end. */ 1817 if (middle_match_len != 0 1818 && vim_strchr(part_buf, COM_MIDDLE) == NULL 1819 && vim_strchr(part_buf, COM_END) == NULL) 1820 break; 1821 1822 /* When we already found a nested comment, only accept further 1823 * nested comments. */ 1824 if (got_com && vim_strchr(part_buf, COM_NEST) == NULL) 1825 continue; 1826 1827 /* When 'O' flag present and using "O" command skip this one. */ 1828 if (backward && vim_strchr(part_buf, COM_NOBACK) != NULL) 1829 continue; 1830 1831 /* Line contents and string must match. 1832 * When string starts with white space, must have some white space 1833 * (but the amount does not need to match, there might be a mix of 1834 * TABs and spaces). */ 1835 if (VIM_ISWHITE(string[0])) 1836 { 1837 if (i == 0 || !VIM_ISWHITE(line[i - 1])) 1838 continue; /* missing white space */ 1839 while (VIM_ISWHITE(string[0])) 1840 ++string; 1841 } 1842 for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j) 1843 ; 1844 if (string[j] != NUL) 1845 continue; /* string doesn't match */ 1846 1847 /* When 'b' flag used, there must be white space or an 1848 * end-of-line after the string in the line. */ 1849 if (vim_strchr(part_buf, COM_BLANK) != NULL 1850 && !VIM_ISWHITE(line[i + j]) && line[i + j] != NUL) 1851 continue; 1852 1853 /* We have found a match, stop searching unless this is a middle 1854 * comment. The middle comment can be a substring of the end 1855 * comment in which case it's better to return the length of the 1856 * end comment and its flags. Thus we keep searching with middle 1857 * and end matches and use an end match if it matches better. */ 1858 if (vim_strchr(part_buf, COM_MIDDLE) != NULL) 1859 { 1860 if (middle_match_len == 0) 1861 { 1862 middle_match_len = j; 1863 saved_flags = prev_list; 1864 } 1865 continue; 1866 } 1867 if (middle_match_len != 0 && j > middle_match_len) 1868 /* Use this match instead of the middle match, since it's a 1869 * longer thus better match. */ 1870 middle_match_len = 0; 1871 1872 if (middle_match_len == 0) 1873 i += j; 1874 found_one = TRUE; 1875 break; 1876 } 1877 1878 if (middle_match_len != 0) 1879 { 1880 /* Use the previously found middle match after failing to find a 1881 * match with an end. */ 1882 if (!got_com && flags != NULL) 1883 *flags = saved_flags; 1884 i += middle_match_len; 1885 found_one = TRUE; 1886 } 1887 1888 /* No match found, stop scanning. */ 1889 if (!found_one) 1890 break; 1891 1892 result = i; 1893 1894 /* Include any trailing white space. */ 1895 while (VIM_ISWHITE(line[i])) 1896 ++i; 1897 1898 if (include_space) 1899 result = i; 1900 1901 /* If this comment doesn't nest, stop here. */ 1902 got_com = TRUE; 1903 if (vim_strchr(part_buf, COM_NEST) == NULL) 1904 break; 1905 } 1906 return result; 1907 } 1908 1909 /* 1910 * Return the offset at which the last comment in line starts. If there is no 1911 * comment in the whole line, -1 is returned. 1912 * 1913 * When "flags" is not null, it is set to point to the flags describing the 1914 * recognized comment leader. 1915 */ 1916 int 1917 get_last_leader_offset(char_u *line, char_u **flags) 1918 { 1919 int result = -1; 1920 int i, j; 1921 int lower_check_bound = 0; 1922 char_u *string; 1923 char_u *com_leader; 1924 char_u *com_flags; 1925 char_u *list; 1926 int found_one; 1927 char_u part_buf[COM_MAX_LEN]; /* buffer for one option part */ 1928 1929 /* 1930 * Repeat to match several nested comment strings. 1931 */ 1932 i = (int)STRLEN(line); 1933 while (--i >= lower_check_bound) 1934 { 1935 /* 1936 * scan through the 'comments' option for a match 1937 */ 1938 found_one = FALSE; 1939 for (list = curbuf->b_p_com; *list; ) 1940 { 1941 char_u *flags_save = list; 1942 1943 /* 1944 * Get one option part into part_buf[]. Advance list to next one. 1945 * put string at start of string. 1946 */ 1947 (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ","); 1948 string = vim_strchr(part_buf, ':'); 1949 if (string == NULL) /* If everything is fine, this cannot actually 1950 * happen. */ 1951 { 1952 continue; 1953 } 1954 *string++ = NUL; /* Isolate flags from string. */ 1955 com_leader = string; 1956 1957 /* 1958 * Line contents and string must match. 1959 * When string starts with white space, must have some white space 1960 * (but the amount does not need to match, there might be a mix of 1961 * TABs and spaces). 1962 */ 1963 if (VIM_ISWHITE(string[0])) 1964 { 1965 if (i == 0 || !VIM_ISWHITE(line[i - 1])) 1966 continue; 1967 while (VIM_ISWHITE(*string)) 1968 ++string; 1969 } 1970 for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j) 1971 /* do nothing */; 1972 if (string[j] != NUL) 1973 continue; 1974 1975 /* 1976 * When 'b' flag used, there must be white space or an 1977 * end-of-line after the string in the line. 1978 */ 1979 if (vim_strchr(part_buf, COM_BLANK) != NULL 1980 && !VIM_ISWHITE(line[i + j]) && line[i + j] != NUL) 1981 continue; 1982 1983 if (vim_strchr(part_buf, COM_MIDDLE) != NULL) 1984 { 1985 // For a middlepart comment, only consider it to match if 1986 // everything before the current position in the line is 1987 // whitespace. Otherwise we would think we are inside a 1988 // comment if the middle part appears somewhere in the middle 1989 // of the line. E.g. for C the "*" appears often. 1990 for (j = 0; VIM_ISWHITE(line[j]) && j <= i; j++) 1991 ; 1992 if (j < i) 1993 continue; 1994 } 1995 1996 /* 1997 * We have found a match, stop searching. 1998 */ 1999 found_one = TRUE; 2000 2001 if (flags) 2002 *flags = flags_save; 2003 com_flags = flags_save; 2004 2005 break; 2006 } 2007 2008 if (found_one) 2009 { 2010 char_u part_buf2[COM_MAX_LEN]; /* buffer for one option part */ 2011 int len1, len2, off; 2012 2013 result = i; 2014 /* 2015 * If this comment nests, continue searching. 2016 */ 2017 if (vim_strchr(part_buf, COM_NEST) != NULL) 2018 continue; 2019 2020 lower_check_bound = i; 2021 2022 /* Let's verify whether the comment leader found is a substring 2023 * of other comment leaders. If it is, let's adjust the 2024 * lower_check_bound so that we make sure that we have determined 2025 * the comment leader correctly. 2026 */ 2027 2028 while (VIM_ISWHITE(*com_leader)) 2029 ++com_leader; 2030 len1 = (int)STRLEN(com_leader); 2031 2032 for (list = curbuf->b_p_com; *list; ) 2033 { 2034 char_u *flags_save = list; 2035 2036 (void)copy_option_part(&list, part_buf2, COM_MAX_LEN, ","); 2037 if (flags_save == com_flags) 2038 continue; 2039 string = vim_strchr(part_buf2, ':'); 2040 ++string; 2041 while (VIM_ISWHITE(*string)) 2042 ++string; 2043 len2 = (int)STRLEN(string); 2044 if (len2 == 0) 2045 continue; 2046 2047 /* Now we have to verify whether string ends with a substring 2048 * beginning the com_leader. */ 2049 for (off = (len2 > i ? i : len2); off > 0 && off + len1 > len2;) 2050 { 2051 --off; 2052 if (!STRNCMP(string + off, com_leader, len2 - off)) 2053 { 2054 if (i - off < lower_check_bound) 2055 lower_check_bound = i - off; 2056 } 2057 } 2058 } 2059 } 2060 } 2061 return result; 2062 } 2063 #endif 2064 2065 /* 2066 * Return the number of window lines occupied by buffer line "lnum". 2067 */ 2068 int 2069 plines(linenr_T lnum) 2070 { 2071 return plines_win(curwin, lnum, TRUE); 2072 } 2073 2074 int 2075 plines_win( 2076 win_T *wp, 2077 linenr_T lnum, 2078 int winheight) /* when TRUE limit to window height */ 2079 { 2080 #if defined(FEAT_DIFF) || defined(PROTO) 2081 /* Check for filler lines above this buffer line. When folded the result 2082 * is one line anyway. */ 2083 return plines_win_nofill(wp, lnum, winheight) + diff_check_fill(wp, lnum); 2084 } 2085 2086 int 2087 plines_nofill(linenr_T lnum) 2088 { 2089 return plines_win_nofill(curwin, lnum, TRUE); 2090 } 2091 2092 int 2093 plines_win_nofill( 2094 win_T *wp, 2095 linenr_T lnum, 2096 int winheight) /* when TRUE limit to window height */ 2097 { 2098 #endif 2099 int lines; 2100 2101 if (!wp->w_p_wrap) 2102 return 1; 2103 2104 if (wp->w_width == 0) 2105 return 1; 2106 2107 #ifdef FEAT_FOLDING 2108 /* A folded lines is handled just like an empty line. */ 2109 /* NOTE: Caller must handle lines that are MAYBE folded. */ 2110 if (lineFolded(wp, lnum) == TRUE) 2111 return 1; 2112 #endif 2113 2114 lines = plines_win_nofold(wp, lnum); 2115 if (winheight > 0 && lines > wp->w_height) 2116 return (int)wp->w_height; 2117 return lines; 2118 } 2119 2120 /* 2121 * Return number of window lines physical line "lnum" will occupy in window 2122 * "wp". Does not care about folding, 'wrap' or 'diff'. 2123 */ 2124 int 2125 plines_win_nofold(win_T *wp, linenr_T lnum) 2126 { 2127 char_u *s; 2128 long col; 2129 int width; 2130 2131 s = ml_get_buf(wp->w_buffer, lnum, FALSE); 2132 if (*s == NUL) /* empty line */ 2133 return 1; 2134 col = win_linetabsize(wp, s, (colnr_T)MAXCOL); 2135 2136 /* 2137 * If list mode is on, then the '$' at the end of the line may take up one 2138 * extra column. 2139 */ 2140 if (wp->w_p_list && lcs_eol != NUL) 2141 col += 1; 2142 2143 /* 2144 * Add column offset for 'number', 'relativenumber' and 'foldcolumn'. 2145 */ 2146 width = wp->w_width - win_col_off(wp); 2147 if (width <= 0) 2148 return 32000; 2149 if (col <= width) 2150 return 1; 2151 col -= width; 2152 width += win_col_off2(wp); 2153 return (col + (width - 1)) / width + 1; 2154 } 2155 2156 /* 2157 * Like plines_win(), but only reports the number of physical screen lines 2158 * used from the start of the line to the given column number. 2159 */ 2160 int 2161 plines_win_col(win_T *wp, linenr_T lnum, long column) 2162 { 2163 long col; 2164 char_u *s; 2165 int lines = 0; 2166 int width; 2167 char_u *line; 2168 2169 #ifdef FEAT_DIFF 2170 /* Check for filler lines above this buffer line. When folded the result 2171 * is one line anyway. */ 2172 lines = diff_check_fill(wp, lnum); 2173 #endif 2174 2175 if (!wp->w_p_wrap) 2176 return lines + 1; 2177 2178 if (wp->w_width == 0) 2179 return lines + 1; 2180 2181 line = s = ml_get_buf(wp->w_buffer, lnum, FALSE); 2182 2183 col = 0; 2184 while (*s != NUL && --column >= 0) 2185 { 2186 col += win_lbr_chartabsize(wp, line, s, (colnr_T)col, NULL); 2187 MB_PTR_ADV(s); 2188 } 2189 2190 /* 2191 * If *s is a TAB, and the TAB is not displayed as ^I, and we're not in 2192 * INSERT mode, then col must be adjusted so that it represents the last 2193 * screen position of the TAB. This only fixes an error when the TAB wraps 2194 * from one screen line to the next (when 'columns' is not a multiple of 2195 * 'ts') -- webb. 2196 */ 2197 if (*s == TAB && (State & NORMAL) && (!wp->w_p_list || lcs_tab1)) 2198 col += win_lbr_chartabsize(wp, line, s, (colnr_T)col, NULL) - 1; 2199 2200 /* 2201 * Add column offset for 'number', 'relativenumber', 'foldcolumn', etc. 2202 */ 2203 width = wp->w_width - win_col_off(wp); 2204 if (width <= 0) 2205 return 9999; 2206 2207 lines += 1; 2208 if (col > width) 2209 lines += (col - width) / (width + win_col_off2(wp)) + 1; 2210 return lines; 2211 } 2212 2213 int 2214 plines_m_win(win_T *wp, linenr_T first, linenr_T last) 2215 { 2216 int count = 0; 2217 2218 while (first <= last) 2219 { 2220 #ifdef FEAT_FOLDING 2221 int x; 2222 2223 /* Check if there are any really folded lines, but also included lines 2224 * that are maybe folded. */ 2225 x = foldedCount(wp, first, NULL); 2226 if (x > 0) 2227 { 2228 ++count; /* count 1 for "+-- folded" line */ 2229 first += x; 2230 } 2231 else 2232 #endif 2233 { 2234 #ifdef FEAT_DIFF 2235 if (first == wp->w_topline) 2236 count += plines_win_nofill(wp, first, TRUE) + wp->w_topfill; 2237 else 2238 #endif 2239 count += plines_win(wp, first, TRUE); 2240 ++first; 2241 } 2242 } 2243 return (count); 2244 } 2245 2246 /* 2247 * Insert string "p" at the cursor position. Stops at a NUL byte. 2248 * Handles Replace mode and multi-byte characters. 2249 */ 2250 void 2251 ins_bytes(char_u *p) 2252 { 2253 ins_bytes_len(p, (int)STRLEN(p)); 2254 } 2255 2256 /* 2257 * Insert string "p" with length "len" at the cursor position. 2258 * Handles Replace mode and multi-byte characters. 2259 */ 2260 void 2261 ins_bytes_len(char_u *p, int len) 2262 { 2263 int i; 2264 int n; 2265 2266 if (has_mbyte) 2267 for (i = 0; i < len; i += n) 2268 { 2269 if (enc_utf8) 2270 // avoid reading past p[len] 2271 n = utfc_ptr2len_len(p + i, len - i); 2272 else 2273 n = (*mb_ptr2len)(p + i); 2274 ins_char_bytes(p + i, n); 2275 } 2276 else 2277 for (i = 0; i < len; ++i) 2278 ins_char(p[i]); 2279 } 2280 2281 /* 2282 * Insert or replace a single character at the cursor position. 2283 * When in REPLACE or VREPLACE mode, replace any existing character. 2284 * Caller must have prepared for undo. 2285 * For multi-byte characters we get the whole character, the caller must 2286 * convert bytes to a character. 2287 */ 2288 void 2289 ins_char(int c) 2290 { 2291 char_u buf[MB_MAXBYTES + 1]; 2292 int n = (*mb_char2bytes)(c, buf); 2293 2294 /* When "c" is 0x100, 0x200, etc. we don't want to insert a NUL byte. 2295 * Happens for CTRL-Vu9900. */ 2296 if (buf[0] == 0) 2297 buf[0] = '\n'; 2298 2299 ins_char_bytes(buf, n); 2300 } 2301 2302 void 2303 ins_char_bytes(char_u *buf, int charlen) 2304 { 2305 int c = buf[0]; 2306 int newlen; // nr of bytes inserted 2307 int oldlen; // nr of bytes deleted (0 when not replacing) 2308 char_u *p; 2309 char_u *newp; 2310 char_u *oldp; 2311 int linelen; // length of old line including NUL 2312 colnr_T col; 2313 linenr_T lnum = curwin->w_cursor.lnum; 2314 int i; 2315 2316 /* Break tabs if needed. */ 2317 if (virtual_active() && curwin->w_cursor.coladd > 0) 2318 coladvance_force(getviscol()); 2319 2320 col = curwin->w_cursor.col; 2321 oldp = ml_get(lnum); 2322 linelen = (int)STRLEN(oldp) + 1; 2323 2324 /* The lengths default to the values for when not replacing. */ 2325 oldlen = 0; 2326 newlen = charlen; 2327 2328 if (State & REPLACE_FLAG) 2329 { 2330 if (State & VREPLACE_FLAG) 2331 { 2332 colnr_T new_vcol = 0; /* init for GCC */ 2333 colnr_T vcol; 2334 int old_list; 2335 2336 /* 2337 * Disable 'list' temporarily, unless 'cpo' contains the 'L' flag. 2338 * Returns the old value of list, so when finished, 2339 * curwin->w_p_list should be set back to this. 2340 */ 2341 old_list = curwin->w_p_list; 2342 if (old_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL) 2343 curwin->w_p_list = FALSE; 2344 2345 /* 2346 * In virtual replace mode each character may replace one or more 2347 * characters (zero if it's a TAB). Count the number of bytes to 2348 * be deleted to make room for the new character, counting screen 2349 * cells. May result in adding spaces to fill a gap. 2350 */ 2351 getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL); 2352 new_vcol = vcol + chartabsize(buf, vcol); 2353 while (oldp[col + oldlen] != NUL && vcol < new_vcol) 2354 { 2355 vcol += chartabsize(oldp + col + oldlen, vcol); 2356 /* Don't need to remove a TAB that takes us to the right 2357 * position. */ 2358 if (vcol > new_vcol && oldp[col + oldlen] == TAB) 2359 break; 2360 oldlen += (*mb_ptr2len)(oldp + col + oldlen); 2361 /* Deleted a bit too much, insert spaces. */ 2362 if (vcol > new_vcol) 2363 newlen += vcol - new_vcol; 2364 } 2365 curwin->w_p_list = old_list; 2366 } 2367 else if (oldp[col] != NUL) 2368 { 2369 /* normal replace */ 2370 oldlen = (*mb_ptr2len)(oldp + col); 2371 } 2372 2373 2374 /* Push the replaced bytes onto the replace stack, so that they can be 2375 * put back when BS is used. The bytes of a multi-byte character are 2376 * done the other way around, so that the first byte is popped off 2377 * first (it tells the byte length of the character). */ 2378 replace_push(NUL); 2379 for (i = 0; i < oldlen; ++i) 2380 { 2381 if (has_mbyte) 2382 i += replace_push_mb(oldp + col + i) - 1; 2383 else 2384 replace_push(oldp[col + i]); 2385 } 2386 } 2387 2388 newp = alloc_check((unsigned)(linelen + newlen - oldlen)); 2389 if (newp == NULL) 2390 return; 2391 2392 /* Copy bytes before the cursor. */ 2393 if (col > 0) 2394 mch_memmove(newp, oldp, (size_t)col); 2395 2396 /* Copy bytes after the changed character(s). */ 2397 p = newp + col; 2398 if (linelen > col + oldlen) 2399 mch_memmove(p + newlen, oldp + col + oldlen, 2400 (size_t)(linelen - col - oldlen)); 2401 2402 /* Insert or overwrite the new character. */ 2403 mch_memmove(p, buf, charlen); 2404 i = charlen; 2405 2406 /* Fill with spaces when necessary. */ 2407 while (i < newlen) 2408 p[i++] = ' '; 2409 2410 // Replace the line in the buffer. 2411 ml_replace(lnum, newp, FALSE); 2412 2413 // mark the buffer as changed and prepare for displaying 2414 inserted_bytes(lnum, col, newlen - oldlen); 2415 2416 /* 2417 * If we're in Insert or Replace mode and 'showmatch' is set, then briefly 2418 * show the match for right parens and braces. 2419 */ 2420 if (p_sm && (State & INSERT) 2421 && msg_silent == 0 2422 #ifdef FEAT_INS_EXPAND 2423 && !ins_compl_active() 2424 #endif 2425 ) 2426 { 2427 if (has_mbyte) 2428 showmatch(mb_ptr2char(buf)); 2429 else 2430 showmatch(c); 2431 } 2432 2433 #ifdef FEAT_RIGHTLEFT 2434 if (!p_ri || (State & REPLACE_FLAG)) 2435 #endif 2436 { 2437 /* Normal insert: move cursor right */ 2438 curwin->w_cursor.col += charlen; 2439 } 2440 /* 2441 * TODO: should try to update w_row here, to avoid recomputing it later. 2442 */ 2443 } 2444 2445 /* 2446 * Insert a string at the cursor position. 2447 * Note: Does NOT handle Replace mode. 2448 * Caller must have prepared for undo. 2449 */ 2450 void 2451 ins_str(char_u *s) 2452 { 2453 char_u *oldp, *newp; 2454 int newlen = (int)STRLEN(s); 2455 int oldlen; 2456 colnr_T col; 2457 linenr_T lnum = curwin->w_cursor.lnum; 2458 2459 if (virtual_active() && curwin->w_cursor.coladd > 0) 2460 coladvance_force(getviscol()); 2461 2462 col = curwin->w_cursor.col; 2463 oldp = ml_get(lnum); 2464 oldlen = (int)STRLEN(oldp); 2465 2466 newp = alloc_check((unsigned)(oldlen + newlen + 1)); 2467 if (newp == NULL) 2468 return; 2469 if (col > 0) 2470 mch_memmove(newp, oldp, (size_t)col); 2471 mch_memmove(newp + col, s, (size_t)newlen); 2472 mch_memmove(newp + col + newlen, oldp + col, (size_t)(oldlen - col + 1)); 2473 ml_replace(lnum, newp, FALSE); 2474 inserted_bytes(lnum, col, newlen); 2475 curwin->w_cursor.col += newlen; 2476 } 2477 2478 /* 2479 * Delete one character under the cursor. 2480 * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line. 2481 * Caller must have prepared for undo. 2482 * 2483 * return FAIL for failure, OK otherwise 2484 */ 2485 int 2486 del_char(int fixpos) 2487 { 2488 if (has_mbyte) 2489 { 2490 /* Make sure the cursor is at the start of a character. */ 2491 mb_adjust_cursor(); 2492 if (*ml_get_cursor() == NUL) 2493 return FAIL; 2494 return del_chars(1L, fixpos); 2495 } 2496 return del_bytes(1L, fixpos, TRUE); 2497 } 2498 2499 /* 2500 * Like del_bytes(), but delete characters instead of bytes. 2501 */ 2502 int 2503 del_chars(long count, int fixpos) 2504 { 2505 long bytes = 0; 2506 long i; 2507 char_u *p; 2508 int l; 2509 2510 p = ml_get_cursor(); 2511 for (i = 0; i < count && *p != NUL; ++i) 2512 { 2513 l = (*mb_ptr2len)(p); 2514 bytes += l; 2515 p += l; 2516 } 2517 return del_bytes(bytes, fixpos, TRUE); 2518 } 2519 2520 /* 2521 * Delete "count" bytes under the cursor. 2522 * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line. 2523 * Caller must have prepared for undo. 2524 * 2525 * Return FAIL for failure, OK otherwise. 2526 */ 2527 int 2528 del_bytes( 2529 long count, 2530 int fixpos_arg, 2531 int use_delcombine UNUSED) /* 'delcombine' option applies */ 2532 { 2533 char_u *oldp, *newp; 2534 colnr_T oldlen; 2535 colnr_T newlen; 2536 linenr_T lnum = curwin->w_cursor.lnum; 2537 colnr_T col = curwin->w_cursor.col; 2538 int alloc_newp; 2539 long movelen; 2540 int fixpos = fixpos_arg; 2541 2542 oldp = ml_get(lnum); 2543 oldlen = (int)STRLEN(oldp); 2544 2545 /* Can't do anything when the cursor is on the NUL after the line. */ 2546 if (col >= oldlen) 2547 return FAIL; 2548 2549 /* If "count" is zero there is nothing to do. */ 2550 if (count == 0) 2551 return OK; 2552 2553 /* If "count" is negative the caller must be doing something wrong. */ 2554 if (count < 1) 2555 { 2556 siemsg("E950: Invalid count for del_bytes(): %ld", count); 2557 return FAIL; 2558 } 2559 2560 /* If 'delcombine' is set and deleting (less than) one character, only 2561 * delete the last combining character. */ 2562 if (p_deco && use_delcombine && enc_utf8 2563 && utfc_ptr2len(oldp + col) >= count) 2564 { 2565 int cc[MAX_MCO]; 2566 int n; 2567 2568 (void)utfc_ptr2char(oldp + col, cc); 2569 if (cc[0] != NUL) 2570 { 2571 /* Find the last composing char, there can be several. */ 2572 n = col; 2573 do 2574 { 2575 col = n; 2576 count = utf_ptr2len(oldp + n); 2577 n += count; 2578 } while (UTF_COMPOSINGLIKE(oldp + col, oldp + n)); 2579 fixpos = 0; 2580 } 2581 } 2582 2583 /* 2584 * When count is too big, reduce it. 2585 */ 2586 movelen = (long)oldlen - (long)col - count + 1; /* includes trailing NUL */ 2587 if (movelen <= 1) 2588 { 2589 /* 2590 * If we just took off the last character of a non-blank line, and 2591 * fixpos is TRUE, we don't want to end up positioned at the NUL, 2592 * unless "restart_edit" is set or 'virtualedit' contains "onemore". 2593 */ 2594 if (col > 0 && fixpos && restart_edit == 0 2595 && (ve_flags & VE_ONEMORE) == 0) 2596 { 2597 --curwin->w_cursor.col; 2598 curwin->w_cursor.coladd = 0; 2599 if (has_mbyte) 2600 curwin->w_cursor.col -= 2601 (*mb_head_off)(oldp, oldp + curwin->w_cursor.col); 2602 } 2603 count = oldlen - col; 2604 movelen = 1; 2605 } 2606 newlen = oldlen - count; 2607 2608 /* 2609 * If the old line has been allocated the deletion can be done in the 2610 * existing line. Otherwise a new line has to be allocated 2611 * Can't do this when using Netbeans, because we would need to invoke 2612 * netbeans_removed(), which deallocates the line. Let ml_replace() take 2613 * care of notifying Netbeans. 2614 */ 2615 #ifdef FEAT_NETBEANS_INTG 2616 if (netbeans_active()) 2617 alloc_newp = TRUE; 2618 else 2619 #endif 2620 alloc_newp = !ml_line_alloced(); // check if oldp was allocated 2621 if (!alloc_newp) 2622 newp = oldp; // use same allocated memory 2623 else 2624 { // need to allocate a new line 2625 newp = alloc((unsigned)(newlen + 1)); 2626 if (newp == NULL) 2627 return FAIL; 2628 mch_memmove(newp, oldp, (size_t)col); 2629 } 2630 mch_memmove(newp + col, oldp + col + count, (size_t)movelen); 2631 if (alloc_newp) 2632 ml_replace(lnum, newp, FALSE); 2633 #ifdef FEAT_TEXT_PROP 2634 else 2635 { 2636 // Also move any following text properties. 2637 if (oldlen + 1 < curbuf->b_ml.ml_line_len) 2638 mch_memmove(newp + newlen + 1, oldp + oldlen + 1, 2639 (size_t)curbuf->b_ml.ml_line_len - oldlen - 1); 2640 curbuf->b_ml.ml_line_len -= count; 2641 } 2642 #endif 2643 2644 // mark the buffer as changed and prepare for displaying 2645 inserted_bytes(lnum, curwin->w_cursor.col, -count); 2646 2647 return OK; 2648 } 2649 2650 /* 2651 * Delete from cursor to end of line. 2652 * Caller must have prepared for undo. 2653 * 2654 * return FAIL for failure, OK otherwise 2655 */ 2656 int 2657 truncate_line( 2658 int fixpos) /* if TRUE fix the cursor position when done */ 2659 { 2660 char_u *newp; 2661 linenr_T lnum = curwin->w_cursor.lnum; 2662 colnr_T col = curwin->w_cursor.col; 2663 2664 if (col == 0) 2665 newp = vim_strsave((char_u *)""); 2666 else 2667 newp = vim_strnsave(ml_get(lnum), col); 2668 2669 if (newp == NULL) 2670 return FAIL; 2671 2672 ml_replace(lnum, newp, FALSE); 2673 2674 /* mark the buffer as changed and prepare for displaying */ 2675 changed_bytes(lnum, curwin->w_cursor.col); 2676 2677 /* 2678 * If "fixpos" is TRUE we don't want to end up positioned at the NUL. 2679 */ 2680 if (fixpos && curwin->w_cursor.col > 0) 2681 --curwin->w_cursor.col; 2682 2683 return OK; 2684 } 2685 2686 /* 2687 * Delete "nlines" lines at the cursor. 2688 * Saves the lines for undo first if "undo" is TRUE. 2689 */ 2690 void 2691 del_lines( 2692 long nlines, /* number of lines to delete */ 2693 int undo) /* if TRUE, prepare for undo */ 2694 { 2695 long n; 2696 linenr_T first = curwin->w_cursor.lnum; 2697 2698 if (nlines <= 0) 2699 return; 2700 2701 /* save the deleted lines for undo */ 2702 if (undo && u_savedel(first, nlines) == FAIL) 2703 return; 2704 2705 for (n = 0; n < nlines; ) 2706 { 2707 if (curbuf->b_ml.ml_flags & ML_EMPTY) /* nothing to delete */ 2708 break; 2709 2710 ml_delete(first, TRUE); 2711 ++n; 2712 2713 /* If we delete the last line in the file, stop */ 2714 if (first > curbuf->b_ml.ml_line_count) 2715 break; 2716 } 2717 2718 /* Correct the cursor position before calling deleted_lines_mark(), it may 2719 * trigger a callback to display the cursor. */ 2720 curwin->w_cursor.col = 0; 2721 check_cursor_lnum(); 2722 2723 /* adjust marks, mark the buffer as changed and prepare for displaying */ 2724 deleted_lines_mark(first, n); 2725 } 2726 2727 int 2728 gchar_pos(pos_T *pos) 2729 { 2730 char_u *ptr; 2731 2732 /* When searching columns is sometimes put at the end of a line. */ 2733 if (pos->col == MAXCOL) 2734 return NUL; 2735 ptr = ml_get_pos(pos); 2736 if (has_mbyte) 2737 return (*mb_ptr2char)(ptr); 2738 return (int)*ptr; 2739 } 2740 2741 int 2742 gchar_cursor(void) 2743 { 2744 if (has_mbyte) 2745 return (*mb_ptr2char)(ml_get_cursor()); 2746 return (int)*ml_get_cursor(); 2747 } 2748 2749 /* 2750 * Write a character at the current cursor position. 2751 * It is directly written into the block. 2752 */ 2753 void 2754 pchar_cursor(int c) 2755 { 2756 *(ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE) 2757 + curwin->w_cursor.col) = c; 2758 } 2759 2760 /* 2761 * When extra == 0: Return TRUE if the cursor is before or on the first 2762 * non-blank in the line. 2763 * When extra == 1: Return TRUE if the cursor is before the first non-blank in 2764 * the line. 2765 */ 2766 int 2767 inindent(int extra) 2768 { 2769 char_u *ptr; 2770 colnr_T col; 2771 2772 for (col = 0, ptr = ml_get_curline(); VIM_ISWHITE(*ptr); ++col) 2773 ++ptr; 2774 if (col >= curwin->w_cursor.col + extra) 2775 return TRUE; 2776 else 2777 return FALSE; 2778 } 2779 2780 /* 2781 * Skip to next part of an option argument: Skip space and comma. 2782 */ 2783 char_u * 2784 skip_to_option_part(char_u *p) 2785 { 2786 if (*p == ',') 2787 ++p; 2788 while (*p == ' ') 2789 ++p; 2790 return p; 2791 } 2792 2793 /* 2794 * Call this function when something in the current buffer is changed. 2795 * 2796 * Most often called through changed_bytes() and changed_lines(), which also 2797 * mark the area of the display to be redrawn. 2798 * 2799 * Careful: may trigger autocommands that reload the buffer. 2800 */ 2801 void 2802 changed(void) 2803 { 2804 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) 2805 if (p_imst == IM_ON_THE_SPOT) 2806 { 2807 /* The text of the preediting area is inserted, but this doesn't 2808 * mean a change of the buffer yet. That is delayed until the 2809 * text is committed. (this means preedit becomes empty) */ 2810 if (im_is_preediting() && !xim_changed_while_preediting) 2811 return; 2812 xim_changed_while_preediting = FALSE; 2813 } 2814 #endif 2815 2816 if (!curbuf->b_changed) 2817 { 2818 int save_msg_scroll = msg_scroll; 2819 2820 /* Give a warning about changing a read-only file. This may also 2821 * check-out the file, thus change "curbuf"! */ 2822 change_warning(0); 2823 2824 /* Create a swap file if that is wanted. 2825 * Don't do this for "nofile" and "nowrite" buffer types. */ 2826 if (curbuf->b_may_swap 2827 #ifdef FEAT_QUICKFIX 2828 && !bt_dontwrite(curbuf) 2829 #endif 2830 ) 2831 { 2832 int save_need_wait_return = need_wait_return; 2833 2834 need_wait_return = FALSE; 2835 ml_open_file(curbuf); 2836 2837 /* The ml_open_file() can cause an ATTENTION message. 2838 * Wait two seconds, to make sure the user reads this unexpected 2839 * message. Since we could be anywhere, call wait_return() now, 2840 * and don't let the emsg() set msg_scroll. */ 2841 if (need_wait_return && emsg_silent == 0) 2842 { 2843 out_flush(); 2844 ui_delay(2000L, TRUE); 2845 wait_return(TRUE); 2846 msg_scroll = save_msg_scroll; 2847 } 2848 else 2849 need_wait_return = save_need_wait_return; 2850 } 2851 changed_int(); 2852 } 2853 ++CHANGEDTICK(curbuf); 2854 } 2855 2856 /* 2857 * Internal part of changed(), no user interaction. 2858 */ 2859 void 2860 changed_int(void) 2861 { 2862 curbuf->b_changed = TRUE; 2863 ml_setflags(curbuf); 2864 check_status(curbuf); 2865 redraw_tabline = TRUE; 2866 #ifdef FEAT_TITLE 2867 need_maketitle = TRUE; /* set window title later */ 2868 #endif 2869 } 2870 2871 static void changedOneline(buf_T *buf, linenr_T lnum); 2872 static void changed_lines_buf(buf_T *buf, linenr_T lnum, linenr_T lnume, long xtra); 2873 static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra); 2874 2875 /* 2876 * Changed bytes within a single line for the current buffer. 2877 * - marks the windows on this buffer to be redisplayed 2878 * - marks the buffer changed by calling changed() 2879 * - invalidates cached values 2880 * Careful: may trigger autocommands that reload the buffer. 2881 */ 2882 void 2883 changed_bytes(linenr_T lnum, colnr_T col) 2884 { 2885 changedOneline(curbuf, lnum); 2886 changed_common(lnum, col, lnum + 1, 0L); 2887 2888 #ifdef FEAT_DIFF 2889 /* Diff highlighting in other diff windows may need to be updated too. */ 2890 if (curwin->w_p_diff) 2891 { 2892 win_T *wp; 2893 linenr_T wlnum; 2894 2895 FOR_ALL_WINDOWS(wp) 2896 if (wp->w_p_diff && wp != curwin) 2897 { 2898 redraw_win_later(wp, VALID); 2899 wlnum = diff_lnum_win(lnum, wp); 2900 if (wlnum > 0) 2901 changedOneline(wp->w_buffer, wlnum); 2902 } 2903 } 2904 #endif 2905 } 2906 2907 /* 2908 * Like changed_bytes() but also adjust text properties for "added" bytes. 2909 * When "added" is negative text was deleted. 2910 */ 2911 void 2912 inserted_bytes(linenr_T lnum, colnr_T col, int added UNUSED) 2913 { 2914 changed_bytes(lnum, col); 2915 2916 #ifdef FEAT_TEXT_PROP 2917 if (curbuf->b_has_textprop && added != 0) 2918 adjust_prop_columns(lnum, col, added); 2919 #endif 2920 } 2921 2922 static void 2923 changedOneline(buf_T *buf, linenr_T lnum) 2924 { 2925 if (buf->b_mod_set) 2926 { 2927 /* find the maximum area that must be redisplayed */ 2928 if (lnum < buf->b_mod_top) 2929 buf->b_mod_top = lnum; 2930 else if (lnum >= buf->b_mod_bot) 2931 buf->b_mod_bot = lnum + 1; 2932 } 2933 else 2934 { 2935 /* set the area that must be redisplayed to one line */ 2936 buf->b_mod_set = TRUE; 2937 buf->b_mod_top = lnum; 2938 buf->b_mod_bot = lnum + 1; 2939 buf->b_mod_xlines = 0; 2940 } 2941 } 2942 2943 /* 2944 * Appended "count" lines below line "lnum" in the current buffer. 2945 * Must be called AFTER the change and after mark_adjust(). 2946 * Takes care of marking the buffer to be redrawn and sets the changed flag. 2947 */ 2948 void 2949 appended_lines(linenr_T lnum, long count) 2950 { 2951 changed_lines(lnum + 1, 0, lnum + 1, count); 2952 } 2953 2954 /* 2955 * Like appended_lines(), but adjust marks first. 2956 */ 2957 void 2958 appended_lines_mark(linenr_T lnum, long count) 2959 { 2960 /* Skip mark_adjust when adding a line after the last one, there can't 2961 * be marks there. But it's still needed in diff mode. */ 2962 if (lnum + count < curbuf->b_ml.ml_line_count 2963 #ifdef FEAT_DIFF 2964 || curwin->w_p_diff 2965 #endif 2966 ) 2967 mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L); 2968 changed_lines(lnum + 1, 0, lnum + 1, count); 2969 } 2970 2971 /* 2972 * Deleted "count" lines at line "lnum" in the current buffer. 2973 * Must be called AFTER the change and after mark_adjust(). 2974 * Takes care of marking the buffer to be redrawn and sets the changed flag. 2975 */ 2976 void 2977 deleted_lines(linenr_T lnum, long count) 2978 { 2979 changed_lines(lnum, 0, lnum + count, -count); 2980 } 2981 2982 /* 2983 * Like deleted_lines(), but adjust marks first. 2984 * Make sure the cursor is on a valid line before calling, a GUI callback may 2985 * be triggered to display the cursor. 2986 */ 2987 void 2988 deleted_lines_mark(linenr_T lnum, long count) 2989 { 2990 mark_adjust(lnum, (linenr_T)(lnum + count - 1), (long)MAXLNUM, -count); 2991 changed_lines(lnum, 0, lnum + count, -count); 2992 } 2993 2994 /* 2995 * Changed lines for the current buffer. 2996 * Must be called AFTER the change and after mark_adjust(). 2997 * - mark the buffer changed by calling changed() 2998 * - mark the windows on this buffer to be redisplayed 2999 * - invalidate cached values 3000 * "lnum" is the first line that needs displaying, "lnume" the first line 3001 * below the changed lines (BEFORE the change). 3002 * When only inserting lines, "lnum" and "lnume" are equal. 3003 * Takes care of calling changed() and updating b_mod_*. 3004 * Careful: may trigger autocommands that reload the buffer. 3005 */ 3006 void 3007 changed_lines( 3008 linenr_T lnum, /* first line with change */ 3009 colnr_T col, /* column in first line with change */ 3010 linenr_T lnume, /* line below last changed line */ 3011 long xtra) /* number of extra lines (negative when deleting) */ 3012 { 3013 changed_lines_buf(curbuf, lnum, lnume, xtra); 3014 3015 #ifdef FEAT_DIFF 3016 if (xtra == 0 && curwin->w_p_diff && !diff_internal()) 3017 { 3018 /* When the number of lines doesn't change then mark_adjust() isn't 3019 * called and other diff buffers still need to be marked for 3020 * displaying. */ 3021 win_T *wp; 3022 linenr_T wlnum; 3023 3024 FOR_ALL_WINDOWS(wp) 3025 if (wp->w_p_diff && wp != curwin) 3026 { 3027 redraw_win_later(wp, VALID); 3028 wlnum = diff_lnum_win(lnum, wp); 3029 if (wlnum > 0) 3030 changed_lines_buf(wp->w_buffer, wlnum, 3031 lnume - lnum + wlnum, 0L); 3032 } 3033 } 3034 #endif 3035 3036 changed_common(lnum, col, lnume, xtra); 3037 } 3038 3039 static void 3040 changed_lines_buf( 3041 buf_T *buf, 3042 linenr_T lnum, /* first line with change */ 3043 linenr_T lnume, /* line below last changed line */ 3044 long xtra) /* number of extra lines (negative when deleting) */ 3045 { 3046 if (buf->b_mod_set) 3047 { 3048 /* find the maximum area that must be redisplayed */ 3049 if (lnum < buf->b_mod_top) 3050 buf->b_mod_top = lnum; 3051 if (lnum < buf->b_mod_bot) 3052 { 3053 /* adjust old bot position for xtra lines */ 3054 buf->b_mod_bot += xtra; 3055 if (buf->b_mod_bot < lnum) 3056 buf->b_mod_bot = lnum; 3057 } 3058 if (lnume + xtra > buf->b_mod_bot) 3059 buf->b_mod_bot = lnume + xtra; 3060 buf->b_mod_xlines += xtra; 3061 } 3062 else 3063 { 3064 /* set the area that must be redisplayed */ 3065 buf->b_mod_set = TRUE; 3066 buf->b_mod_top = lnum; 3067 buf->b_mod_bot = lnume + xtra; 3068 buf->b_mod_xlines = xtra; 3069 } 3070 } 3071 3072 /* 3073 * Common code for when a change is was made. 3074 * See changed_lines() for the arguments. 3075 * Careful: may trigger autocommands that reload the buffer. 3076 */ 3077 static void 3078 changed_common( 3079 linenr_T lnum, 3080 colnr_T col, 3081 linenr_T lnume, 3082 long xtra) 3083 { 3084 win_T *wp; 3085 tabpage_T *tp; 3086 int i; 3087 #ifdef FEAT_JUMPLIST 3088 int cols; 3089 pos_T *p; 3090 int add; 3091 #endif 3092 3093 /* mark the buffer as modified */ 3094 changed(); 3095 3096 #ifdef FEAT_DIFF 3097 if (curwin->w_p_diff && diff_internal()) 3098 curtab->tp_diff_update = TRUE; 3099 #endif 3100 3101 /* set the '. mark */ 3102 if (!cmdmod.keepjumps) 3103 { 3104 curbuf->b_last_change.lnum = lnum; 3105 curbuf->b_last_change.col = col; 3106 3107 #ifdef FEAT_JUMPLIST 3108 /* Create a new entry if a new undo-able change was started or we 3109 * don't have an entry yet. */ 3110 if (curbuf->b_new_change || curbuf->b_changelistlen == 0) 3111 { 3112 if (curbuf->b_changelistlen == 0) 3113 add = TRUE; 3114 else 3115 { 3116 /* Don't create a new entry when the line number is the same 3117 * as the last one and the column is not too far away. Avoids 3118 * creating many entries for typing "xxxxx". */ 3119 p = &curbuf->b_changelist[curbuf->b_changelistlen - 1]; 3120 if (p->lnum != lnum) 3121 add = TRUE; 3122 else 3123 { 3124 cols = comp_textwidth(FALSE); 3125 if (cols == 0) 3126 cols = 79; 3127 add = (p->col + cols < col || col + cols < p->col); 3128 } 3129 } 3130 if (add) 3131 { 3132 /* This is the first of a new sequence of undo-able changes 3133 * and it's at some distance of the last change. Use a new 3134 * position in the changelist. */ 3135 curbuf->b_new_change = FALSE; 3136 3137 if (curbuf->b_changelistlen == JUMPLISTSIZE) 3138 { 3139 /* changelist is full: remove oldest entry */ 3140 curbuf->b_changelistlen = JUMPLISTSIZE - 1; 3141 mch_memmove(curbuf->b_changelist, curbuf->b_changelist + 1, 3142 sizeof(pos_T) * (JUMPLISTSIZE - 1)); 3143 FOR_ALL_TAB_WINDOWS(tp, wp) 3144 { 3145 /* Correct position in changelist for other windows on 3146 * this buffer. */ 3147 if (wp->w_buffer == curbuf && wp->w_changelistidx > 0) 3148 --wp->w_changelistidx; 3149 } 3150 } 3151 FOR_ALL_TAB_WINDOWS(tp, wp) 3152 { 3153 /* For other windows, if the position in the changelist is 3154 * at the end it stays at the end. */ 3155 if (wp->w_buffer == curbuf 3156 && wp->w_changelistidx == curbuf->b_changelistlen) 3157 ++wp->w_changelistidx; 3158 } 3159 ++curbuf->b_changelistlen; 3160 } 3161 } 3162 curbuf->b_changelist[curbuf->b_changelistlen - 1] = 3163 curbuf->b_last_change; 3164 /* The current window is always after the last change, so that "g," 3165 * takes you back to it. */ 3166 curwin->w_changelistidx = curbuf->b_changelistlen; 3167 #endif 3168 } 3169 3170 FOR_ALL_TAB_WINDOWS(tp, wp) 3171 { 3172 if (wp->w_buffer == curbuf) 3173 { 3174 /* Mark this window to be redrawn later. */ 3175 if (wp->w_redr_type < VALID) 3176 wp->w_redr_type = VALID; 3177 3178 /* Check if a change in the buffer has invalidated the cached 3179 * values for the cursor. */ 3180 #ifdef FEAT_FOLDING 3181 /* 3182 * Update the folds for this window. Can't postpone this, because 3183 * a following operator might work on the whole fold: ">>dd". 3184 */ 3185 foldUpdate(wp, lnum, lnume + xtra - 1); 3186 3187 /* The change may cause lines above or below the change to become 3188 * included in a fold. Set lnum/lnume to the first/last line that 3189 * might be displayed differently. 3190 * Set w_cline_folded here as an efficient way to update it when 3191 * inserting lines just above a closed fold. */ 3192 i = hasFoldingWin(wp, lnum, &lnum, NULL, FALSE, NULL); 3193 if (wp->w_cursor.lnum == lnum) 3194 wp->w_cline_folded = i; 3195 i = hasFoldingWin(wp, lnume, NULL, &lnume, FALSE, NULL); 3196 if (wp->w_cursor.lnum == lnume) 3197 wp->w_cline_folded = i; 3198 3199 /* If the changed line is in a range of previously folded lines, 3200 * compare with the first line in that range. */ 3201 if (wp->w_cursor.lnum <= lnum) 3202 { 3203 i = find_wl_entry(wp, lnum); 3204 if (i >= 0 && wp->w_cursor.lnum > wp->w_lines[i].wl_lnum) 3205 changed_line_abv_curs_win(wp); 3206 } 3207 #endif 3208 3209 if (wp->w_cursor.lnum > lnum) 3210 changed_line_abv_curs_win(wp); 3211 else if (wp->w_cursor.lnum == lnum && wp->w_cursor.col >= col) 3212 changed_cline_bef_curs_win(wp); 3213 if (wp->w_botline >= lnum) 3214 { 3215 /* Assume that botline doesn't change (inserted lines make 3216 * other lines scroll down below botline). */ 3217 approximate_botline_win(wp); 3218 } 3219 3220 /* Check if any w_lines[] entries have become invalid. 3221 * For entries below the change: Correct the lnums for 3222 * inserted/deleted lines. Makes it possible to stop displaying 3223 * after the change. */ 3224 for (i = 0; i < wp->w_lines_valid; ++i) 3225 if (wp->w_lines[i].wl_valid) 3226 { 3227 if (wp->w_lines[i].wl_lnum >= lnum) 3228 { 3229 if (wp->w_lines[i].wl_lnum < lnume) 3230 { 3231 /* line included in change */ 3232 wp->w_lines[i].wl_valid = FALSE; 3233 } 3234 else if (xtra != 0) 3235 { 3236 /* line below change */ 3237 wp->w_lines[i].wl_lnum += xtra; 3238 #ifdef FEAT_FOLDING 3239 wp->w_lines[i].wl_lastlnum += xtra; 3240 #endif 3241 } 3242 } 3243 #ifdef FEAT_FOLDING 3244 else if (wp->w_lines[i].wl_lastlnum >= lnum) 3245 { 3246 /* change somewhere inside this range of folded lines, 3247 * may need to be redrawn */ 3248 wp->w_lines[i].wl_valid = FALSE; 3249 } 3250 #endif 3251 } 3252 3253 #ifdef FEAT_FOLDING 3254 /* Take care of side effects for setting w_topline when folds have 3255 * changed. Esp. when the buffer was changed in another window. */ 3256 if (hasAnyFolding(wp)) 3257 set_topline(wp, wp->w_topline); 3258 #endif 3259 /* relative numbering may require updating more */ 3260 if (wp->w_p_rnu) 3261 redraw_win_later(wp, SOME_VALID); 3262 } 3263 } 3264 3265 /* Call update_screen() later, which checks out what needs to be redrawn, 3266 * since it notices b_mod_set and then uses b_mod_*. */ 3267 if (must_redraw < VALID) 3268 must_redraw = VALID; 3269 3270 /* when the cursor line is changed always trigger CursorMoved */ 3271 if (lnum <= curwin->w_cursor.lnum 3272 && lnume + (xtra < 0 ? -xtra : xtra) > curwin->w_cursor.lnum) 3273 last_cursormoved.lnum = 0; 3274 } 3275 3276 /* 3277 * unchanged() is called when the changed flag must be reset for buffer 'buf' 3278 */ 3279 void 3280 unchanged( 3281 buf_T *buf, 3282 int ff) /* also reset 'fileformat' */ 3283 { 3284 if (buf->b_changed || (ff && file_ff_differs(buf, FALSE))) 3285 { 3286 buf->b_changed = 0; 3287 ml_setflags(buf); 3288 if (ff) 3289 save_file_ff(buf); 3290 check_status(buf); 3291 redraw_tabline = TRUE; 3292 #ifdef FEAT_TITLE 3293 need_maketitle = TRUE; /* set window title later */ 3294 #endif 3295 } 3296 ++CHANGEDTICK(buf); 3297 #ifdef FEAT_NETBEANS_INTG 3298 netbeans_unmodified(buf); 3299 #endif 3300 } 3301 3302 /* 3303 * check_status: called when the status bars for the buffer 'buf' 3304 * need to be updated 3305 */ 3306 void 3307 check_status(buf_T *buf) 3308 { 3309 win_T *wp; 3310 3311 FOR_ALL_WINDOWS(wp) 3312 if (wp->w_buffer == buf && wp->w_status_height) 3313 { 3314 wp->w_redr_status = TRUE; 3315 if (must_redraw < VALID) 3316 must_redraw = VALID; 3317 } 3318 } 3319 3320 /* 3321 * If the file is readonly, give a warning message with the first change. 3322 * Don't do this for autocommands. 3323 * Don't use emsg(), because it flushes the macro buffer. 3324 * If we have undone all changes b_changed will be FALSE, but "b_did_warn" 3325 * will be TRUE. 3326 * Careful: may trigger autocommands that reload the buffer. 3327 */ 3328 void 3329 change_warning( 3330 int col) /* column for message; non-zero when in insert 3331 mode and 'showmode' is on */ 3332 { 3333 static char *w_readonly = N_("W10: Warning: Changing a readonly file"); 3334 3335 if (curbuf->b_did_warn == FALSE 3336 && curbufIsChanged() == 0 3337 && !autocmd_busy 3338 && curbuf->b_p_ro) 3339 { 3340 ++curbuf_lock; 3341 apply_autocmds(EVENT_FILECHANGEDRO, NULL, NULL, FALSE, curbuf); 3342 --curbuf_lock; 3343 if (!curbuf->b_p_ro) 3344 return; 3345 /* 3346 * Do what msg() does, but with a column offset if the warning should 3347 * be after the mode message. 3348 */ 3349 msg_start(); 3350 if (msg_row == Rows - 1) 3351 msg_col = col; 3352 msg_source(HL_ATTR(HLF_W)); 3353 msg_puts_attr(_(w_readonly), HL_ATTR(HLF_W) | MSG_HIST); 3354 #ifdef FEAT_EVAL 3355 set_vim_var_string(VV_WARNINGMSG, (char_u *)_(w_readonly), -1); 3356 #endif 3357 msg_clr_eos(); 3358 (void)msg_end(); 3359 if (msg_silent == 0 && !silent_mode 3360 #ifdef FEAT_EVAL 3361 && time_for_testing != 1 3362 #endif 3363 ) 3364 { 3365 out_flush(); 3366 ui_delay(1000L, TRUE); /* give the user time to think about it */ 3367 } 3368 curbuf->b_did_warn = TRUE; 3369 redraw_cmdline = FALSE; /* don't redraw and erase the message */ 3370 if (msg_row < Rows - 1) 3371 showmode(); 3372 } 3373 } 3374 3375 /* 3376 * Ask for a reply from the user, a 'y' or a 'n'. 3377 * No other characters are accepted, the message is repeated until a valid 3378 * reply is entered or CTRL-C is hit. 3379 * If direct is TRUE, don't use vgetc() but ui_inchar(), don't get characters 3380 * from any buffers but directly from the user. 3381 * 3382 * return the 'y' or 'n' 3383 */ 3384 int 3385 ask_yesno(char_u *str, int direct) 3386 { 3387 int r = ' '; 3388 int save_State = State; 3389 3390 if (exiting) /* put terminal in raw mode for this question */ 3391 settmode(TMODE_RAW); 3392 ++no_wait_return; 3393 #ifdef USE_ON_FLY_SCROLL 3394 dont_scroll = TRUE; /* disallow scrolling here */ 3395 #endif 3396 State = CONFIRM; /* mouse behaves like with :confirm */ 3397 #ifdef FEAT_MOUSE 3398 setmouse(); /* disables mouse for xterm */ 3399 #endif 3400 ++no_mapping; 3401 ++allow_keys; /* no mapping here, but recognize keys */ 3402 3403 while (r != 'y' && r != 'n') 3404 { 3405 /* same highlighting as for wait_return */ 3406 smsg_attr(HL_ATTR(HLF_R), "%s (y/n)?", str); 3407 if (direct) 3408 r = get_keystroke(); 3409 else 3410 r = plain_vgetc(); 3411 if (r == Ctrl_C || r == ESC) 3412 r = 'n'; 3413 msg_putchar(r); /* show what you typed */ 3414 out_flush(); 3415 } 3416 --no_wait_return; 3417 State = save_State; 3418 #ifdef FEAT_MOUSE 3419 setmouse(); 3420 #endif 3421 --no_mapping; 3422 --allow_keys; 3423 3424 return r; 3425 } 3426 3427 #if defined(FEAT_MOUSE) || defined(PROTO) 3428 /* 3429 * Return TRUE if "c" is a mouse key. 3430 */ 3431 int 3432 is_mouse_key(int c) 3433 { 3434 return c == K_LEFTMOUSE 3435 || c == K_LEFTMOUSE_NM 3436 || c == K_LEFTDRAG 3437 || c == K_LEFTRELEASE 3438 || c == K_LEFTRELEASE_NM 3439 || c == K_MOUSEMOVE 3440 || c == K_MIDDLEMOUSE 3441 || c == K_MIDDLEDRAG 3442 || c == K_MIDDLERELEASE 3443 || c == K_RIGHTMOUSE 3444 || c == K_RIGHTDRAG 3445 || c == K_RIGHTRELEASE 3446 || c == K_MOUSEDOWN 3447 || c == K_MOUSEUP 3448 || c == K_MOUSELEFT 3449 || c == K_MOUSERIGHT 3450 || c == K_X1MOUSE 3451 || c == K_X1DRAG 3452 || c == K_X1RELEASE 3453 || c == K_X2MOUSE 3454 || c == K_X2DRAG 3455 || c == K_X2RELEASE; 3456 } 3457 #endif 3458 3459 /* 3460 * Get a key stroke directly from the user. 3461 * Ignores mouse clicks and scrollbar events, except a click for the left 3462 * button (used at the more prompt). 3463 * Doesn't use vgetc(), because it syncs undo and eats mapped characters. 3464 * Disadvantage: typeahead is ignored. 3465 * Translates the interrupt character for unix to ESC. 3466 */ 3467 int 3468 get_keystroke(void) 3469 { 3470 char_u *buf = NULL; 3471 int buflen = 150; 3472 int maxlen; 3473 int len = 0; 3474 int n; 3475 int save_mapped_ctrl_c = mapped_ctrl_c; 3476 int waited = 0; 3477 3478 mapped_ctrl_c = FALSE; /* mappings are not used here */ 3479 for (;;) 3480 { 3481 cursor_on(); 3482 out_flush(); 3483 3484 /* Leave some room for check_termcode() to insert a key code into (max 3485 * 5 chars plus NUL). And fix_input_buffer() can triple the number of 3486 * bytes. */ 3487 maxlen = (buflen - 6 - len) / 3; 3488 if (buf == NULL) 3489 buf = alloc(buflen); 3490 else if (maxlen < 10) 3491 { 3492 char_u *t_buf = buf; 3493 3494 /* Need some more space. This might happen when receiving a long 3495 * escape sequence. */ 3496 buflen += 100; 3497 buf = vim_realloc(buf, buflen); 3498 if (buf == NULL) 3499 vim_free(t_buf); 3500 maxlen = (buflen - 6 - len) / 3; 3501 } 3502 if (buf == NULL) 3503 { 3504 do_outofmem_msg((long_u)buflen); 3505 return ESC; /* panic! */ 3506 } 3507 3508 /* First time: blocking wait. Second time: wait up to 100ms for a 3509 * terminal code to complete. */ 3510 n = ui_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0); 3511 if (n > 0) 3512 { 3513 /* Replace zero and CSI by a special key code. */ 3514 n = fix_input_buffer(buf + len, n); 3515 len += n; 3516 waited = 0; 3517 } 3518 else if (len > 0) 3519 ++waited; /* keep track of the waiting time */ 3520 3521 /* Incomplete termcode and not timed out yet: get more characters */ 3522 if ((n = check_termcode(1, buf, buflen, &len)) < 0 3523 && (!p_ttimeout || waited * 100L < (p_ttm < 0 ? p_tm : p_ttm))) 3524 continue; 3525 3526 if (n == KEYLEN_REMOVED) /* key code removed */ 3527 { 3528 if (must_redraw != 0 && !need_wait_return && (State & CMDLINE) == 0) 3529 { 3530 /* Redrawing was postponed, do it now. */ 3531 update_screen(0); 3532 setcursor(); /* put cursor back where it belongs */ 3533 } 3534 continue; 3535 } 3536 if (n > 0) /* found a termcode: adjust length */ 3537 len = n; 3538 if (len == 0) /* nothing typed yet */ 3539 continue; 3540 3541 /* Handle modifier and/or special key code. */ 3542 n = buf[0]; 3543 if (n == K_SPECIAL) 3544 { 3545 n = TO_SPECIAL(buf[1], buf[2]); 3546 if (buf[1] == KS_MODIFIER 3547 || n == K_IGNORE 3548 #ifdef FEAT_MOUSE 3549 || (is_mouse_key(n) && n != K_LEFTMOUSE) 3550 #endif 3551 #ifdef FEAT_GUI 3552 || n == K_VER_SCROLLBAR 3553 || n == K_HOR_SCROLLBAR 3554 #endif 3555 ) 3556 { 3557 if (buf[1] == KS_MODIFIER) 3558 mod_mask = buf[2]; 3559 len -= 3; 3560 if (len > 0) 3561 mch_memmove(buf, buf + 3, (size_t)len); 3562 continue; 3563 } 3564 break; 3565 } 3566 if (has_mbyte) 3567 { 3568 if (MB_BYTE2LEN(n) > len) 3569 continue; /* more bytes to get */ 3570 buf[len >= buflen ? buflen - 1 : len] = NUL; 3571 n = (*mb_ptr2char)(buf); 3572 } 3573 #ifdef UNIX 3574 if (n == intr_char) 3575 n = ESC; 3576 #endif 3577 break; 3578 } 3579 vim_free(buf); 3580 3581 mapped_ctrl_c = save_mapped_ctrl_c; 3582 return n; 3583 } 3584 3585 /* 3586 * Get a number from the user. 3587 * When "mouse_used" is not NULL allow using the mouse. 3588 */ 3589 int 3590 get_number( 3591 int colon, /* allow colon to abort */ 3592 int *mouse_used) 3593 { 3594 int n = 0; 3595 int c; 3596 int typed = 0; 3597 3598 if (mouse_used != NULL) 3599 *mouse_used = FALSE; 3600 3601 /* When not printing messages, the user won't know what to type, return a 3602 * zero (as if CR was hit). */ 3603 if (msg_silent != 0) 3604 return 0; 3605 3606 #ifdef USE_ON_FLY_SCROLL 3607 dont_scroll = TRUE; /* disallow scrolling here */ 3608 #endif 3609 ++no_mapping; 3610 ++allow_keys; /* no mapping here, but recognize keys */ 3611 for (;;) 3612 { 3613 windgoto(msg_row, msg_col); 3614 c = safe_vgetc(); 3615 if (VIM_ISDIGIT(c)) 3616 { 3617 n = n * 10 + c - '0'; 3618 msg_putchar(c); 3619 ++typed; 3620 } 3621 else if (c == K_DEL || c == K_KDEL || c == K_BS || c == Ctrl_H) 3622 { 3623 if (typed > 0) 3624 { 3625 msg_puts("\b \b"); 3626 --typed; 3627 } 3628 n /= 10; 3629 } 3630 #ifdef FEAT_MOUSE 3631 else if (mouse_used != NULL && c == K_LEFTMOUSE) 3632 { 3633 *mouse_used = TRUE; 3634 n = mouse_row + 1; 3635 break; 3636 } 3637 #endif 3638 else if (n == 0 && c == ':' && colon) 3639 { 3640 stuffcharReadbuff(':'); 3641 if (!exmode_active) 3642 cmdline_row = msg_row; 3643 skip_redraw = TRUE; /* skip redraw once */ 3644 do_redraw = FALSE; 3645 break; 3646 } 3647 else if (c == CAR || c == NL || c == Ctrl_C || c == ESC) 3648 break; 3649 } 3650 --no_mapping; 3651 --allow_keys; 3652 return n; 3653 } 3654 3655 /* 3656 * Ask the user to enter a number. 3657 * When "mouse_used" is not NULL allow using the mouse and in that case return 3658 * the line number. 3659 */ 3660 int 3661 prompt_for_number(int *mouse_used) 3662 { 3663 int i; 3664 int save_cmdline_row; 3665 int save_State; 3666 3667 /* When using ":silent" assume that <CR> was entered. */ 3668 if (mouse_used != NULL) 3669 msg_puts(_("Type number and <Enter> or click with mouse (empty cancels): ")); 3670 else 3671 msg_puts(_("Type number and <Enter> (empty cancels): ")); 3672 3673 // Set the state such that text can be selected/copied/pasted and we still 3674 // get mouse events. redraw_after_callback() will not redraw if cmdline_row 3675 // is zero. 3676 save_cmdline_row = cmdline_row; 3677 cmdline_row = 0; 3678 save_State = State; 3679 State = CMDLINE; 3680 #ifdef FEAT_MOUSE 3681 // May show different mouse shape. 3682 setmouse(); 3683 #endif 3684 3685 i = get_number(TRUE, mouse_used); 3686 if (KeyTyped) 3687 { 3688 /* don't call wait_return() now */ 3689 /* msg_putchar('\n'); */ 3690 cmdline_row = msg_row - 1; 3691 need_wait_return = FALSE; 3692 msg_didany = FALSE; 3693 msg_didout = FALSE; 3694 } 3695 else 3696 cmdline_row = save_cmdline_row; 3697 State = save_State; 3698 #ifdef FEAT_MOUSE 3699 // May need to restore mouse shape. 3700 setmouse(); 3701 #endif 3702 3703 return i; 3704 } 3705 3706 void 3707 msgmore(long n) 3708 { 3709 long pn; 3710 3711 if (global_busy /* no messages now, wait until global is finished */ 3712 || !messaging()) /* 'lazyredraw' set, don't do messages now */ 3713 return; 3714 3715 /* We don't want to overwrite another important message, but do overwrite 3716 * a previous "more lines" or "fewer lines" message, so that "5dd" and 3717 * then "put" reports the last action. */ 3718 if (keep_msg != NULL && !keep_msg_more) 3719 return; 3720 3721 if (n > 0) 3722 pn = n; 3723 else 3724 pn = -n; 3725 3726 if (pn > p_report) 3727 { 3728 if (n > 0) 3729 vim_snprintf(msg_buf, MSG_BUF_LEN, 3730 NGETTEXT("%ld more line", "%ld more lines", pn), pn); 3731 else 3732 vim_snprintf(msg_buf, MSG_BUF_LEN, 3733 NGETTEXT("%ld line less", "%ld fewer lines", pn), pn); 3734 if (got_int) 3735 vim_strcat((char_u *)msg_buf, (char_u *)_(" (Interrupted)"), 3736 MSG_BUF_LEN); 3737 if (msg(msg_buf)) 3738 { 3739 set_keep_msg((char_u *)msg_buf, 0); 3740 keep_msg_more = TRUE; 3741 } 3742 } 3743 } 3744 3745 /* 3746 * flush map and typeahead buffers and give a warning for an error 3747 */ 3748 void 3749 beep_flush(void) 3750 { 3751 if (emsg_silent == 0) 3752 { 3753 flush_buffers(FLUSH_MINIMAL); 3754 vim_beep(BO_ERROR); 3755 } 3756 } 3757 3758 /* 3759 * Give a warning for an error. 3760 */ 3761 void 3762 vim_beep( 3763 unsigned val) /* one of the BO_ values, e.g., BO_OPER */ 3764 { 3765 #ifdef FEAT_EVAL 3766 called_vim_beep = TRUE; 3767 #endif 3768 3769 if (emsg_silent == 0) 3770 { 3771 if (!((bo_flags & val) || (bo_flags & BO_ALL))) 3772 { 3773 #ifdef ELAPSED_FUNC 3774 static int did_init = FALSE; 3775 static elapsed_T start_tv; 3776 3777 /* Only beep once per half a second, otherwise a sequence of beeps 3778 * would freeze Vim. */ 3779 if (!did_init || ELAPSED_FUNC(start_tv) > 500) 3780 { 3781 did_init = TRUE; 3782 ELAPSED_INIT(start_tv); 3783 #endif 3784 if (p_vb 3785 #ifdef FEAT_GUI 3786 /* While the GUI is starting up the termcap is set for 3787 * the GUI but the output still goes to a terminal. */ 3788 && !(gui.in_use && gui.starting) 3789 #endif 3790 ) 3791 { 3792 out_str_cf(T_VB); 3793 #ifdef FEAT_VTP 3794 /* No restore color information, refresh the screen. */ 3795 if (has_vtp_working() != 0 3796 # ifdef FEAT_TERMGUICOLORS 3797 && (p_tgc || (!p_tgc && t_colors >= 256)) 3798 # endif 3799 ) 3800 { 3801 redraw_later(CLEAR); 3802 update_screen(0); 3803 redrawcmd(); 3804 } 3805 #endif 3806 } 3807 else 3808 out_char(BELL); 3809 #ifdef ELAPSED_FUNC 3810 } 3811 #endif 3812 } 3813 3814 /* When 'debug' contains "beep" produce a message. If we are sourcing 3815 * a script or executing a function give the user a hint where the beep 3816 * comes from. */ 3817 if (vim_strchr(p_debug, 'e') != NULL) 3818 { 3819 msg_source(HL_ATTR(HLF_W)); 3820 msg_attr(_("Beep!"), HL_ATTR(HLF_W)); 3821 } 3822 } 3823 } 3824 3825 /* 3826 * To get the "real" home directory: 3827 * - get value of $HOME 3828 * For Unix: 3829 * - go to that directory 3830 * - do mch_dirname() to get the real name of that directory. 3831 * This also works with mounts and links. 3832 * Don't do this for MS-DOS, it will change the "current dir" for a drive. 3833 * For Windows: 3834 * This code is duplicated in init_homedir() in dosinst.c. Keep in sync! 3835 */ 3836 static char_u *homedir = NULL; 3837 3838 void 3839 init_homedir(void) 3840 { 3841 char_u *var; 3842 3843 /* In case we are called a second time (when 'encoding' changes). */ 3844 VIM_CLEAR(homedir); 3845 3846 #ifdef VMS 3847 var = mch_getenv((char_u *)"SYS$LOGIN"); 3848 #else 3849 var = mch_getenv((char_u *)"HOME"); 3850 #endif 3851 3852 #ifdef WIN3264 3853 /* 3854 * Typically, $HOME is not defined on Windows, unless the user has 3855 * specifically defined it for Vim's sake. However, on Windows NT 3856 * platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for 3857 * each user. Try constructing $HOME from these. 3858 */ 3859 if (var == NULL || *var == NUL) 3860 { 3861 char_u *homedrive, *homepath; 3862 3863 homedrive = mch_getenv((char_u *)"HOMEDRIVE"); 3864 homepath = mch_getenv((char_u *)"HOMEPATH"); 3865 if (homepath == NULL || *homepath == NUL) 3866 homepath = (char_u *)"\\"; 3867 if (homedrive != NULL 3868 && STRLEN(homedrive) + STRLEN(homepath) < MAXPATHL) 3869 { 3870 sprintf((char *)NameBuff, "%s%s", homedrive, homepath); 3871 if (NameBuff[0] != NUL) 3872 var = NameBuff; 3873 } 3874 } 3875 3876 if (var == NULL) 3877 var = mch_getenv((char_u *)"USERPROFILE"); 3878 3879 /* 3880 * Weird but true: $HOME may contain an indirect reference to another 3881 * variable, esp. "%USERPROFILE%". Happens when $USERPROFILE isn't set 3882 * when $HOME is being set. 3883 */ 3884 if (var != NULL && *var == '%') 3885 { 3886 char_u *p; 3887 char_u *exp; 3888 3889 p = vim_strchr(var + 1, '%'); 3890 if (p != NULL) 3891 { 3892 vim_strncpy(NameBuff, var + 1, p - (var + 1)); 3893 exp = mch_getenv(NameBuff); 3894 if (exp != NULL && *exp != NUL 3895 && STRLEN(exp) + STRLEN(p) < MAXPATHL) 3896 { 3897 vim_snprintf((char *)NameBuff, MAXPATHL, "%s%s", exp, p + 1); 3898 var = NameBuff; 3899 } 3900 } 3901 } 3902 3903 if (var != NULL && *var == NUL) /* empty is same as not set */ 3904 var = NULL; 3905 3906 if (enc_utf8 && var != NULL) 3907 { 3908 int len; 3909 char_u *pp = NULL; 3910 3911 /* Convert from active codepage to UTF-8. Other conversions are 3912 * not done, because they would fail for non-ASCII characters. */ 3913 acp_to_enc(var, (int)STRLEN(var), &pp, &len); 3914 if (pp != NULL) 3915 { 3916 homedir = pp; 3917 return; 3918 } 3919 } 3920 3921 /* 3922 * Default home dir is C:/ 3923 * Best assumption we can make in such a situation. 3924 */ 3925 if (var == NULL) 3926 var = (char_u *)"C:/"; 3927 #endif 3928 3929 if (var != NULL) 3930 { 3931 #ifdef UNIX 3932 /* 3933 * Change to the directory and get the actual path. This resolves 3934 * links. Don't do it when we can't return. 3935 */ 3936 if (mch_dirname(NameBuff, MAXPATHL) == OK 3937 && mch_chdir((char *)NameBuff) == 0) 3938 { 3939 if (!mch_chdir((char *)var) && mch_dirname(IObuff, IOSIZE) == OK) 3940 var = IObuff; 3941 if (mch_chdir((char *)NameBuff) != 0) 3942 emsg(_(e_prev_dir)); 3943 } 3944 #endif 3945 homedir = vim_strsave(var); 3946 } 3947 } 3948 3949 #if defined(EXITFREE) || defined(PROTO) 3950 void 3951 free_homedir(void) 3952 { 3953 vim_free(homedir); 3954 } 3955 3956 # ifdef FEAT_CMDL_COMPL 3957 void 3958 free_users(void) 3959 { 3960 ga_clear_strings(&ga_users); 3961 } 3962 # endif 3963 #endif 3964 3965 /* 3966 * Call expand_env() and store the result in an allocated string. 3967 * This is not very memory efficient, this expects the result to be freed 3968 * again soon. 3969 */ 3970 char_u * 3971 expand_env_save(char_u *src) 3972 { 3973 return expand_env_save_opt(src, FALSE); 3974 } 3975 3976 /* 3977 * Idem, but when "one" is TRUE handle the string as one file name, only 3978 * expand "~" at the start. 3979 */ 3980 char_u * 3981 expand_env_save_opt(char_u *src, int one) 3982 { 3983 char_u *p; 3984 3985 p = alloc(MAXPATHL); 3986 if (p != NULL) 3987 expand_env_esc(src, p, MAXPATHL, FALSE, one, NULL); 3988 return p; 3989 } 3990 3991 /* 3992 * Expand environment variable with path name. 3993 * "~/" is also expanded, using $HOME. For Unix "~user/" is expanded. 3994 * Skips over "\ ", "\~" and "\$" (not for Win32 though). 3995 * If anything fails no expansion is done and dst equals src. 3996 */ 3997 void 3998 expand_env( 3999 char_u *src, /* input string e.g. "$HOME/vim.hlp" */ 4000 char_u *dst, /* where to put the result */ 4001 int dstlen) /* maximum length of the result */ 4002 { 4003 expand_env_esc(src, dst, dstlen, FALSE, FALSE, NULL); 4004 } 4005 4006 void 4007 expand_env_esc( 4008 char_u *srcp, /* input string e.g. "$HOME/vim.hlp" */ 4009 char_u *dst, /* where to put the result */ 4010 int dstlen, /* maximum length of the result */ 4011 int esc, /* escape spaces in expanded variables */ 4012 int one, /* "srcp" is one file name */ 4013 char_u *startstr) /* start again after this (can be NULL) */ 4014 { 4015 char_u *src; 4016 char_u *tail; 4017 int c; 4018 char_u *var; 4019 int copy_char; 4020 int mustfree; /* var was allocated, need to free it later */ 4021 int at_start = TRUE; /* at start of a name */ 4022 int startstr_len = 0; 4023 4024 if (startstr != NULL) 4025 startstr_len = (int)STRLEN(startstr); 4026 4027 src = skipwhite(srcp); 4028 --dstlen; /* leave one char space for "\," */ 4029 while (*src && dstlen > 0) 4030 { 4031 #ifdef FEAT_EVAL 4032 /* Skip over `=expr`. */ 4033 if (src[0] == '`' && src[1] == '=') 4034 { 4035 size_t len; 4036 4037 var = src; 4038 src += 2; 4039 (void)skip_expr(&src); 4040 if (*src == '`') 4041 ++src; 4042 len = src - var; 4043 if (len > (size_t)dstlen) 4044 len = dstlen; 4045 vim_strncpy(dst, var, len); 4046 dst += len; 4047 dstlen -= (int)len; 4048 continue; 4049 } 4050 #endif 4051 copy_char = TRUE; 4052 if ((*src == '$' 4053 #ifdef VMS 4054 && at_start 4055 #endif 4056 ) 4057 #if defined(MSWIN) 4058 || *src == '%' 4059 #endif 4060 || (*src == '~' && at_start)) 4061 { 4062 mustfree = FALSE; 4063 4064 /* 4065 * The variable name is copied into dst temporarily, because it may 4066 * be a string in read-only memory and a NUL needs to be appended. 4067 */ 4068 if (*src != '~') /* environment var */ 4069 { 4070 tail = src + 1; 4071 var = dst; 4072 c = dstlen - 1; 4073 4074 #ifdef UNIX 4075 /* Unix has ${var-name} type environment vars */ 4076 if (*tail == '{' && !vim_isIDc('{')) 4077 { 4078 tail++; /* ignore '{' */ 4079 while (c-- > 0 && *tail && *tail != '}') 4080 *var++ = *tail++; 4081 } 4082 else 4083 #endif 4084 { 4085 while (c-- > 0 && *tail != NUL && ((vim_isIDc(*tail)) 4086 #if defined(MSWIN) 4087 || (*src == '%' && *tail != '%') 4088 #endif 4089 )) 4090 { 4091 *var++ = *tail++; 4092 } 4093 } 4094 4095 #if defined(MSWIN) || defined(UNIX) 4096 # ifdef UNIX 4097 if (src[1] == '{' && *tail != '}') 4098 # else 4099 if (*src == '%' && *tail != '%') 4100 # endif 4101 var = NULL; 4102 else 4103 { 4104 # ifdef UNIX 4105 if (src[1] == '{') 4106 # else 4107 if (*src == '%') 4108 #endif 4109 ++tail; 4110 #endif 4111 *var = NUL; 4112 var = vim_getenv(dst, &mustfree); 4113 #if defined(MSWIN) || defined(UNIX) 4114 } 4115 #endif 4116 } 4117 /* home directory */ 4118 else if ( src[1] == NUL 4119 || vim_ispathsep(src[1]) 4120 || vim_strchr((char_u *)" ,\t\n", src[1]) != NULL) 4121 { 4122 var = homedir; 4123 tail = src + 1; 4124 } 4125 else /* user directory */ 4126 { 4127 #if defined(UNIX) || (defined(VMS) && defined(USER_HOME)) 4128 /* 4129 * Copy ~user to dst[], so we can put a NUL after it. 4130 */ 4131 tail = src; 4132 var = dst; 4133 c = dstlen - 1; 4134 while ( c-- > 0 4135 && *tail 4136 && vim_isfilec(*tail) 4137 && !vim_ispathsep(*tail)) 4138 *var++ = *tail++; 4139 *var = NUL; 4140 # ifdef UNIX 4141 /* 4142 * If the system supports getpwnam(), use it. 4143 * Otherwise, or if getpwnam() fails, the shell is used to 4144 * expand ~user. This is slower and may fail if the shell 4145 * does not support ~user (old versions of /bin/sh). 4146 */ 4147 # if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H) 4148 { 4149 /* Note: memory allocated by getpwnam() is never freed. 4150 * Calling endpwent() apparently doesn't help. */ 4151 struct passwd *pw = (*dst == NUL) 4152 ? NULL : getpwnam((char *)dst + 1); 4153 4154 var = (pw == NULL) ? NULL : (char_u *)pw->pw_dir; 4155 } 4156 if (var == NULL) 4157 # endif 4158 { 4159 expand_T xpc; 4160 4161 ExpandInit(&xpc); 4162 xpc.xp_context = EXPAND_FILES; 4163 var = ExpandOne(&xpc, dst, NULL, 4164 WILD_ADD_SLASH|WILD_SILENT, WILD_EXPAND_FREE); 4165 mustfree = TRUE; 4166 } 4167 4168 # else /* !UNIX, thus VMS */ 4169 /* 4170 * USER_HOME is a comma-separated list of 4171 * directories to search for the user account in. 4172 */ 4173 { 4174 char_u test[MAXPATHL], paths[MAXPATHL]; 4175 char_u *path, *next_path, *ptr; 4176 stat_T st; 4177 4178 STRCPY(paths, USER_HOME); 4179 next_path = paths; 4180 while (*next_path) 4181 { 4182 for (path = next_path; *next_path && *next_path != ','; 4183 next_path++); 4184 if (*next_path) 4185 *next_path++ = NUL; 4186 STRCPY(test, path); 4187 STRCAT(test, "/"); 4188 STRCAT(test, dst + 1); 4189 if (mch_stat(test, &st) == 0) 4190 { 4191 var = alloc(STRLEN(test) + 1); 4192 STRCPY(var, test); 4193 mustfree = TRUE; 4194 break; 4195 } 4196 } 4197 } 4198 # endif /* UNIX */ 4199 #else 4200 /* cannot expand user's home directory, so don't try */ 4201 var = NULL; 4202 tail = (char_u *)""; /* for gcc */ 4203 #endif /* UNIX || VMS */ 4204 } 4205 4206 #ifdef BACKSLASH_IN_FILENAME 4207 /* If 'shellslash' is set change backslashes to forward slashes. 4208 * Can't use slash_adjust(), p_ssl may be set temporarily. */ 4209 if (p_ssl && var != NULL && vim_strchr(var, '\\') != NULL) 4210 { 4211 char_u *p = vim_strsave(var); 4212 4213 if (p != NULL) 4214 { 4215 if (mustfree) 4216 vim_free(var); 4217 var = p; 4218 mustfree = TRUE; 4219 forward_slash(var); 4220 } 4221 } 4222 #endif 4223 4224 /* If "var" contains white space, escape it with a backslash. 4225 * Required for ":e ~/tt" when $HOME includes a space. */ 4226 if (esc && var != NULL && vim_strpbrk(var, (char_u *)" \t") != NULL) 4227 { 4228 char_u *p = vim_strsave_escaped(var, (char_u *)" \t"); 4229 4230 if (p != NULL) 4231 { 4232 if (mustfree) 4233 vim_free(var); 4234 var = p; 4235 mustfree = TRUE; 4236 } 4237 } 4238 4239 if (var != NULL && *var != NUL 4240 && (STRLEN(var) + STRLEN(tail) + 1 < (unsigned)dstlen)) 4241 { 4242 STRCPY(dst, var); 4243 dstlen -= (int)STRLEN(var); 4244 c = (int)STRLEN(var); 4245 /* if var[] ends in a path separator and tail[] starts 4246 * with it, skip a character */ 4247 if (*var != NUL && after_pathsep(dst, dst + c) 4248 #if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA) 4249 && dst[-1] != ':' 4250 #endif 4251 && vim_ispathsep(*tail)) 4252 ++tail; 4253 dst += c; 4254 src = tail; 4255 copy_char = FALSE; 4256 } 4257 if (mustfree) 4258 vim_free(var); 4259 } 4260 4261 if (copy_char) /* copy at least one char */ 4262 { 4263 /* 4264 * Recognize the start of a new name, for '~'. 4265 * Don't do this when "one" is TRUE, to avoid expanding "~" in 4266 * ":edit foo ~ foo". 4267 */ 4268 at_start = FALSE; 4269 if (src[0] == '\\' && src[1] != NUL) 4270 { 4271 *dst++ = *src++; 4272 --dstlen; 4273 } 4274 else if ((src[0] == ' ' || src[0] == ',') && !one) 4275 at_start = TRUE; 4276 if (dstlen > 0) 4277 { 4278 *dst++ = *src++; 4279 --dstlen; 4280 4281 if (startstr != NULL && src - startstr_len >= srcp 4282 && STRNCMP(src - startstr_len, startstr, 4283 startstr_len) == 0) 4284 at_start = TRUE; 4285 } 4286 } 4287 4288 } 4289 *dst = NUL; 4290 } 4291 4292 /* 4293 * Vim's version of getenv(). 4294 * Special handling of $HOME, $VIM and $VIMRUNTIME. 4295 * Also does ACP to 'enc' conversion for Win32. 4296 * "mustfree" is set to TRUE when returned is allocated, it must be 4297 * initialized to FALSE by the caller. 4298 */ 4299 char_u * 4300 vim_getenv(char_u *name, int *mustfree) 4301 { 4302 char_u *p; 4303 char_u *pend; 4304 int vimruntime; 4305 4306 #if defined(MSWIN) 4307 /* use "C:/" when $HOME is not set */ 4308 if (STRCMP(name, "HOME") == 0) 4309 return homedir; 4310 #endif 4311 4312 p = mch_getenv(name); 4313 if (p != NULL && *p == NUL) /* empty is the same as not set */ 4314 p = NULL; 4315 4316 if (p != NULL) 4317 { 4318 #if defined(WIN3264) 4319 if (enc_utf8) 4320 { 4321 int len; 4322 char_u *pp = NULL; 4323 4324 /* Convert from active codepage to UTF-8. Other conversions are 4325 * not done, because they would fail for non-ASCII characters. */ 4326 acp_to_enc(p, (int)STRLEN(p), &pp, &len); 4327 if (pp != NULL) 4328 { 4329 p = pp; 4330 *mustfree = TRUE; 4331 } 4332 } 4333 #endif 4334 return p; 4335 } 4336 4337 vimruntime = (STRCMP(name, "VIMRUNTIME") == 0); 4338 if (!vimruntime && STRCMP(name, "VIM") != 0) 4339 return NULL; 4340 4341 /* 4342 * When expanding $VIMRUNTIME fails, try using $VIM/vim<version> or $VIM. 4343 * Don't do this when default_vimruntime_dir is non-empty. 4344 */ 4345 if (vimruntime 4346 #ifdef HAVE_PATHDEF 4347 && *default_vimruntime_dir == NUL 4348 #endif 4349 ) 4350 { 4351 p = mch_getenv((char_u *)"VIM"); 4352 if (p != NULL && *p == NUL) /* empty is the same as not set */ 4353 p = NULL; 4354 if (p != NULL) 4355 { 4356 p = vim_version_dir(p); 4357 if (p != NULL) 4358 *mustfree = TRUE; 4359 else 4360 p = mch_getenv((char_u *)"VIM"); 4361 4362 #if defined(WIN3264) 4363 if (enc_utf8) 4364 { 4365 int len; 4366 char_u *pp = NULL; 4367 4368 /* Convert from active codepage to UTF-8. Other conversions 4369 * are not done, because they would fail for non-ASCII 4370 * characters. */ 4371 acp_to_enc(p, (int)STRLEN(p), &pp, &len); 4372 if (pp != NULL) 4373 { 4374 if (*mustfree) 4375 vim_free(p); 4376 p = pp; 4377 *mustfree = TRUE; 4378 } 4379 } 4380 #endif 4381 } 4382 } 4383 4384 /* 4385 * When expanding $VIM or $VIMRUNTIME fails, try using: 4386 * - the directory name from 'helpfile' (unless it contains '$') 4387 * - the executable name from argv[0] 4388 */ 4389 if (p == NULL) 4390 { 4391 if (p_hf != NULL && vim_strchr(p_hf, '$') == NULL) 4392 p = p_hf; 4393 #ifdef USE_EXE_NAME 4394 /* 4395 * Use the name of the executable, obtained from argv[0]. 4396 */ 4397 else 4398 p = exe_name; 4399 #endif 4400 if (p != NULL) 4401 { 4402 /* remove the file name */ 4403 pend = gettail(p); 4404 4405 /* remove "doc/" from 'helpfile', if present */ 4406 if (p == p_hf) 4407 pend = remove_tail(p, pend, (char_u *)"doc"); 4408 4409 #ifdef USE_EXE_NAME 4410 # ifdef MACOS_X 4411 /* remove "MacOS" from exe_name and add "Resources/vim" */ 4412 if (p == exe_name) 4413 { 4414 char_u *pend1; 4415 char_u *pnew; 4416 4417 pend1 = remove_tail(p, pend, (char_u *)"MacOS"); 4418 if (pend1 != pend) 4419 { 4420 pnew = alloc((unsigned)(pend1 - p) + 15); 4421 if (pnew != NULL) 4422 { 4423 STRNCPY(pnew, p, (pend1 - p)); 4424 STRCPY(pnew + (pend1 - p), "Resources/vim"); 4425 p = pnew; 4426 pend = p + STRLEN(p); 4427 } 4428 } 4429 } 4430 # endif 4431 /* remove "src/" from exe_name, if present */ 4432 if (p == exe_name) 4433 pend = remove_tail(p, pend, (char_u *)"src"); 4434 #endif 4435 4436 /* for $VIM, remove "runtime/" or "vim54/", if present */ 4437 if (!vimruntime) 4438 { 4439 pend = remove_tail(p, pend, (char_u *)RUNTIME_DIRNAME); 4440 pend = remove_tail(p, pend, (char_u *)VIM_VERSION_NODOT); 4441 } 4442 4443 /* remove trailing path separator */ 4444 if (pend > p && after_pathsep(p, pend)) 4445 --pend; 4446 4447 #ifdef MACOS_X 4448 if (p == exe_name || p == p_hf) 4449 #endif 4450 /* check that the result is a directory name */ 4451 p = vim_strnsave(p, (int)(pend - p)); 4452 4453 if (p != NULL && !mch_isdir(p)) 4454 VIM_CLEAR(p); 4455 else 4456 { 4457 #ifdef USE_EXE_NAME 4458 /* may add "/vim54" or "/runtime" if it exists */ 4459 if (vimruntime && (pend = vim_version_dir(p)) != NULL) 4460 { 4461 vim_free(p); 4462 p = pend; 4463 } 4464 #endif 4465 *mustfree = TRUE; 4466 } 4467 } 4468 } 4469 4470 #ifdef HAVE_PATHDEF 4471 /* When there is a pathdef.c file we can use default_vim_dir and 4472 * default_vimruntime_dir */ 4473 if (p == NULL) 4474 { 4475 /* Only use default_vimruntime_dir when it is not empty */ 4476 if (vimruntime && *default_vimruntime_dir != NUL) 4477 { 4478 p = default_vimruntime_dir; 4479 *mustfree = FALSE; 4480 } 4481 else if (*default_vim_dir != NUL) 4482 { 4483 if (vimruntime && (p = vim_version_dir(default_vim_dir)) != NULL) 4484 *mustfree = TRUE; 4485 else 4486 { 4487 p = default_vim_dir; 4488 *mustfree = FALSE; 4489 } 4490 } 4491 } 4492 #endif 4493 4494 /* 4495 * Set the environment variable, so that the new value can be found fast 4496 * next time, and others can also use it (e.g. Perl). 4497 */ 4498 if (p != NULL) 4499 { 4500 if (vimruntime) 4501 { 4502 vim_setenv((char_u *)"VIMRUNTIME", p); 4503 didset_vimruntime = TRUE; 4504 } 4505 else 4506 { 4507 vim_setenv((char_u *)"VIM", p); 4508 didset_vim = TRUE; 4509 } 4510 } 4511 return p; 4512 } 4513 4514 /* 4515 * Check if the directory "vimdir/<version>" or "vimdir/runtime" exists. 4516 * Return NULL if not, return its name in allocated memory otherwise. 4517 */ 4518 static char_u * 4519 vim_version_dir(char_u *vimdir) 4520 { 4521 char_u *p; 4522 4523 if (vimdir == NULL || *vimdir == NUL) 4524 return NULL; 4525 p = concat_fnames(vimdir, (char_u *)VIM_VERSION_NODOT, TRUE); 4526 if (p != NULL && mch_isdir(p)) 4527 return p; 4528 vim_free(p); 4529 p = concat_fnames(vimdir, (char_u *)RUNTIME_DIRNAME, TRUE); 4530 if (p != NULL && mch_isdir(p)) 4531 return p; 4532 vim_free(p); 4533 return NULL; 4534 } 4535 4536 /* 4537 * If the string between "p" and "pend" ends in "name/", return "pend" minus 4538 * the length of "name/". Otherwise return "pend". 4539 */ 4540 static char_u * 4541 remove_tail(char_u *p, char_u *pend, char_u *name) 4542 { 4543 int len = (int)STRLEN(name) + 1; 4544 char_u *newend = pend - len; 4545 4546 if (newend >= p 4547 && fnamencmp(newend, name, len - 1) == 0 4548 && (newend == p || after_pathsep(p, newend))) 4549 return newend; 4550 return pend; 4551 } 4552 4553 #if defined(FEAT_EVAL) || defined(PROTO) 4554 void 4555 vim_unsetenv(char_u *var) 4556 { 4557 #ifdef HAVE_UNSETENV 4558 unsetenv((char *)var); 4559 #else 4560 vim_setenv(var, (char_u *)""); 4561 #endif 4562 } 4563 #endif 4564 4565 4566 /* 4567 * Our portable version of setenv. 4568 */ 4569 void 4570 vim_setenv(char_u *name, char_u *val) 4571 { 4572 #ifdef HAVE_SETENV 4573 mch_setenv((char *)name, (char *)val, 1); 4574 #else 4575 char_u *envbuf; 4576 4577 /* 4578 * Putenv does not copy the string, it has to remain 4579 * valid. The allocated memory will never be freed. 4580 */ 4581 envbuf = alloc((unsigned)(STRLEN(name) + STRLEN(val) + 2)); 4582 if (envbuf != NULL) 4583 { 4584 sprintf((char *)envbuf, "%s=%s", name, val); 4585 putenv((char *)envbuf); 4586 } 4587 #endif 4588 #ifdef FEAT_GETTEXT 4589 /* 4590 * When setting $VIMRUNTIME adjust the directory to find message 4591 * translations to $VIMRUNTIME/lang. 4592 */ 4593 if (*val != NUL && STRICMP(name, "VIMRUNTIME") == 0) 4594 { 4595 char_u *buf = concat_str(val, (char_u *)"/lang"); 4596 4597 if (buf != NULL) 4598 { 4599 bindtextdomain(VIMPACKAGE, (char *)buf); 4600 vim_free(buf); 4601 } 4602 } 4603 #endif 4604 } 4605 4606 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 4607 /* 4608 * Function given to ExpandGeneric() to obtain an environment variable name. 4609 */ 4610 char_u * 4611 get_env_name( 4612 expand_T *xp UNUSED, 4613 int idx) 4614 { 4615 # if defined(AMIGA) 4616 /* 4617 * No environ[] on the Amiga. 4618 */ 4619 return NULL; 4620 # else 4621 # ifndef __WIN32__ 4622 /* Borland C++ 5.2 has this in a header file. */ 4623 extern char **environ; 4624 # endif 4625 # define ENVNAMELEN 100 4626 static char_u name[ENVNAMELEN]; 4627 char_u *str; 4628 int n; 4629 4630 str = (char_u *)environ[idx]; 4631 if (str == NULL) 4632 return NULL; 4633 4634 for (n = 0; n < ENVNAMELEN - 1; ++n) 4635 { 4636 if (str[n] == '=' || str[n] == NUL) 4637 break; 4638 name[n] = str[n]; 4639 } 4640 name[n] = NUL; 4641 return name; 4642 # endif 4643 } 4644 4645 /* 4646 * Add a user name to the list of users in ga_users. 4647 * Do nothing if user name is NULL or empty. 4648 */ 4649 static void 4650 add_user(char_u *user, int need_copy) 4651 { 4652 char_u *user_copy = (user != NULL && need_copy) 4653 ? vim_strsave(user) : user; 4654 4655 if (user_copy == NULL || *user_copy == NUL || ga_grow(&ga_users, 1) == FAIL) 4656 { 4657 if (need_copy) 4658 vim_free(user); 4659 return; 4660 } 4661 ((char_u **)(ga_users.ga_data))[ga_users.ga_len++] = user_copy; 4662 } 4663 4664 /* 4665 * Find all user names for user completion. 4666 * Done only once and then cached. 4667 */ 4668 static void 4669 init_users(void) 4670 { 4671 static int lazy_init_done = FALSE; 4672 4673 if (lazy_init_done) 4674 return; 4675 4676 lazy_init_done = TRUE; 4677 ga_init2(&ga_users, sizeof(char_u *), 20); 4678 4679 # if defined(HAVE_GETPWENT) && defined(HAVE_PWD_H) 4680 { 4681 struct passwd* pw; 4682 4683 setpwent(); 4684 while ((pw = getpwent()) != NULL) 4685 add_user((char_u *)pw->pw_name, TRUE); 4686 endpwent(); 4687 } 4688 # elif defined(WIN3264) 4689 { 4690 DWORD nusers = 0, ntotal = 0, i; 4691 PUSER_INFO_0 uinfo; 4692 4693 if (NetUserEnum(NULL, 0, 0, (LPBYTE *) &uinfo, MAX_PREFERRED_LENGTH, 4694 &nusers, &ntotal, NULL) == NERR_Success) 4695 { 4696 for (i = 0; i < nusers; i++) 4697 add_user(utf16_to_enc(uinfo[i].usri0_name, NULL), FALSE); 4698 4699 NetApiBufferFree(uinfo); 4700 } 4701 } 4702 # endif 4703 # if defined(HAVE_GETPWNAM) 4704 { 4705 char_u *user_env = mch_getenv((char_u *)"USER"); 4706 4707 // The $USER environment variable may be a valid remote user name (NIS, 4708 // LDAP) not already listed by getpwent(), as getpwent() only lists 4709 // local user names. If $USER is not already listed, check whether it 4710 // is a valid remote user name using getpwnam() and if it is, add it to 4711 // the list of user names. 4712 4713 if (user_env != NULL && *user_env != NUL) 4714 { 4715 int i; 4716 4717 for (i = 0; i < ga_users.ga_len; i++) 4718 { 4719 char_u *local_user = ((char_u **)ga_users.ga_data)[i]; 4720 4721 if (STRCMP(local_user, user_env) == 0) 4722 break; 4723 } 4724 4725 if (i == ga_users.ga_len) 4726 { 4727 struct passwd *pw = getpwnam((char *)user_env); 4728 4729 if (pw != NULL) 4730 add_user((char_u *)pw->pw_name, TRUE); 4731 } 4732 } 4733 } 4734 # endif 4735 } 4736 4737 /* 4738 * Function given to ExpandGeneric() to obtain an user names. 4739 */ 4740 char_u* 4741 get_users(expand_T *xp UNUSED, int idx) 4742 { 4743 init_users(); 4744 if (idx < ga_users.ga_len) 4745 return ((char_u **)ga_users.ga_data)[idx]; 4746 return NULL; 4747 } 4748 4749 /* 4750 * Check whether name matches a user name. Return: 4751 * 0 if name does not match any user name. 4752 * 1 if name partially matches the beginning of a user name. 4753 * 2 is name fully matches a user name. 4754 */ 4755 int 4756 match_user(char_u *name) 4757 { 4758 int i; 4759 int n = (int)STRLEN(name); 4760 int result = 0; 4761 4762 init_users(); 4763 for (i = 0; i < ga_users.ga_len; i++) 4764 { 4765 if (STRCMP(((char_u **)ga_users.ga_data)[i], name) == 0) 4766 return 2; /* full match */ 4767 if (STRNCMP(((char_u **)ga_users.ga_data)[i], name, n) == 0) 4768 result = 1; /* partial match */ 4769 } 4770 return result; 4771 } 4772 #endif 4773 4774 /* 4775 * Replace home directory by "~" in each space or comma separated file name in 4776 * 'src'. 4777 * If anything fails (except when out of space) dst equals src. 4778 */ 4779 void 4780 home_replace( 4781 buf_T *buf, /* when not NULL, check for help files */ 4782 char_u *src, /* input file name */ 4783 char_u *dst, /* where to put the result */ 4784 int dstlen, /* maximum length of the result */ 4785 int one) /* if TRUE, only replace one file name, include 4786 spaces and commas in the file name. */ 4787 { 4788 size_t dirlen = 0, envlen = 0; 4789 size_t len; 4790 char_u *homedir_env, *homedir_env_orig; 4791 char_u *p; 4792 4793 if (src == NULL) 4794 { 4795 *dst = NUL; 4796 return; 4797 } 4798 4799 /* 4800 * If the file is a help file, remove the path completely. 4801 */ 4802 if (buf != NULL && buf->b_help) 4803 { 4804 vim_snprintf((char *)dst, dstlen, "%s", gettail(src)); 4805 return; 4806 } 4807 4808 /* 4809 * We check both the value of the $HOME environment variable and the 4810 * "real" home directory. 4811 */ 4812 if (homedir != NULL) 4813 dirlen = STRLEN(homedir); 4814 4815 #ifdef VMS 4816 homedir_env_orig = homedir_env = mch_getenv((char_u *)"SYS$LOGIN"); 4817 #else 4818 homedir_env_orig = homedir_env = mch_getenv((char_u *)"HOME"); 4819 #endif 4820 #ifdef WIN3264 4821 if (homedir_env == NULL) 4822 homedir_env_orig = homedir_env = mch_getenv((char_u *)"USERPROFILE"); 4823 #endif 4824 /* Empty is the same as not set. */ 4825 if (homedir_env != NULL && *homedir_env == NUL) 4826 homedir_env = NULL; 4827 4828 #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) 4829 if (homedir_env != NULL && *homedir_env == '~') 4830 { 4831 int usedlen = 0; 4832 int flen; 4833 char_u *fbuf = NULL; 4834 4835 flen = (int)STRLEN(homedir_env); 4836 (void)modify_fname((char_u *)":p", FALSE, &usedlen, 4837 &homedir_env, &fbuf, &flen); 4838 flen = (int)STRLEN(homedir_env); 4839 if (flen > 0 && vim_ispathsep(homedir_env[flen - 1])) 4840 /* Remove the trailing / that is added to a directory. */ 4841 homedir_env[flen - 1] = NUL; 4842 } 4843 #endif 4844 4845 if (homedir_env != NULL) 4846 envlen = STRLEN(homedir_env); 4847 4848 if (!one) 4849 src = skipwhite(src); 4850 while (*src && dstlen > 0) 4851 { 4852 /* 4853 * Here we are at the beginning of a file name. 4854 * First, check to see if the beginning of the file name matches 4855 * $HOME or the "real" home directory. Check that there is a '/' 4856 * after the match (so that if e.g. the file is "/home/pieter/bla", 4857 * and the home directory is "/home/piet", the file does not end up 4858 * as "~er/bla" (which would seem to indicate the file "bla" in user 4859 * er's home directory)). 4860 */ 4861 p = homedir; 4862 len = dirlen; 4863 for (;;) 4864 { 4865 if ( len 4866 && fnamencmp(src, p, len) == 0 4867 && (vim_ispathsep(src[len]) 4868 || (!one && (src[len] == ',' || src[len] == ' ')) 4869 || src[len] == NUL)) 4870 { 4871 src += len; 4872 if (--dstlen > 0) 4873 *dst++ = '~'; 4874 4875 /* 4876 * If it's just the home directory, add "/". 4877 */ 4878 if (!vim_ispathsep(src[0]) && --dstlen > 0) 4879 *dst++ = '/'; 4880 break; 4881 } 4882 if (p == homedir_env) 4883 break; 4884 p = homedir_env; 4885 len = envlen; 4886 } 4887 4888 /* if (!one) skip to separator: space or comma */ 4889 while (*src && (one || (*src != ',' && *src != ' ')) && --dstlen > 0) 4890 *dst++ = *src++; 4891 /* skip separator */ 4892 while ((*src == ' ' || *src == ',') && --dstlen > 0) 4893 *dst++ = *src++; 4894 } 4895 /* if (dstlen == 0) out of space, what to do??? */ 4896 4897 *dst = NUL; 4898 4899 if (homedir_env != homedir_env_orig) 4900 vim_free(homedir_env); 4901 } 4902 4903 /* 4904 * Like home_replace, store the replaced string in allocated memory. 4905 * When something fails, NULL is returned. 4906 */ 4907 char_u * 4908 home_replace_save( 4909 buf_T *buf, /* when not NULL, check for help files */ 4910 char_u *src) /* input file name */ 4911 { 4912 char_u *dst; 4913 unsigned len; 4914 4915 len = 3; /* space for "~/" and trailing NUL */ 4916 if (src != NULL) /* just in case */ 4917 len += (unsigned)STRLEN(src); 4918 dst = alloc(len); 4919 if (dst != NULL) 4920 home_replace(buf, src, dst, len, TRUE); 4921 return dst; 4922 } 4923 4924 /* 4925 * Compare two file names and return: 4926 * FPC_SAME if they both exist and are the same file. 4927 * FPC_SAMEX if they both don't exist and have the same file name. 4928 * FPC_DIFF if they both exist and are different files. 4929 * FPC_NOTX if they both don't exist. 4930 * FPC_DIFFX if one of them doesn't exist. 4931 * For the first name environment variables are expanded 4932 */ 4933 int 4934 fullpathcmp( 4935 char_u *s1, 4936 char_u *s2, 4937 int checkname) /* when both don't exist, check file names */ 4938 { 4939 #ifdef UNIX 4940 char_u exp1[MAXPATHL]; 4941 char_u full1[MAXPATHL]; 4942 char_u full2[MAXPATHL]; 4943 stat_T st1, st2; 4944 int r1, r2; 4945 4946 expand_env(s1, exp1, MAXPATHL); 4947 r1 = mch_stat((char *)exp1, &st1); 4948 r2 = mch_stat((char *)s2, &st2); 4949 if (r1 != 0 && r2 != 0) 4950 { 4951 /* if mch_stat() doesn't work, may compare the names */ 4952 if (checkname) 4953 { 4954 if (fnamecmp(exp1, s2) == 0) 4955 return FPC_SAMEX; 4956 r1 = vim_FullName(exp1, full1, MAXPATHL, FALSE); 4957 r2 = vim_FullName(s2, full2, MAXPATHL, FALSE); 4958 if (r1 == OK && r2 == OK && fnamecmp(full1, full2) == 0) 4959 return FPC_SAMEX; 4960 } 4961 return FPC_NOTX; 4962 } 4963 if (r1 != 0 || r2 != 0) 4964 return FPC_DIFFX; 4965 if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) 4966 return FPC_SAME; 4967 return FPC_DIFF; 4968 #else 4969 char_u *exp1; /* expanded s1 */ 4970 char_u *full1; /* full path of s1 */ 4971 char_u *full2; /* full path of s2 */ 4972 int retval = FPC_DIFF; 4973 int r1, r2; 4974 4975 /* allocate one buffer to store three paths (alloc()/free() is slow!) */ 4976 if ((exp1 = alloc(MAXPATHL * 3)) != NULL) 4977 { 4978 full1 = exp1 + MAXPATHL; 4979 full2 = full1 + MAXPATHL; 4980 4981 expand_env(s1, exp1, MAXPATHL); 4982 r1 = vim_FullName(exp1, full1, MAXPATHL, FALSE); 4983 r2 = vim_FullName(s2, full2, MAXPATHL, FALSE); 4984 4985 /* If vim_FullName() fails, the file probably doesn't exist. */ 4986 if (r1 != OK && r2 != OK) 4987 { 4988 if (checkname && fnamecmp(exp1, s2) == 0) 4989 retval = FPC_SAMEX; 4990 else 4991 retval = FPC_NOTX; 4992 } 4993 else if (r1 != OK || r2 != OK) 4994 retval = FPC_DIFFX; 4995 else if (fnamecmp(full1, full2)) 4996 retval = FPC_DIFF; 4997 else 4998 retval = FPC_SAME; 4999 vim_free(exp1); 5000 } 5001 return retval; 5002 #endif 5003 } 5004 5005 /* 5006 * Get the tail of a path: the file name. 5007 * When the path ends in a path separator the tail is the NUL after it. 5008 * Fail safe: never returns NULL. 5009 */ 5010 char_u * 5011 gettail(char_u *fname) 5012 { 5013 char_u *p1, *p2; 5014 5015 if (fname == NULL) 5016 return (char_u *)""; 5017 for (p1 = p2 = get_past_head(fname); *p2; ) /* find last part of path */ 5018 { 5019 if (vim_ispathsep_nocolon(*p2)) 5020 p1 = p2 + 1; 5021 MB_PTR_ADV(p2); 5022 } 5023 return p1; 5024 } 5025 5026 #if defined(FEAT_SEARCHPATH) 5027 /* 5028 * Return the end of the directory name, on the first path 5029 * separator: 5030 * "/path/file", "/path/dir/", "/path//dir", "/file" 5031 * ^ ^ ^ ^ 5032 */ 5033 static char_u * 5034 gettail_dir(char_u *fname) 5035 { 5036 char_u *dir_end = fname; 5037 char_u *next_dir_end = fname; 5038 int look_for_sep = TRUE; 5039 char_u *p; 5040 5041 for (p = fname; *p != NUL; ) 5042 { 5043 if (vim_ispathsep(*p)) 5044 { 5045 if (look_for_sep) 5046 { 5047 next_dir_end = p; 5048 look_for_sep = FALSE; 5049 } 5050 } 5051 else 5052 { 5053 if (!look_for_sep) 5054 dir_end = next_dir_end; 5055 look_for_sep = TRUE; 5056 } 5057 MB_PTR_ADV(p); 5058 } 5059 return dir_end; 5060 } 5061 #endif 5062 5063 /* 5064 * Get pointer to tail of "fname", including path separators. Putting a NUL 5065 * here leaves the directory name. Takes care of "c:/" and "//". 5066 * Always returns a valid pointer. 5067 */ 5068 char_u * 5069 gettail_sep(char_u *fname) 5070 { 5071 char_u *p; 5072 char_u *t; 5073 5074 p = get_past_head(fname); /* don't remove the '/' from "c:/file" */ 5075 t = gettail(fname); 5076 while (t > p && after_pathsep(fname, t)) 5077 --t; 5078 #ifdef VMS 5079 /* path separator is part of the path */ 5080 ++t; 5081 #endif 5082 return t; 5083 } 5084 5085 /* 5086 * get the next path component (just after the next path separator). 5087 */ 5088 char_u * 5089 getnextcomp(char_u *fname) 5090 { 5091 while (*fname && !vim_ispathsep(*fname)) 5092 MB_PTR_ADV(fname); 5093 if (*fname) 5094 ++fname; 5095 return fname; 5096 } 5097 5098 /* 5099 * Get a pointer to one character past the head of a path name. 5100 * Unix: after "/"; DOS: after "c:\"; Amiga: after "disk:/"; Mac: no head. 5101 * If there is no head, path is returned. 5102 */ 5103 char_u * 5104 get_past_head(char_u *path) 5105 { 5106 char_u *retval; 5107 5108 #if defined(MSWIN) 5109 /* may skip "c:" */ 5110 if (isalpha(path[0]) && path[1] == ':') 5111 retval = path + 2; 5112 else 5113 retval = path; 5114 #else 5115 # if defined(AMIGA) 5116 /* may skip "label:" */ 5117 retval = vim_strchr(path, ':'); 5118 if (retval == NULL) 5119 retval = path; 5120 # else /* Unix */ 5121 retval = path; 5122 # endif 5123 #endif 5124 5125 while (vim_ispathsep(*retval)) 5126 ++retval; 5127 5128 return retval; 5129 } 5130 5131 /* 5132 * Return TRUE if 'c' is a path separator. 5133 * Note that for MS-Windows this includes the colon. 5134 */ 5135 int 5136 vim_ispathsep(int c) 5137 { 5138 #ifdef UNIX 5139 return (c == '/'); /* UNIX has ':' inside file names */ 5140 #else 5141 # ifdef BACKSLASH_IN_FILENAME 5142 return (c == ':' || c == '/' || c == '\\'); 5143 # else 5144 # ifdef VMS 5145 /* server"user passwd"::device:[full.path.name]fname.extension;version" */ 5146 return (c == ':' || c == '[' || c == ']' || c == '/' 5147 || c == '<' || c == '>' || c == '"' ); 5148 # else 5149 return (c == ':' || c == '/'); 5150 # endif /* VMS */ 5151 # endif 5152 #endif 5153 } 5154 5155 /* 5156 * Like vim_ispathsep(c), but exclude the colon for MS-Windows. 5157 */ 5158 int 5159 vim_ispathsep_nocolon(int c) 5160 { 5161 return vim_ispathsep(c) 5162 #ifdef BACKSLASH_IN_FILENAME 5163 && c != ':' 5164 #endif 5165 ; 5166 } 5167 5168 #if defined(FEAT_SEARCHPATH) || defined(PROTO) 5169 /* 5170 * return TRUE if 'c' is a path list separator. 5171 */ 5172 int 5173 vim_ispathlistsep(int c) 5174 { 5175 #ifdef UNIX 5176 return (c == ':'); 5177 #else 5178 return (c == ';'); /* might not be right for every system... */ 5179 #endif 5180 } 5181 #endif 5182 5183 /* 5184 * Shorten the path of a file from "~/foo/../.bar/fname" to "~/f/../.b/fname" 5185 * It's done in-place. 5186 */ 5187 void 5188 shorten_dir(char_u *str) 5189 { 5190 char_u *tail, *s, *d; 5191 int skip = FALSE; 5192 5193 tail = gettail(str); 5194 d = str; 5195 for (s = str; ; ++s) 5196 { 5197 if (s >= tail) /* copy the whole tail */ 5198 { 5199 *d++ = *s; 5200 if (*s == NUL) 5201 break; 5202 } 5203 else if (vim_ispathsep(*s)) /* copy '/' and next char */ 5204 { 5205 *d++ = *s; 5206 skip = FALSE; 5207 } 5208 else if (!skip) 5209 { 5210 *d++ = *s; /* copy next char */ 5211 if (*s != '~' && *s != '.') /* and leading "~" and "." */ 5212 skip = TRUE; 5213 if (has_mbyte) 5214 { 5215 int l = mb_ptr2len(s); 5216 5217 while (--l > 0) 5218 *d++ = *++s; 5219 } 5220 } 5221 } 5222 } 5223 5224 /* 5225 * Return TRUE if the directory of "fname" exists, FALSE otherwise. 5226 * Also returns TRUE if there is no directory name. 5227 * "fname" must be writable!. 5228 */ 5229 int 5230 dir_of_file_exists(char_u *fname) 5231 { 5232 char_u *p; 5233 int c; 5234 int retval; 5235 5236 p = gettail_sep(fname); 5237 if (p == fname) 5238 return TRUE; 5239 c = *p; 5240 *p = NUL; 5241 retval = mch_isdir(fname); 5242 *p = c; 5243 return retval; 5244 } 5245 5246 /* 5247 * Versions of fnamecmp() and fnamencmp() that handle '/' and '\' equally 5248 * and deal with 'fileignorecase'. 5249 */ 5250 int 5251 vim_fnamecmp(char_u *x, char_u *y) 5252 { 5253 #ifdef BACKSLASH_IN_FILENAME 5254 return vim_fnamencmp(x, y, MAXPATHL); 5255 #else 5256 if (p_fic) 5257 return MB_STRICMP(x, y); 5258 return STRCMP(x, y); 5259 #endif 5260 } 5261 5262 int 5263 vim_fnamencmp(char_u *x, char_u *y, size_t len) 5264 { 5265 #ifdef BACKSLASH_IN_FILENAME 5266 char_u *px = x; 5267 char_u *py = y; 5268 int cx = NUL; 5269 int cy = NUL; 5270 5271 while (len > 0) 5272 { 5273 cx = PTR2CHAR(px); 5274 cy = PTR2CHAR(py); 5275 if (cx == NUL || cy == NUL 5276 || ((p_fic ? MB_TOLOWER(cx) != MB_TOLOWER(cy) : cx != cy) 5277 && !(cx == '/' && cy == '\\') 5278 && !(cx == '\\' && cy == '/'))) 5279 break; 5280 len -= MB_PTR2LEN(px); 5281 px += MB_PTR2LEN(px); 5282 py += MB_PTR2LEN(py); 5283 } 5284 if (len == 0) 5285 return 0; 5286 return (cx - cy); 5287 #else 5288 if (p_fic) 5289 return MB_STRNICMP(x, y, len); 5290 return STRNCMP(x, y, len); 5291 #endif 5292 } 5293 5294 /* 5295 * Concatenate file names fname1 and fname2 into allocated memory. 5296 * Only add a '/' or '\\' when 'sep' is TRUE and it is necessary. 5297 */ 5298 char_u * 5299 concat_fnames(char_u *fname1, char_u *fname2, int sep) 5300 { 5301 char_u *dest; 5302 5303 dest = alloc((unsigned)(STRLEN(fname1) + STRLEN(fname2) + 3)); 5304 if (dest != NULL) 5305 { 5306 STRCPY(dest, fname1); 5307 if (sep) 5308 add_pathsep(dest); 5309 STRCAT(dest, fname2); 5310 } 5311 return dest; 5312 } 5313 5314 /* 5315 * Concatenate two strings and return the result in allocated memory. 5316 * Returns NULL when out of memory. 5317 */ 5318 char_u * 5319 concat_str(char_u *str1, char_u *str2) 5320 { 5321 char_u *dest; 5322 size_t l = STRLEN(str1); 5323 5324 dest = alloc((unsigned)(l + STRLEN(str2) + 1L)); 5325 if (dest != NULL) 5326 { 5327 STRCPY(dest, str1); 5328 STRCPY(dest + l, str2); 5329 } 5330 return dest; 5331 } 5332 5333 /* 5334 * Add a path separator to a file name, unless it already ends in a path 5335 * separator. 5336 */ 5337 void 5338 add_pathsep(char_u *p) 5339 { 5340 if (*p != NUL && !after_pathsep(p, p + STRLEN(p))) 5341 STRCAT(p, PATHSEPSTR); 5342 } 5343 5344 /* 5345 * FullName_save - Make an allocated copy of a full file name. 5346 * Returns NULL when out of memory. 5347 */ 5348 char_u * 5349 FullName_save( 5350 char_u *fname, 5351 int force) /* force expansion, even when it already looks 5352 * like a full path name */ 5353 { 5354 char_u *buf; 5355 char_u *new_fname = NULL; 5356 5357 if (fname == NULL) 5358 return NULL; 5359 5360 buf = alloc((unsigned)MAXPATHL); 5361 if (buf != NULL) 5362 { 5363 if (vim_FullName(fname, buf, MAXPATHL, force) != FAIL) 5364 new_fname = vim_strsave(buf); 5365 else 5366 new_fname = vim_strsave(fname); 5367 vim_free(buf); 5368 } 5369 return new_fname; 5370 } 5371 5372 void 5373 prepare_to_exit(void) 5374 { 5375 #if defined(SIGHUP) && defined(SIG_IGN) 5376 /* Ignore SIGHUP, because a dropped connection causes a read error, which 5377 * makes Vim exit and then handling SIGHUP causes various reentrance 5378 * problems. */ 5379 signal(SIGHUP, SIG_IGN); 5380 #endif 5381 5382 #ifdef FEAT_GUI 5383 if (gui.in_use) 5384 { 5385 gui.dying = TRUE; 5386 out_trash(); /* trash any pending output */ 5387 } 5388 else 5389 #endif 5390 { 5391 windgoto((int)Rows - 1, 0); 5392 5393 /* 5394 * Switch terminal mode back now, so messages end up on the "normal" 5395 * screen (if there are two screens). 5396 */ 5397 settmode(TMODE_COOK); 5398 stoptermcap(); 5399 out_flush(); 5400 } 5401 } 5402 5403 /* 5404 * Preserve files and exit. 5405 * When called IObuff must contain a message. 5406 * NOTE: This may be called from deathtrap() in a signal handler, avoid unsafe 5407 * functions, such as allocating memory. 5408 */ 5409 void 5410 preserve_exit(void) 5411 { 5412 buf_T *buf; 5413 5414 prepare_to_exit(); 5415 5416 /* Setting this will prevent free() calls. That avoids calling free() 5417 * recursively when free() was invoked with a bad pointer. */ 5418 really_exiting = TRUE; 5419 5420 out_str(IObuff); 5421 screen_start(); /* don't know where cursor is now */ 5422 out_flush(); 5423 5424 ml_close_notmod(); /* close all not-modified buffers */ 5425 5426 FOR_ALL_BUFFERS(buf) 5427 { 5428 if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL) 5429 { 5430 OUT_STR("Vim: preserving files...\n"); 5431 screen_start(); /* don't know where cursor is now */ 5432 out_flush(); 5433 ml_sync_all(FALSE, FALSE); /* preserve all swap files */ 5434 break; 5435 } 5436 } 5437 5438 ml_close_all(FALSE); /* close all memfiles, without deleting */ 5439 5440 OUT_STR("Vim: Finished.\n"); 5441 5442 getout(1); 5443 } 5444 5445 /* 5446 * return TRUE if "fname" exists. 5447 */ 5448 int 5449 vim_fexists(char_u *fname) 5450 { 5451 stat_T st; 5452 5453 if (mch_stat((char *)fname, &st)) 5454 return FALSE; 5455 return TRUE; 5456 } 5457 5458 /* 5459 * Check for CTRL-C pressed, but only once in a while. 5460 * Should be used instead of ui_breakcheck() for functions that check for 5461 * each line in the file. Calling ui_breakcheck() each time takes too much 5462 * time, because it can be a system call. 5463 */ 5464 5465 #ifndef BREAKCHECK_SKIP 5466 # ifdef FEAT_GUI /* assume the GUI only runs on fast computers */ 5467 # define BREAKCHECK_SKIP 200 5468 # else 5469 # define BREAKCHECK_SKIP 32 5470 # endif 5471 #endif 5472 5473 static int breakcheck_count = 0; 5474 5475 void 5476 line_breakcheck(void) 5477 { 5478 if (++breakcheck_count >= BREAKCHECK_SKIP) 5479 { 5480 breakcheck_count = 0; 5481 ui_breakcheck(); 5482 } 5483 } 5484 5485 /* 5486 * Like line_breakcheck() but check 10 times less often. 5487 */ 5488 void 5489 fast_breakcheck(void) 5490 { 5491 if (++breakcheck_count >= BREAKCHECK_SKIP * 10) 5492 { 5493 breakcheck_count = 0; 5494 ui_breakcheck(); 5495 } 5496 } 5497 5498 /* 5499 * Invoke expand_wildcards() for one pattern. 5500 * Expand items like "%:h" before the expansion. 5501 * Returns OK or FAIL. 5502 */ 5503 int 5504 expand_wildcards_eval( 5505 char_u **pat, /* pointer to input pattern */ 5506 int *num_file, /* resulting number of files */ 5507 char_u ***file, /* array of resulting files */ 5508 int flags) /* EW_DIR, etc. */ 5509 { 5510 int ret = FAIL; 5511 char_u *eval_pat = NULL; 5512 char_u *exp_pat = *pat; 5513 char *ignored_msg; 5514 int usedlen; 5515 5516 if (*exp_pat == '%' || *exp_pat == '#' || *exp_pat == '<') 5517 { 5518 ++emsg_off; 5519 eval_pat = eval_vars(exp_pat, exp_pat, &usedlen, 5520 NULL, &ignored_msg, NULL); 5521 --emsg_off; 5522 if (eval_pat != NULL) 5523 exp_pat = concat_str(eval_pat, exp_pat + usedlen); 5524 } 5525 5526 if (exp_pat != NULL) 5527 ret = expand_wildcards(1, &exp_pat, num_file, file, flags); 5528 5529 if (eval_pat != NULL) 5530 { 5531 vim_free(exp_pat); 5532 vim_free(eval_pat); 5533 } 5534 5535 return ret; 5536 } 5537 5538 /* 5539 * Expand wildcards. Calls gen_expand_wildcards() and removes files matching 5540 * 'wildignore'. 5541 * Returns OK or FAIL. When FAIL then "num_files" won't be set. 5542 */ 5543 int 5544 expand_wildcards( 5545 int num_pat, /* number of input patterns */ 5546 char_u **pat, /* array of input patterns */ 5547 int *num_files, /* resulting number of files */ 5548 char_u ***files, /* array of resulting files */ 5549 int flags) /* EW_DIR, etc. */ 5550 { 5551 int retval; 5552 int i, j; 5553 char_u *p; 5554 int non_suf_match; /* number without matching suffix */ 5555 5556 retval = gen_expand_wildcards(num_pat, pat, num_files, files, flags); 5557 5558 /* When keeping all matches, return here */ 5559 if ((flags & EW_KEEPALL) || retval == FAIL) 5560 return retval; 5561 5562 #ifdef FEAT_WILDIGN 5563 /* 5564 * Remove names that match 'wildignore'. 5565 */ 5566 if (*p_wig) 5567 { 5568 char_u *ffname; 5569 5570 /* check all files in (*files)[] */ 5571 for (i = 0; i < *num_files; ++i) 5572 { 5573 ffname = FullName_save((*files)[i], FALSE); 5574 if (ffname == NULL) /* out of memory */ 5575 break; 5576 # ifdef VMS 5577 vms_remove_version(ffname); 5578 # endif 5579 if (match_file_list(p_wig, (*files)[i], ffname)) 5580 { 5581 /* remove this matching file from the list */ 5582 vim_free((*files)[i]); 5583 for (j = i; j + 1 < *num_files; ++j) 5584 (*files)[j] = (*files)[j + 1]; 5585 --*num_files; 5586 --i; 5587 } 5588 vim_free(ffname); 5589 } 5590 5591 /* If the number of matches is now zero, we fail. */ 5592 if (*num_files == 0) 5593 { 5594 VIM_CLEAR(*files); 5595 return FAIL; 5596 } 5597 } 5598 #endif 5599 5600 /* 5601 * Move the names where 'suffixes' match to the end. 5602 */ 5603 if (*num_files > 1) 5604 { 5605 non_suf_match = 0; 5606 for (i = 0; i < *num_files; ++i) 5607 { 5608 if (!match_suffix((*files)[i])) 5609 { 5610 /* 5611 * Move the name without matching suffix to the front 5612 * of the list. 5613 */ 5614 p = (*files)[i]; 5615 for (j = i; j > non_suf_match; --j) 5616 (*files)[j] = (*files)[j - 1]; 5617 (*files)[non_suf_match++] = p; 5618 } 5619 } 5620 } 5621 5622 return retval; 5623 } 5624 5625 /* 5626 * Return TRUE if "fname" matches with an entry in 'suffixes'. 5627 */ 5628 int 5629 match_suffix(char_u *fname) 5630 { 5631 int fnamelen, setsuflen; 5632 char_u *setsuf; 5633 #define MAXSUFLEN 30 /* maximum length of a file suffix */ 5634 char_u suf_buf[MAXSUFLEN]; 5635 5636 fnamelen = (int)STRLEN(fname); 5637 setsuflen = 0; 5638 for (setsuf = p_su; *setsuf; ) 5639 { 5640 setsuflen = copy_option_part(&setsuf, suf_buf, MAXSUFLEN, ".,"); 5641 if (setsuflen == 0) 5642 { 5643 char_u *tail = gettail(fname); 5644 5645 /* empty entry: match name without a '.' */ 5646 if (vim_strchr(tail, '.') == NULL) 5647 { 5648 setsuflen = 1; 5649 break; 5650 } 5651 } 5652 else 5653 { 5654 if (fnamelen >= setsuflen 5655 && fnamencmp(suf_buf, fname + fnamelen - setsuflen, 5656 (size_t)setsuflen) == 0) 5657 break; 5658 setsuflen = 0; 5659 } 5660 } 5661 return (setsuflen != 0); 5662 } 5663 5664 #if !defined(NO_EXPANDPATH) || defined(PROTO) 5665 5666 # ifdef VIM_BACKTICK 5667 static int vim_backtick(char_u *p); 5668 static int expand_backtick(garray_T *gap, char_u *pat, int flags); 5669 # endif 5670 5671 # if defined(WIN3264) 5672 /* 5673 * File name expansion code for MS-DOS, Win16 and Win32. It's here because 5674 * it's shared between these systems. 5675 */ 5676 # if defined(PROTO) 5677 # define _cdecl 5678 # else 5679 # ifdef __BORLANDC__ 5680 # define _cdecl _RTLENTRYF 5681 # endif 5682 # endif 5683 5684 /* 5685 * comparison function for qsort in dos_expandpath() 5686 */ 5687 static int _cdecl 5688 pstrcmp(const void *a, const void *b) 5689 { 5690 return (pathcmp(*(char **)a, *(char **)b, -1)); 5691 } 5692 5693 /* 5694 * Recursively expand one path component into all matching files and/or 5695 * directories. Adds matches to "gap". Handles "*", "?", "[a-z]", "**", etc. 5696 * Return the number of matches found. 5697 * "path" has backslashes before chars that are not to be expanded, starting 5698 * at "path[wildoff]". 5699 * Return the number of matches found. 5700 * NOTE: much of this is identical to unix_expandpath(), keep in sync! 5701 */ 5702 static int 5703 dos_expandpath( 5704 garray_T *gap, 5705 char_u *path, 5706 int wildoff, 5707 int flags, /* EW_* flags */ 5708 int didstar) /* expanded "**" once already */ 5709 { 5710 char_u *buf; 5711 char_u *path_end; 5712 char_u *p, *s, *e; 5713 int start_len = gap->ga_len; 5714 char_u *pat; 5715 regmatch_T regmatch; 5716 int starts_with_dot; 5717 int matches; 5718 int len; 5719 int starstar = FALSE; 5720 static int stardepth = 0; /* depth for "**" expansion */ 5721 WIN32_FIND_DATA fb; 5722 HANDLE hFind = (HANDLE)0; 5723 WIN32_FIND_DATAW wfb; 5724 WCHAR *wn = NULL; /* UCS-2 name, NULL when not used. */ 5725 char_u *matchname; 5726 int ok; 5727 5728 /* Expanding "**" may take a long time, check for CTRL-C. */ 5729 if (stardepth > 0) 5730 { 5731 ui_breakcheck(); 5732 if (got_int) 5733 return 0; 5734 } 5735 5736 // Make room for file name. When doing encoding conversion the actual 5737 // length may be quite a bit longer, thus use the maximum possible length. 5738 buf = alloc((int)MAXPATHL); 5739 if (buf == NULL) 5740 return 0; 5741 5742 /* 5743 * Find the first part in the path name that contains a wildcard or a ~1. 5744 * Copy it into buf, including the preceding characters. 5745 */ 5746 p = buf; 5747 s = buf; 5748 e = NULL; 5749 path_end = path; 5750 while (*path_end != NUL) 5751 { 5752 /* May ignore a wildcard that has a backslash before it; it will 5753 * be removed by rem_backslash() or file_pat_to_reg_pat() below. */ 5754 if (path_end >= path + wildoff && rem_backslash(path_end)) 5755 *p++ = *path_end++; 5756 else if (*path_end == '\\' || *path_end == ':' || *path_end == '/') 5757 { 5758 if (e != NULL) 5759 break; 5760 s = p + 1; 5761 } 5762 else if (path_end >= path + wildoff 5763 && vim_strchr((char_u *)"*?[~", *path_end) != NULL) 5764 e = p; 5765 if (has_mbyte) 5766 { 5767 len = (*mb_ptr2len)(path_end); 5768 STRNCPY(p, path_end, len); 5769 p += len; 5770 path_end += len; 5771 } 5772 else 5773 *p++ = *path_end++; 5774 } 5775 e = p; 5776 *e = NUL; 5777 5778 /* now we have one wildcard component between s and e */ 5779 /* Remove backslashes between "wildoff" and the start of the wildcard 5780 * component. */ 5781 for (p = buf + wildoff; p < s; ++p) 5782 if (rem_backslash(p)) 5783 { 5784 STRMOVE(p, p + 1); 5785 --e; 5786 --s; 5787 } 5788 5789 /* Check for "**" between "s" and "e". */ 5790 for (p = s; p < e; ++p) 5791 if (p[0] == '*' && p[1] == '*') 5792 starstar = TRUE; 5793 5794 starts_with_dot = *s == '.'; 5795 pat = file_pat_to_reg_pat(s, e, NULL, FALSE); 5796 if (pat == NULL) 5797 { 5798 vim_free(buf); 5799 return 0; 5800 } 5801 5802 /* compile the regexp into a program */ 5803 if (flags & (EW_NOERROR | EW_NOTWILD)) 5804 ++emsg_silent; 5805 regmatch.rm_ic = TRUE; /* Always ignore case */ 5806 regmatch.regprog = vim_regcomp(pat, RE_MAGIC); 5807 if (flags & (EW_NOERROR | EW_NOTWILD)) 5808 --emsg_silent; 5809 vim_free(pat); 5810 5811 if (regmatch.regprog == NULL && (flags & EW_NOTWILD) == 0) 5812 { 5813 vim_free(buf); 5814 return 0; 5815 } 5816 5817 /* remember the pattern or file name being looked for */ 5818 matchname = vim_strsave(s); 5819 5820 /* If "**" is by itself, this is the first time we encounter it and more 5821 * is following then find matches without any directory. */ 5822 if (!didstar && stardepth < 100 && starstar && e - s == 2 5823 && *path_end == '/') 5824 { 5825 STRCPY(s, path_end + 1); 5826 ++stardepth; 5827 (void)dos_expandpath(gap, buf, (int)(s - buf), flags, TRUE); 5828 --stardepth; 5829 } 5830 5831 /* Scan all files in the directory with "dir/ *.*" */ 5832 STRCPY(s, "*.*"); 5833 if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) 5834 { 5835 /* The active codepage differs from 'encoding'. Attempt using the 5836 * wide function. If it fails because it is not implemented fall back 5837 * to the non-wide version (for Windows 98) */ 5838 wn = enc_to_utf16(buf, NULL); 5839 if (wn != NULL) 5840 { 5841 hFind = FindFirstFileW(wn, &wfb); 5842 if (hFind == INVALID_HANDLE_VALUE 5843 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 5844 VIM_CLEAR(wn); 5845 } 5846 } 5847 5848 if (wn == NULL) 5849 hFind = FindFirstFile((LPCSTR)buf, &fb); 5850 ok = (hFind != INVALID_HANDLE_VALUE); 5851 5852 while (ok) 5853 { 5854 if (wn != NULL) 5855 p = utf16_to_enc(wfb.cFileName, NULL); /* p is allocated here */ 5856 else 5857 p = (char_u *)fb.cFileName; 5858 /* Ignore entries starting with a dot, unless when asked for. Accept 5859 * all entries found with "matchname". */ 5860 if ((p[0] != '.' || starts_with_dot 5861 || ((flags & EW_DODOT) 5862 && p[1] != NUL && (p[1] != '.' || p[2] != NUL))) 5863 && (matchname == NULL 5864 || (regmatch.regprog != NULL 5865 && vim_regexec(®match, p, (colnr_T)0)) 5866 || ((flags & EW_NOTWILD) 5867 && fnamencmp(path + (s - buf), p, e - s) == 0))) 5868 { 5869 STRCPY(s, p); 5870 len = (int)STRLEN(buf); 5871 5872 if (starstar && stardepth < 100) 5873 { 5874 /* For "**" in the pattern first go deeper in the tree to 5875 * find matches. */ 5876 STRCPY(buf + len, "/**"); 5877 STRCPY(buf + len + 3, path_end); 5878 ++stardepth; 5879 (void)dos_expandpath(gap, buf, len + 1, flags, TRUE); 5880 --stardepth; 5881 } 5882 5883 STRCPY(buf + len, path_end); 5884 if (mch_has_exp_wildcard(path_end)) 5885 { 5886 /* need to expand another component of the path */ 5887 /* remove backslashes for the remaining components only */ 5888 (void)dos_expandpath(gap, buf, len + 1, flags, FALSE); 5889 } 5890 else 5891 { 5892 /* no more wildcards, check if there is a match */ 5893 /* remove backslashes for the remaining components only */ 5894 if (*path_end != 0) 5895 backslash_halve(buf + len + 1); 5896 if (mch_getperm(buf) >= 0) /* add existing file */ 5897 addfile(gap, buf, flags); 5898 } 5899 } 5900 5901 if (wn != NULL) 5902 { 5903 vim_free(p); 5904 ok = FindNextFileW(hFind, &wfb); 5905 } 5906 else 5907 ok = FindNextFile(hFind, &fb); 5908 5909 /* If no more matches and no match was used, try expanding the name 5910 * itself. Finds the long name of a short filename. */ 5911 if (!ok && matchname != NULL && gap->ga_len == start_len) 5912 { 5913 STRCPY(s, matchname); 5914 FindClose(hFind); 5915 if (wn != NULL) 5916 { 5917 vim_free(wn); 5918 wn = enc_to_utf16(buf, NULL); 5919 if (wn != NULL) 5920 hFind = FindFirstFileW(wn, &wfb); 5921 } 5922 if (wn == NULL) 5923 hFind = FindFirstFile((LPCSTR)buf, &fb); 5924 ok = (hFind != INVALID_HANDLE_VALUE); 5925 VIM_CLEAR(matchname); 5926 } 5927 } 5928 5929 FindClose(hFind); 5930 vim_free(wn); 5931 vim_free(buf); 5932 vim_regfree(regmatch.regprog); 5933 vim_free(matchname); 5934 5935 matches = gap->ga_len - start_len; 5936 if (matches > 0) 5937 qsort(((char_u **)gap->ga_data) + start_len, (size_t)matches, 5938 sizeof(char_u *), pstrcmp); 5939 return matches; 5940 } 5941 5942 int 5943 mch_expandpath( 5944 garray_T *gap, 5945 char_u *path, 5946 int flags) /* EW_* flags */ 5947 { 5948 return dos_expandpath(gap, path, 0, flags, FALSE); 5949 } 5950 # endif /* WIN3264 */ 5951 5952 #if (defined(UNIX) && !defined(VMS)) || defined(USE_UNIXFILENAME) \ 5953 || defined(PROTO) 5954 /* 5955 * Unix style wildcard expansion code. 5956 * It's here because it's used both for Unix and Mac. 5957 */ 5958 static int 5959 pstrcmp(const void *a, const void *b) 5960 { 5961 return (pathcmp(*(char **)a, *(char **)b, -1)); 5962 } 5963 5964 /* 5965 * Recursively expand one path component into all matching files and/or 5966 * directories. Adds matches to "gap". Handles "*", "?", "[a-z]", "**", etc. 5967 * "path" has backslashes before chars that are not to be expanded, starting 5968 * at "path + wildoff". 5969 * Return the number of matches found. 5970 * NOTE: much of this is identical to dos_expandpath(), keep in sync! 5971 */ 5972 int 5973 unix_expandpath( 5974 garray_T *gap, 5975 char_u *path, 5976 int wildoff, 5977 int flags, /* EW_* flags */ 5978 int didstar) /* expanded "**" once already */ 5979 { 5980 char_u *buf; 5981 char_u *path_end; 5982 char_u *p, *s, *e; 5983 int start_len = gap->ga_len; 5984 char_u *pat; 5985 regmatch_T regmatch; 5986 int starts_with_dot; 5987 int matches; 5988 int len; 5989 int starstar = FALSE; 5990 static int stardepth = 0; /* depth for "**" expansion */ 5991 5992 DIR *dirp; 5993 struct dirent *dp; 5994 5995 /* Expanding "**" may take a long time, check for CTRL-C. */ 5996 if (stardepth > 0) 5997 { 5998 ui_breakcheck(); 5999 if (got_int) 6000 return 0; 6001 } 6002 6003 /* make room for file name */ 6004 buf = alloc((int)STRLEN(path) + BASENAMELEN + 5); 6005 if (buf == NULL) 6006 return 0; 6007 6008 /* 6009 * Find the first part in the path name that contains a wildcard. 6010 * When EW_ICASE is set every letter is considered to be a wildcard. 6011 * Copy it into "buf", including the preceding characters. 6012 */ 6013 p = buf; 6014 s = buf; 6015 e = NULL; 6016 path_end = path; 6017 while (*path_end != NUL) 6018 { 6019 /* May ignore a wildcard that has a backslash before it; it will 6020 * be removed by rem_backslash() or file_pat_to_reg_pat() below. */ 6021 if (path_end >= path + wildoff && rem_backslash(path_end)) 6022 *p++ = *path_end++; 6023 else if (*path_end == '/') 6024 { 6025 if (e != NULL) 6026 break; 6027 s = p + 1; 6028 } 6029 else if (path_end >= path + wildoff 6030 && (vim_strchr((char_u *)"*?[{~$", *path_end) != NULL 6031 || (!p_fic && (flags & EW_ICASE) 6032 && isalpha(PTR2CHAR(path_end))))) 6033 e = p; 6034 if (has_mbyte) 6035 { 6036 len = (*mb_ptr2len)(path_end); 6037 STRNCPY(p, path_end, len); 6038 p += len; 6039 path_end += len; 6040 } 6041 else 6042 *p++ = *path_end++; 6043 } 6044 e = p; 6045 *e = NUL; 6046 6047 /* Now we have one wildcard component between "s" and "e". */ 6048 /* Remove backslashes between "wildoff" and the start of the wildcard 6049 * component. */ 6050 for (p = buf + wildoff; p < s; ++p) 6051 if (rem_backslash(p)) 6052 { 6053 STRMOVE(p, p + 1); 6054 --e; 6055 --s; 6056 } 6057 6058 /* Check for "**" between "s" and "e". */ 6059 for (p = s; p < e; ++p) 6060 if (p[0] == '*' && p[1] == '*') 6061 starstar = TRUE; 6062 6063 /* convert the file pattern to a regexp pattern */ 6064 starts_with_dot = *s == '.'; 6065 pat = file_pat_to_reg_pat(s, e, NULL, FALSE); 6066 if (pat == NULL) 6067 { 6068 vim_free(buf); 6069 return 0; 6070 } 6071 6072 /* compile the regexp into a program */ 6073 if (flags & EW_ICASE) 6074 regmatch.rm_ic = TRUE; /* 'wildignorecase' set */ 6075 else 6076 regmatch.rm_ic = p_fic; /* ignore case when 'fileignorecase' is set */ 6077 if (flags & (EW_NOERROR | EW_NOTWILD)) 6078 ++emsg_silent; 6079 regmatch.regprog = vim_regcomp(pat, RE_MAGIC); 6080 if (flags & (EW_NOERROR | EW_NOTWILD)) 6081 --emsg_silent; 6082 vim_free(pat); 6083 6084 if (regmatch.regprog == NULL && (flags & EW_NOTWILD) == 0) 6085 { 6086 vim_free(buf); 6087 return 0; 6088 } 6089 6090 /* If "**" is by itself, this is the first time we encounter it and more 6091 * is following then find matches without any directory. */ 6092 if (!didstar && stardepth < 100 && starstar && e - s == 2 6093 && *path_end == '/') 6094 { 6095 STRCPY(s, path_end + 1); 6096 ++stardepth; 6097 (void)unix_expandpath(gap, buf, (int)(s - buf), flags, TRUE); 6098 --stardepth; 6099 } 6100 6101 /* open the directory for scanning */ 6102 *s = NUL; 6103 dirp = opendir(*buf == NUL ? "." : (char *)buf); 6104 6105 /* Find all matching entries */ 6106 if (dirp != NULL) 6107 { 6108 for (;;) 6109 { 6110 dp = readdir(dirp); 6111 if (dp == NULL) 6112 break; 6113 if ((dp->d_name[0] != '.' || starts_with_dot 6114 || ((flags & EW_DODOT) 6115 && dp->d_name[1] != NUL 6116 && (dp->d_name[1] != '.' || dp->d_name[2] != NUL))) 6117 && ((regmatch.regprog != NULL && vim_regexec(®match, 6118 (char_u *)dp->d_name, (colnr_T)0)) 6119 || ((flags & EW_NOTWILD) 6120 && fnamencmp(path + (s - buf), dp->d_name, e - s) == 0))) 6121 { 6122 STRCPY(s, dp->d_name); 6123 len = STRLEN(buf); 6124 6125 if (starstar && stardepth < 100) 6126 { 6127 /* For "**" in the pattern first go deeper in the tree to 6128 * find matches. */ 6129 STRCPY(buf + len, "/**"); 6130 STRCPY(buf + len + 3, path_end); 6131 ++stardepth; 6132 (void)unix_expandpath(gap, buf, len + 1, flags, TRUE); 6133 --stardepth; 6134 } 6135 6136 STRCPY(buf + len, path_end); 6137 if (mch_has_exp_wildcard(path_end)) /* handle more wildcards */ 6138 { 6139 /* need to expand another component of the path */ 6140 /* remove backslashes for the remaining components only */ 6141 (void)unix_expandpath(gap, buf, len + 1, flags, FALSE); 6142 } 6143 else 6144 { 6145 stat_T sb; 6146 6147 /* no more wildcards, check if there is a match */ 6148 /* remove backslashes for the remaining components only */ 6149 if (*path_end != NUL) 6150 backslash_halve(buf + len + 1); 6151 /* add existing file or symbolic link */ 6152 if ((flags & EW_ALLLINKS) ? mch_lstat((char *)buf, &sb) >= 0 6153 : mch_getperm(buf) >= 0) 6154 { 6155 #ifdef MACOS_CONVERT 6156 size_t precomp_len = STRLEN(buf)+1; 6157 char_u *precomp_buf = 6158 mac_precompose_path(buf, precomp_len, &precomp_len); 6159 6160 if (precomp_buf) 6161 { 6162 mch_memmove(buf, precomp_buf, precomp_len); 6163 vim_free(precomp_buf); 6164 } 6165 #endif 6166 addfile(gap, buf, flags); 6167 } 6168 } 6169 } 6170 } 6171 6172 closedir(dirp); 6173 } 6174 6175 vim_free(buf); 6176 vim_regfree(regmatch.regprog); 6177 6178 matches = gap->ga_len - start_len; 6179 if (matches > 0) 6180 qsort(((char_u **)gap->ga_data) + start_len, matches, 6181 sizeof(char_u *), pstrcmp); 6182 return matches; 6183 } 6184 #endif 6185 6186 #if defined(FEAT_SEARCHPATH) 6187 /* 6188 * Moves "*psep" back to the previous path separator in "path". 6189 * Returns FAIL is "*psep" ends up at the beginning of "path". 6190 */ 6191 static int 6192 find_previous_pathsep(char_u *path, char_u **psep) 6193 { 6194 /* skip the current separator */ 6195 if (*psep > path && vim_ispathsep(**psep)) 6196 --*psep; 6197 6198 /* find the previous separator */ 6199 while (*psep > path) 6200 { 6201 if (vim_ispathsep(**psep)) 6202 return OK; 6203 MB_PTR_BACK(path, *psep); 6204 } 6205 6206 return FAIL; 6207 } 6208 6209 /* 6210 * Returns TRUE if "maybe_unique" is unique wrt other_paths in "gap". 6211 * "maybe_unique" is the end portion of "((char_u **)gap->ga_data)[i]". 6212 */ 6213 static int 6214 is_unique(char_u *maybe_unique, garray_T *gap, int i) 6215 { 6216 int j; 6217 int candidate_len; 6218 int other_path_len; 6219 char_u **other_paths = (char_u **)gap->ga_data; 6220 char_u *rival; 6221 6222 for (j = 0; j < gap->ga_len; j++) 6223 { 6224 if (j == i) 6225 continue; /* don't compare it with itself */ 6226 6227 candidate_len = (int)STRLEN(maybe_unique); 6228 other_path_len = (int)STRLEN(other_paths[j]); 6229 if (other_path_len < candidate_len) 6230 continue; /* it's different when it's shorter */ 6231 6232 rival = other_paths[j] + other_path_len - candidate_len; 6233 if (fnamecmp(maybe_unique, rival) == 0 6234 && (rival == other_paths[j] || vim_ispathsep(*(rival - 1)))) 6235 return FALSE; /* match */ 6236 } 6237 6238 return TRUE; /* no match found */ 6239 } 6240 6241 /* 6242 * Split the 'path' option into an array of strings in garray_T. Relative 6243 * paths are expanded to their equivalent fullpath. This includes the "." 6244 * (relative to current buffer directory) and empty path (relative to current 6245 * directory) notations. 6246 * 6247 * TODO: handle upward search (;) and path limiter (**N) notations by 6248 * expanding each into their equivalent path(s). 6249 */ 6250 static void 6251 expand_path_option(char_u *curdir, garray_T *gap) 6252 { 6253 char_u *path_option = *curbuf->b_p_path == NUL 6254 ? p_path : curbuf->b_p_path; 6255 char_u *buf; 6256 char_u *p; 6257 int len; 6258 6259 if ((buf = alloc((int)MAXPATHL)) == NULL) 6260 return; 6261 6262 while (*path_option != NUL) 6263 { 6264 copy_option_part(&path_option, buf, MAXPATHL, " ,"); 6265 6266 if (buf[0] == '.' && (buf[1] == NUL || vim_ispathsep(buf[1]))) 6267 { 6268 /* Relative to current buffer: 6269 * "/path/file" + "." -> "/path/" 6270 * "/path/file" + "./subdir" -> "/path/subdir" */ 6271 if (curbuf->b_ffname == NULL) 6272 continue; 6273 p = gettail(curbuf->b_ffname); 6274 len = (int)(p - curbuf->b_ffname); 6275 if (len + (int)STRLEN(buf) >= MAXPATHL) 6276 continue; 6277 if (buf[1] == NUL) 6278 buf[len] = NUL; 6279 else 6280 STRMOVE(buf + len, buf + 2); 6281 mch_memmove(buf, curbuf->b_ffname, len); 6282 simplify_filename(buf); 6283 } 6284 else if (buf[0] == NUL) 6285 /* relative to current directory */ 6286 STRCPY(buf, curdir); 6287 else if (path_with_url(buf)) 6288 /* URL can't be used here */ 6289 continue; 6290 else if (!mch_isFullName(buf)) 6291 { 6292 /* Expand relative path to their full path equivalent */ 6293 len = (int)STRLEN(curdir); 6294 if (len + (int)STRLEN(buf) + 3 > MAXPATHL) 6295 continue; 6296 STRMOVE(buf + len + 1, buf); 6297 STRCPY(buf, curdir); 6298 buf[len] = PATHSEP; 6299 simplify_filename(buf); 6300 } 6301 6302 if (ga_grow(gap, 1) == FAIL) 6303 break; 6304 6305 # if defined(MSWIN) 6306 /* Avoid the path ending in a backslash, it fails when a comma is 6307 * appended. */ 6308 len = (int)STRLEN(buf); 6309 if (buf[len - 1] == '\\') 6310 buf[len - 1] = '/'; 6311 # endif 6312 6313 p = vim_strsave(buf); 6314 if (p == NULL) 6315 break; 6316 ((char_u **)gap->ga_data)[gap->ga_len++] = p; 6317 } 6318 6319 vim_free(buf); 6320 } 6321 6322 /* 6323 * Returns a pointer to the file or directory name in "fname" that matches the 6324 * longest path in "ga"p, or NULL if there is no match. For example: 6325 * 6326 * path: /foo/bar/baz 6327 * fname: /foo/bar/baz/quux.txt 6328 * returns: ^this 6329 */ 6330 static char_u * 6331 get_path_cutoff(char_u *fname, garray_T *gap) 6332 { 6333 int i; 6334 int maxlen = 0; 6335 char_u **path_part = (char_u **)gap->ga_data; 6336 char_u *cutoff = NULL; 6337 6338 for (i = 0; i < gap->ga_len; i++) 6339 { 6340 int j = 0; 6341 6342 while ((fname[j] == path_part[i][j] 6343 # if defined(MSWIN) 6344 || (vim_ispathsep(fname[j]) && vim_ispathsep(path_part[i][j])) 6345 #endif 6346 ) && fname[j] != NUL && path_part[i][j] != NUL) 6347 j++; 6348 if (j > maxlen) 6349 { 6350 maxlen = j; 6351 cutoff = &fname[j]; 6352 } 6353 } 6354 6355 /* skip to the file or directory name */ 6356 if (cutoff != NULL) 6357 while (vim_ispathsep(*cutoff)) 6358 MB_PTR_ADV(cutoff); 6359 6360 return cutoff; 6361 } 6362 6363 /* 6364 * Sorts, removes duplicates and modifies all the fullpath names in "gap" so 6365 * that they are unique with respect to each other while conserving the part 6366 * that matches the pattern. Beware, this is at least O(n^2) wrt "gap->ga_len". 6367 */ 6368 static void 6369 uniquefy_paths(garray_T *gap, char_u *pattern) 6370 { 6371 int i; 6372 int len; 6373 char_u **fnames = (char_u **)gap->ga_data; 6374 int sort_again = FALSE; 6375 char_u *pat; 6376 char_u *file_pattern; 6377 char_u *curdir; 6378 regmatch_T regmatch; 6379 garray_T path_ga; 6380 char_u **in_curdir = NULL; 6381 char_u *short_name; 6382 6383 remove_duplicates(gap); 6384 ga_init2(&path_ga, (int)sizeof(char_u *), 1); 6385 6386 /* 6387 * We need to prepend a '*' at the beginning of file_pattern so that the 6388 * regex matches anywhere in the path. FIXME: is this valid for all 6389 * possible patterns? 6390 */ 6391 len = (int)STRLEN(pattern); 6392 file_pattern = alloc(len + 2); 6393 if (file_pattern == NULL) 6394 return; 6395 file_pattern[0] = '*'; 6396 file_pattern[1] = NUL; 6397 STRCAT(file_pattern, pattern); 6398 pat = file_pat_to_reg_pat(file_pattern, NULL, NULL, TRUE); 6399 vim_free(file_pattern); 6400 if (pat == NULL) 6401 return; 6402 6403 regmatch.rm_ic = TRUE; /* always ignore case */ 6404 regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); 6405 vim_free(pat); 6406 if (regmatch.regprog == NULL) 6407 return; 6408 6409 if ((curdir = alloc((int)(MAXPATHL))) == NULL) 6410 goto theend; 6411 mch_dirname(curdir, MAXPATHL); 6412 expand_path_option(curdir, &path_ga); 6413 6414 in_curdir = (char_u **)alloc_clear(gap->ga_len * sizeof(char_u *)); 6415 if (in_curdir == NULL) 6416 goto theend; 6417 6418 for (i = 0; i < gap->ga_len && !got_int; i++) 6419 { 6420 char_u *path = fnames[i]; 6421 int is_in_curdir; 6422 char_u *dir_end = gettail_dir(path); 6423 char_u *pathsep_p; 6424 char_u *path_cutoff; 6425 6426 len = (int)STRLEN(path); 6427 is_in_curdir = fnamencmp(curdir, path, dir_end - path) == 0 6428 && curdir[dir_end - path] == NUL; 6429 if (is_in_curdir) 6430 in_curdir[i] = vim_strsave(path); 6431 6432 /* Shorten the filename while maintaining its uniqueness */ 6433 path_cutoff = get_path_cutoff(path, &path_ga); 6434 6435 /* Don't assume all files can be reached without path when search 6436 * pattern starts with star star slash, so only remove path_cutoff 6437 * when possible. */ 6438 if (pattern[0] == '*' && pattern[1] == '*' 6439 && vim_ispathsep_nocolon(pattern[2]) 6440 && path_cutoff != NULL 6441 && vim_regexec(®match, path_cutoff, (colnr_T)0) 6442 && is_unique(path_cutoff, gap, i)) 6443 { 6444 sort_again = TRUE; 6445 mch_memmove(path, path_cutoff, STRLEN(path_cutoff) + 1); 6446 } 6447 else 6448 { 6449 /* Here all files can be reached without path, so get shortest 6450 * unique path. We start at the end of the path. */ 6451 pathsep_p = path + len - 1; 6452 6453 while (find_previous_pathsep(path, &pathsep_p)) 6454 if (vim_regexec(®match, pathsep_p + 1, (colnr_T)0) 6455 && is_unique(pathsep_p + 1, gap, i) 6456 && path_cutoff != NULL && pathsep_p + 1 >= path_cutoff) 6457 { 6458 sort_again = TRUE; 6459 mch_memmove(path, pathsep_p + 1, STRLEN(pathsep_p)); 6460 break; 6461 } 6462 } 6463 6464 if (mch_isFullName(path)) 6465 { 6466 /* 6467 * Last resort: shorten relative to curdir if possible. 6468 * 'possible' means: 6469 * 1. It is under the current directory. 6470 * 2. The result is actually shorter than the original. 6471 * 6472 * Before curdir After 6473 * /foo/bar/file.txt /foo/bar ./file.txt 6474 * c:\foo\bar\file.txt c:\foo\bar .\file.txt 6475 * /file.txt / /file.txt 6476 * c:\file.txt c:\ .\file.txt 6477 */ 6478 short_name = shorten_fname(path, curdir); 6479 if (short_name != NULL && short_name > path + 1 6480 #if defined(MSWIN) 6481 /* On windows, 6482 * shorten_fname("c:\a\a.txt", "c:\a\b") 6483 * returns "\a\a.txt", which is not really the short 6484 * name, hence: */ 6485 && !vim_ispathsep(*short_name) 6486 #endif 6487 ) 6488 { 6489 STRCPY(path, "."); 6490 add_pathsep(path); 6491 STRMOVE(path + STRLEN(path), short_name); 6492 } 6493 } 6494 ui_breakcheck(); 6495 } 6496 6497 /* Shorten filenames in /in/current/directory/{filename} */ 6498 for (i = 0; i < gap->ga_len && !got_int; i++) 6499 { 6500 char_u *rel_path; 6501 char_u *path = in_curdir[i]; 6502 6503 if (path == NULL) 6504 continue; 6505 6506 /* If the {filename} is not unique, change it to ./{filename}. 6507 * Else reduce it to {filename} */ 6508 short_name = shorten_fname(path, curdir); 6509 if (short_name == NULL) 6510 short_name = path; 6511 if (is_unique(short_name, gap, i)) 6512 { 6513 STRCPY(fnames[i], short_name); 6514 continue; 6515 } 6516 6517 rel_path = alloc((int)(STRLEN(short_name) + STRLEN(PATHSEPSTR) + 2)); 6518 if (rel_path == NULL) 6519 goto theend; 6520 STRCPY(rel_path, "."); 6521 add_pathsep(rel_path); 6522 STRCAT(rel_path, short_name); 6523 6524 vim_free(fnames[i]); 6525 fnames[i] = rel_path; 6526 sort_again = TRUE; 6527 ui_breakcheck(); 6528 } 6529 6530 theend: 6531 vim_free(curdir); 6532 if (in_curdir != NULL) 6533 { 6534 for (i = 0; i < gap->ga_len; i++) 6535 vim_free(in_curdir[i]); 6536 vim_free(in_curdir); 6537 } 6538 ga_clear_strings(&path_ga); 6539 vim_regfree(regmatch.regprog); 6540 6541 if (sort_again) 6542 remove_duplicates(gap); 6543 } 6544 6545 /* 6546 * Calls globpath() with 'path' values for the given pattern and stores the 6547 * result in "gap". 6548 * Returns the total number of matches. 6549 */ 6550 static int 6551 expand_in_path( 6552 garray_T *gap, 6553 char_u *pattern, 6554 int flags) /* EW_* flags */ 6555 { 6556 char_u *curdir; 6557 garray_T path_ga; 6558 char_u *paths = NULL; 6559 int glob_flags = 0; 6560 6561 if ((curdir = alloc((unsigned)MAXPATHL)) == NULL) 6562 return 0; 6563 mch_dirname(curdir, MAXPATHL); 6564 6565 ga_init2(&path_ga, (int)sizeof(char_u *), 1); 6566 expand_path_option(curdir, &path_ga); 6567 vim_free(curdir); 6568 if (path_ga.ga_len == 0) 6569 return 0; 6570 6571 paths = ga_concat_strings(&path_ga, ","); 6572 ga_clear_strings(&path_ga); 6573 if (paths == NULL) 6574 return 0; 6575 6576 if (flags & EW_ICASE) 6577 glob_flags |= WILD_ICASE; 6578 if (flags & EW_ADDSLASH) 6579 glob_flags |= WILD_ADD_SLASH; 6580 globpath(paths, pattern, gap, glob_flags); 6581 vim_free(paths); 6582 6583 return gap->ga_len; 6584 } 6585 #endif 6586 6587 #if defined(FEAT_SEARCHPATH) || defined(FEAT_CMDL_COMPL) || defined(PROTO) 6588 /* 6589 * Sort "gap" and remove duplicate entries. "gap" is expected to contain a 6590 * list of file names in allocated memory. 6591 */ 6592 void 6593 remove_duplicates(garray_T *gap) 6594 { 6595 int i; 6596 int j; 6597 char_u **fnames = (char_u **)gap->ga_data; 6598 6599 sort_strings(fnames, gap->ga_len); 6600 for (i = gap->ga_len - 1; i > 0; --i) 6601 if (fnamecmp(fnames[i - 1], fnames[i]) == 0) 6602 { 6603 vim_free(fnames[i]); 6604 for (j = i + 1; j < gap->ga_len; ++j) 6605 fnames[j - 1] = fnames[j]; 6606 --gap->ga_len; 6607 } 6608 } 6609 #endif 6610 6611 /* 6612 * Return TRUE if "p" contains what looks like an environment variable. 6613 * Allowing for escaping. 6614 */ 6615 static int 6616 has_env_var(char_u *p) 6617 { 6618 for ( ; *p; MB_PTR_ADV(p)) 6619 { 6620 if (*p == '\\' && p[1] != NUL) 6621 ++p; 6622 else if (vim_strchr((char_u *) 6623 #if defined(MSWIN) 6624 "$%" 6625 #else 6626 "$" 6627 #endif 6628 , *p) != NULL) 6629 return TRUE; 6630 } 6631 return FALSE; 6632 } 6633 6634 #ifdef SPECIAL_WILDCHAR 6635 /* 6636 * Return TRUE if "p" contains a special wildcard character, one that Vim 6637 * cannot expand, requires using a shell. 6638 */ 6639 static int 6640 has_special_wildchar(char_u *p) 6641 { 6642 for ( ; *p; MB_PTR_ADV(p)) 6643 { 6644 /* Allow for escaping. */ 6645 if (*p == '\\' && p[1] != NUL) 6646 ++p; 6647 else if (vim_strchr((char_u *)SPECIAL_WILDCHAR, *p) != NULL) 6648 return TRUE; 6649 } 6650 return FALSE; 6651 } 6652 #endif 6653 6654 /* 6655 * Generic wildcard expansion code. 6656 * 6657 * Characters in "pat" that should not be expanded must be preceded with a 6658 * backslash. E.g., "/path\ with\ spaces/my\*star*" 6659 * 6660 * Return FAIL when no single file was found. In this case "num_file" is not 6661 * set, and "file" may contain an error message. 6662 * Return OK when some files found. "num_file" is set to the number of 6663 * matches, "file" to the array of matches. Call FreeWild() later. 6664 */ 6665 int 6666 gen_expand_wildcards( 6667 int num_pat, /* number of input patterns */ 6668 char_u **pat, /* array of input patterns */ 6669 int *num_file, /* resulting number of files */ 6670 char_u ***file, /* array of resulting files */ 6671 int flags) /* EW_* flags */ 6672 { 6673 int i; 6674 garray_T ga; 6675 char_u *p; 6676 static int recursive = FALSE; 6677 int add_pat; 6678 int retval = OK; 6679 #if defined(FEAT_SEARCHPATH) 6680 int did_expand_in_path = FALSE; 6681 #endif 6682 6683 /* 6684 * expand_env() is called to expand things like "~user". If this fails, 6685 * it calls ExpandOne(), which brings us back here. In this case, always 6686 * call the machine specific expansion function, if possible. Otherwise, 6687 * return FAIL. 6688 */ 6689 if (recursive) 6690 #ifdef SPECIAL_WILDCHAR 6691 return mch_expand_wildcards(num_pat, pat, num_file, file, flags); 6692 #else 6693 return FAIL; 6694 #endif 6695 6696 #ifdef SPECIAL_WILDCHAR 6697 /* 6698 * If there are any special wildcard characters which we cannot handle 6699 * here, call machine specific function for all the expansion. This 6700 * avoids starting the shell for each argument separately. 6701 * For `=expr` do use the internal function. 6702 */ 6703 for (i = 0; i < num_pat; i++) 6704 { 6705 if (has_special_wildchar(pat[i]) 6706 # ifdef VIM_BACKTICK 6707 && !(vim_backtick(pat[i]) && pat[i][1] == '=') 6708 # endif 6709 ) 6710 return mch_expand_wildcards(num_pat, pat, num_file, file, flags); 6711 } 6712 #endif 6713 6714 recursive = TRUE; 6715 6716 /* 6717 * The matching file names are stored in a growarray. Init it empty. 6718 */ 6719 ga_init2(&ga, (int)sizeof(char_u *), 30); 6720 6721 for (i = 0; i < num_pat; ++i) 6722 { 6723 add_pat = -1; 6724 p = pat[i]; 6725 6726 #ifdef VIM_BACKTICK 6727 if (vim_backtick(p)) 6728 { 6729 add_pat = expand_backtick(&ga, p, flags); 6730 if (add_pat == -1) 6731 retval = FAIL; 6732 } 6733 else 6734 #endif 6735 { 6736 /* 6737 * First expand environment variables, "~/" and "~user/". 6738 */ 6739 if (has_env_var(p) || *p == '~') 6740 { 6741 p = expand_env_save_opt(p, TRUE); 6742 if (p == NULL) 6743 p = pat[i]; 6744 #ifdef UNIX 6745 /* 6746 * On Unix, if expand_env() can't expand an environment 6747 * variable, use the shell to do that. Discard previously 6748 * found file names and start all over again. 6749 */ 6750 else if (has_env_var(p) || *p == '~') 6751 { 6752 vim_free(p); 6753 ga_clear_strings(&ga); 6754 i = mch_expand_wildcards(num_pat, pat, num_file, file, 6755 flags|EW_KEEPDOLLAR); 6756 recursive = FALSE; 6757 return i; 6758 } 6759 #endif 6760 } 6761 6762 /* 6763 * If there are wildcards: Expand file names and add each match to 6764 * the list. If there is no match, and EW_NOTFOUND is given, add 6765 * the pattern. 6766 * If there are no wildcards: Add the file name if it exists or 6767 * when EW_NOTFOUND is given. 6768 */ 6769 if (mch_has_exp_wildcard(p)) 6770 { 6771 #if defined(FEAT_SEARCHPATH) 6772 if ((flags & EW_PATH) 6773 && !mch_isFullName(p) 6774 && !(p[0] == '.' 6775 && (vim_ispathsep(p[1]) 6776 || (p[1] == '.' && vim_ispathsep(p[2])))) 6777 ) 6778 { 6779 /* :find completion where 'path' is used. 6780 * Recursiveness is OK here. */ 6781 recursive = FALSE; 6782 add_pat = expand_in_path(&ga, p, flags); 6783 recursive = TRUE; 6784 did_expand_in_path = TRUE; 6785 } 6786 else 6787 #endif 6788 add_pat = mch_expandpath(&ga, p, flags); 6789 } 6790 } 6791 6792 if (add_pat == -1 || (add_pat == 0 && (flags & EW_NOTFOUND))) 6793 { 6794 char_u *t = backslash_halve_save(p); 6795 6796 /* When EW_NOTFOUND is used, always add files and dirs. Makes 6797 * "vim c:/" work. */ 6798 if (flags & EW_NOTFOUND) 6799 addfile(&ga, t, flags | EW_DIR | EW_FILE); 6800 else 6801 addfile(&ga, t, flags); 6802 vim_free(t); 6803 } 6804 6805 #if defined(FEAT_SEARCHPATH) 6806 if (did_expand_in_path && ga.ga_len > 0 && (flags & EW_PATH)) 6807 uniquefy_paths(&ga, p); 6808 #endif 6809 if (p != pat[i]) 6810 vim_free(p); 6811 } 6812 6813 *num_file = ga.ga_len; 6814 *file = (ga.ga_data != NULL) ? (char_u **)ga.ga_data : (char_u **)""; 6815 6816 recursive = FALSE; 6817 6818 return ((flags & EW_EMPTYOK) || ga.ga_data != NULL) ? retval : FAIL; 6819 } 6820 6821 # ifdef VIM_BACKTICK 6822 6823 /* 6824 * Return TRUE if we can expand this backtick thing here. 6825 */ 6826 static int 6827 vim_backtick(char_u *p) 6828 { 6829 return (*p == '`' && *(p + 1) != NUL && *(p + STRLEN(p) - 1) == '`'); 6830 } 6831 6832 /* 6833 * Expand an item in `backticks` by executing it as a command. 6834 * Currently only works when pat[] starts and ends with a `. 6835 * Returns number of file names found, -1 if an error is encountered. 6836 */ 6837 static int 6838 expand_backtick( 6839 garray_T *gap, 6840 char_u *pat, 6841 int flags) /* EW_* flags */ 6842 { 6843 char_u *p; 6844 char_u *cmd; 6845 char_u *buffer; 6846 int cnt = 0; 6847 int i; 6848 6849 /* Create the command: lop off the backticks. */ 6850 cmd = vim_strnsave(pat + 1, (int)STRLEN(pat) - 2); 6851 if (cmd == NULL) 6852 return -1; 6853 6854 #ifdef FEAT_EVAL 6855 if (*cmd == '=') /* `={expr}`: Expand expression */ 6856 buffer = eval_to_string(cmd + 1, &p, TRUE); 6857 else 6858 #endif 6859 buffer = get_cmd_output(cmd, NULL, 6860 (flags & EW_SILENT) ? SHELL_SILENT : 0, NULL); 6861 vim_free(cmd); 6862 if (buffer == NULL) 6863 return -1; 6864 6865 cmd = buffer; 6866 while (*cmd != NUL) 6867 { 6868 cmd = skipwhite(cmd); /* skip over white space */ 6869 p = cmd; 6870 while (*p != NUL && *p != '\r' && *p != '\n') /* skip over entry */ 6871 ++p; 6872 /* add an entry if it is not empty */ 6873 if (p > cmd) 6874 { 6875 i = *p; 6876 *p = NUL; 6877 addfile(gap, cmd, flags); 6878 *p = i; 6879 ++cnt; 6880 } 6881 cmd = p; 6882 while (*cmd != NUL && (*cmd == '\r' || *cmd == '\n')) 6883 ++cmd; 6884 } 6885 6886 vim_free(buffer); 6887 return cnt; 6888 } 6889 # endif /* VIM_BACKTICK */ 6890 6891 /* 6892 * Add a file to a file list. Accepted flags: 6893 * EW_DIR add directories 6894 * EW_FILE add files 6895 * EW_EXEC add executable files 6896 * EW_NOTFOUND add even when it doesn't exist 6897 * EW_ADDSLASH add slash after directory name 6898 * EW_ALLLINKS add symlink also when the referred file does not exist 6899 */ 6900 void 6901 addfile( 6902 garray_T *gap, 6903 char_u *f, /* filename */ 6904 int flags) 6905 { 6906 char_u *p; 6907 int isdir; 6908 stat_T sb; 6909 6910 /* if the file/dir/link doesn't exist, may not add it */ 6911 if (!(flags & EW_NOTFOUND) && ((flags & EW_ALLLINKS) 6912 ? mch_lstat((char *)f, &sb) < 0 : mch_getperm(f) < 0)) 6913 return; 6914 6915 #ifdef FNAME_ILLEGAL 6916 /* if the file/dir contains illegal characters, don't add it */ 6917 if (vim_strpbrk(f, (char_u *)FNAME_ILLEGAL) != NULL) 6918 return; 6919 #endif 6920 6921 isdir = mch_isdir(f); 6922 if ((isdir && !(flags & EW_DIR)) || (!isdir && !(flags & EW_FILE))) 6923 return; 6924 6925 /* If the file isn't executable, may not add it. Do accept directories. 6926 * When invoked from expand_shellcmd() do not use $PATH. */ 6927 if (!isdir && (flags & EW_EXEC) 6928 && !mch_can_exe(f, NULL, !(flags & EW_SHELLCMD))) 6929 return; 6930 6931 /* Make room for another item in the file list. */ 6932 if (ga_grow(gap, 1) == FAIL) 6933 return; 6934 6935 p = alloc((unsigned)(STRLEN(f) + 1 + isdir)); 6936 if (p == NULL) 6937 return; 6938 6939 STRCPY(p, f); 6940 #ifdef BACKSLASH_IN_FILENAME 6941 slash_adjust(p); 6942 #endif 6943 /* 6944 * Append a slash or backslash after directory names if none is present. 6945 */ 6946 #ifndef DONT_ADD_PATHSEP_TO_DIR 6947 if (isdir && (flags & EW_ADDSLASH)) 6948 add_pathsep(p); 6949 #endif 6950 ((char_u **)gap->ga_data)[gap->ga_len++] = p; 6951 } 6952 #endif /* !NO_EXPANDPATH */ 6953 6954 #if defined(VIM_BACKTICK) || defined(FEAT_EVAL) || defined(PROTO) 6955 6956 #ifndef SEEK_SET 6957 # define SEEK_SET 0 6958 #endif 6959 #ifndef SEEK_END 6960 # define SEEK_END 2 6961 #endif 6962 6963 /* 6964 * Get the stdout of an external command. 6965 * If "ret_len" is NULL replace NUL characters with NL. When "ret_len" is not 6966 * NULL store the length there. 6967 * Returns an allocated string, or NULL for error. 6968 */ 6969 char_u * 6970 get_cmd_output( 6971 char_u *cmd, 6972 char_u *infile, /* optional input file name */ 6973 int flags, /* can be SHELL_SILENT */ 6974 int *ret_len) 6975 { 6976 char_u *tempname; 6977 char_u *command; 6978 char_u *buffer = NULL; 6979 int len; 6980 int i = 0; 6981 FILE *fd; 6982 6983 if (check_restricted() || check_secure()) 6984 return NULL; 6985 6986 /* get a name for the temp file */ 6987 if ((tempname = vim_tempname('o', FALSE)) == NULL) 6988 { 6989 emsg(_(e_notmp)); 6990 return NULL; 6991 } 6992 6993 /* Add the redirection stuff */ 6994 command = make_filter_cmd(cmd, infile, tempname); 6995 if (command == NULL) 6996 goto done; 6997 6998 /* 6999 * Call the shell to execute the command (errors are ignored). 7000 * Don't check timestamps here. 7001 */ 7002 ++no_check_timestamps; 7003 call_shell(command, SHELL_DOOUT | SHELL_EXPAND | flags); 7004 --no_check_timestamps; 7005 7006 vim_free(command); 7007 7008 /* 7009 * read the names from the file into memory 7010 */ 7011 # ifdef VMS 7012 /* created temporary file is not always readable as binary */ 7013 fd = mch_fopen((char *)tempname, "r"); 7014 # else 7015 fd = mch_fopen((char *)tempname, READBIN); 7016 # endif 7017 7018 if (fd == NULL) 7019 { 7020 semsg(_(e_notopen), tempname); 7021 goto done; 7022 } 7023 7024 fseek(fd, 0L, SEEK_END); 7025 len = ftell(fd); /* get size of temp file */ 7026 fseek(fd, 0L, SEEK_SET); 7027 7028 buffer = alloc(len + 1); 7029 if (buffer != NULL) 7030 i = (int)fread((char *)buffer, (size_t)1, (size_t)len, fd); 7031 fclose(fd); 7032 mch_remove(tempname); 7033 if (buffer == NULL) 7034 goto done; 7035 #ifdef VMS 7036 len = i; /* VMS doesn't give us what we asked for... */ 7037 #endif 7038 if (i != len) 7039 { 7040 semsg(_(e_notread), tempname); 7041 VIM_CLEAR(buffer); 7042 } 7043 else if (ret_len == NULL) 7044 { 7045 /* Change NUL into SOH, otherwise the string is truncated. */ 7046 for (i = 0; i < len; ++i) 7047 if (buffer[i] == NUL) 7048 buffer[i] = 1; 7049 7050 buffer[len] = NUL; /* make sure the buffer is terminated */ 7051 } 7052 else 7053 *ret_len = len; 7054 7055 done: 7056 vim_free(tempname); 7057 return buffer; 7058 } 7059 #endif 7060 7061 /* 7062 * Free the list of files returned by expand_wildcards() or other expansion 7063 * functions. 7064 */ 7065 void 7066 FreeWild(int count, char_u **files) 7067 { 7068 if (count <= 0 || files == NULL) 7069 return; 7070 while (count--) 7071 vim_free(files[count]); 7072 vim_free(files); 7073 } 7074 7075 /* 7076 * Return TRUE when need to go to Insert mode because of 'insertmode'. 7077 * Don't do this when still processing a command or a mapping. 7078 * Don't do this when inside a ":normal" command. 7079 */ 7080 int 7081 goto_im(void) 7082 { 7083 return (p_im && stuff_empty() && typebuf_typed()); 7084 } 7085 7086 /* 7087 * Returns the isolated name of the shell in allocated memory: 7088 * - Skip beyond any path. E.g., "/usr/bin/csh -f" -> "csh -f". 7089 * - Remove any argument. E.g., "csh -f" -> "csh". 7090 * But don't allow a space in the path, so that this works: 7091 * "/usr/bin/csh --rcfile ~/.cshrc" 7092 * But don't do that for Windows, it's common to have a space in the path. 7093 */ 7094 char_u * 7095 get_isolated_shell_name(void) 7096 { 7097 char_u *p; 7098 7099 #ifdef WIN3264 7100 p = gettail(p_sh); 7101 p = vim_strnsave(p, (int)(skiptowhite(p) - p)); 7102 #else 7103 p = skiptowhite(p_sh); 7104 if (*p == NUL) 7105 { 7106 /* No white space, use the tail. */ 7107 p = vim_strsave(gettail(p_sh)); 7108 } 7109 else 7110 { 7111 char_u *p1, *p2; 7112 7113 /* Find the last path separator before the space. */ 7114 p1 = p_sh; 7115 for (p2 = p_sh; p2 < p; MB_PTR_ADV(p2)) 7116 if (vim_ispathsep(*p2)) 7117 p1 = p2 + 1; 7118 p = vim_strnsave(p1, (int)(p - p1)); 7119 } 7120 #endif 7121 return p; 7122 } 7123