1 /* vi:set ts=8 sts=4 sw=4: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * misc2.c: Various functions. 12 */ 13 #include "vim.h" 14 15 static char_u *username = NULL; /* cached result of mch_get_user_name() */ 16 17 static char_u *ff_expand_buffer = NULL; /* used for expanding filenames */ 18 19 #if defined(FEAT_VIRTUALEDIT) || defined(PROTO) 20 static int coladvance2 __ARGS((pos_T *pos, int addspaces, int finetune, colnr_T wcol)); 21 22 /* 23 * Return TRUE if in the current mode we need to use virtual. 24 */ 25 int 26 virtual_active() 27 { 28 /* While an operator is being executed we return "virtual_op", because 29 * VIsual_active has already been reset, thus we can't check for "block" 30 * being used. */ 31 if (virtual_op != MAYBE) 32 return virtual_op; 33 return (ve_flags == VE_ALL 34 || ((ve_flags & VE_BLOCK) && VIsual_active && VIsual_mode == Ctrl_V) 35 || ((ve_flags & VE_INSERT) && (State & INSERT))); 36 } 37 38 /* 39 * Get the screen position of the cursor. 40 */ 41 int 42 getviscol() 43 { 44 colnr_T x; 45 46 getvvcol(curwin, &curwin->w_cursor, &x, NULL, NULL); 47 return (int)x; 48 } 49 50 /* 51 * Get the screen position of character col with a coladd in the cursor line. 52 */ 53 int 54 getviscol2(col, coladd) 55 colnr_T col; 56 colnr_T coladd; 57 { 58 colnr_T x; 59 pos_T pos; 60 61 pos.lnum = curwin->w_cursor.lnum; 62 pos.col = col; 63 pos.coladd = coladd; 64 getvvcol(curwin, &pos, &x, NULL, NULL); 65 return (int)x; 66 } 67 68 /* 69 * Go to column "wcol", and add/insert white space as necessary to get the 70 * cursor in that column. 71 * The caller must have saved the cursor line for undo! 72 */ 73 int 74 coladvance_force(wcol) 75 colnr_T wcol; 76 { 77 int rc = coladvance2(&curwin->w_cursor, TRUE, FALSE, wcol); 78 79 if (wcol == MAXCOL) 80 curwin->w_valid &= ~VALID_VIRTCOL; 81 else 82 { 83 /* Virtcol is valid */ 84 curwin->w_valid |= VALID_VIRTCOL; 85 curwin->w_virtcol = wcol; 86 } 87 return rc; 88 } 89 #endif 90 91 /* 92 * Try to advance the Cursor to the specified screen column. 93 * If virtual editing: fine tune the cursor position. 94 * Note that all virtual positions off the end of a line should share 95 * a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)), 96 * beginning at coladd 0. 97 * 98 * return OK if desired column is reached, FAIL if not 99 */ 100 int 101 coladvance(wcol) 102 colnr_T wcol; 103 { 104 int rc = getvpos(&curwin->w_cursor, wcol); 105 106 if (wcol == MAXCOL || rc == FAIL) 107 curwin->w_valid &= ~VALID_VIRTCOL; 108 else if (*ml_get_cursor() != TAB) 109 { 110 /* Virtcol is valid when not on a TAB */ 111 curwin->w_valid |= VALID_VIRTCOL; 112 curwin->w_virtcol = wcol; 113 } 114 return rc; 115 } 116 117 /* 118 * Return in "pos" the position of the cursor advanced to screen column "wcol". 119 * return OK if desired column is reached, FAIL if not 120 */ 121 int 122 getvpos(pos, wcol) 123 pos_T *pos; 124 colnr_T wcol; 125 { 126 #ifdef FEAT_VIRTUALEDIT 127 return coladvance2(pos, FALSE, virtual_active(), wcol); 128 } 129 130 static int 131 coladvance2(pos, addspaces, finetune, wcol) 132 pos_T *pos; 133 int addspaces; /* change the text to achieve our goal? */ 134 int finetune; /* change char offset for the exact column */ 135 colnr_T wcol; /* column to move to */ 136 { 137 #endif 138 int idx; 139 char_u *ptr; 140 char_u *line; 141 colnr_T col = 0; 142 int csize = 0; 143 int one_more; 144 #ifdef FEAT_LINEBREAK 145 int head = 0; 146 #endif 147 148 one_more = (State & INSERT) 149 || restart_edit != NUL 150 || (VIsual_active && *p_sel != 'o') 151 #ifdef FEAT_VIRTUALEDIT 152 || ((ve_flags & VE_ONEMORE) && wcol < MAXCOL) 153 #endif 154 ; 155 line = ml_get_buf(curbuf, pos->lnum, FALSE); 156 157 if (wcol >= MAXCOL) 158 { 159 idx = (int)STRLEN(line) - 1 + one_more; 160 col = wcol; 161 162 #ifdef FEAT_VIRTUALEDIT 163 if ((addspaces || finetune) && !VIsual_active) 164 { 165 curwin->w_curswant = linetabsize(line) + one_more; 166 if (curwin->w_curswant > 0) 167 --curwin->w_curswant; 168 } 169 #endif 170 } 171 else 172 { 173 #ifdef FEAT_VIRTUALEDIT 174 int width = W_WIDTH(curwin) - win_col_off(curwin); 175 176 if (finetune 177 && curwin->w_p_wrap 178 # ifdef FEAT_VERTSPLIT 179 && curwin->w_width != 0 180 # endif 181 && wcol >= (colnr_T)width) 182 { 183 csize = linetabsize(line); 184 if (csize > 0) 185 csize--; 186 187 if (wcol / width > (colnr_T)csize / width 188 && ((State & INSERT) == 0 || (int)wcol > csize + 1)) 189 { 190 /* In case of line wrapping don't move the cursor beyond the 191 * right screen edge. In Insert mode allow going just beyond 192 * the last character (like what happens when typing and 193 * reaching the right window edge). */ 194 wcol = (csize / width + 1) * width - 1; 195 } 196 } 197 #endif 198 199 ptr = line; 200 while (col <= wcol && *ptr != NUL) 201 { 202 /* Count a tab for what it's worth (if list mode not on) */ 203 #ifdef FEAT_LINEBREAK 204 csize = win_lbr_chartabsize(curwin, line, ptr, col, &head); 205 mb_ptr_adv(ptr); 206 #else 207 csize = lbr_chartabsize_adv(line, &ptr, col); 208 #endif 209 col += csize; 210 } 211 idx = (int)(ptr - line); 212 /* 213 * Handle all the special cases. The virtual_active() check 214 * is needed to ensure that a virtual position off the end of 215 * a line has the correct indexing. The one_more comparison 216 * replaces an explicit add of one_more later on. 217 */ 218 if (col > wcol || (!virtual_active() && one_more == 0)) 219 { 220 idx -= 1; 221 # ifdef FEAT_LINEBREAK 222 /* Don't count the chars from 'showbreak'. */ 223 csize -= head; 224 # endif 225 col -= csize; 226 } 227 228 #ifdef FEAT_VIRTUALEDIT 229 if (virtual_active() 230 && addspaces 231 && ((col != wcol && col != wcol + 1) || csize > 1)) 232 { 233 /* 'virtualedit' is set: The difference between wcol and col is 234 * filled with spaces. */ 235 236 if (line[idx] == NUL) 237 { 238 /* Append spaces */ 239 int correct = wcol - col; 240 char_u *newline = alloc(idx + correct + 1); 241 int t; 242 243 if (newline == NULL) 244 return FAIL; 245 246 for (t = 0; t < idx; ++t) 247 newline[t] = line[t]; 248 249 for (t = 0; t < correct; ++t) 250 newline[t + idx] = ' '; 251 252 newline[idx + correct] = NUL; 253 254 ml_replace(pos->lnum, newline, FALSE); 255 changed_bytes(pos->lnum, (colnr_T)idx); 256 idx += correct; 257 col = wcol; 258 } 259 else 260 { 261 /* Break a tab */ 262 int linelen = (int)STRLEN(line); 263 int correct = wcol - col - csize + 1; /* negative!! */ 264 char_u *newline; 265 int t, s = 0; 266 int v; 267 268 if (-correct > csize) 269 return FAIL; 270 271 newline = alloc(linelen + csize); 272 if (newline == NULL) 273 return FAIL; 274 275 for (t = 0; t < linelen; t++) 276 { 277 if (t != idx) 278 newline[s++] = line[t]; 279 else 280 for (v = 0; v < csize; v++) 281 newline[s++] = ' '; 282 } 283 284 newline[linelen + csize - 1] = NUL; 285 286 ml_replace(pos->lnum, newline, FALSE); 287 changed_bytes(pos->lnum, idx); 288 idx += (csize - 1 + correct); 289 col += correct; 290 } 291 } 292 #endif 293 } 294 295 if (idx < 0) 296 pos->col = 0; 297 else 298 pos->col = idx; 299 300 #ifdef FEAT_VIRTUALEDIT 301 pos->coladd = 0; 302 303 if (finetune) 304 { 305 if (wcol == MAXCOL) 306 { 307 /* The width of the last character is used to set coladd. */ 308 if (!one_more) 309 { 310 colnr_T scol, ecol; 311 312 getvcol(curwin, pos, &scol, NULL, &ecol); 313 pos->coladd = ecol - scol; 314 } 315 } 316 else 317 { 318 int b = (int)wcol - (int)col; 319 320 /* The difference between wcol and col is used to set coladd. */ 321 if (b > 0 && b < (MAXCOL - 2 * W_WIDTH(curwin))) 322 pos->coladd = b; 323 324 col += b; 325 } 326 } 327 #endif 328 329 #ifdef FEAT_MBYTE 330 /* prevent from moving onto a trail byte */ 331 if (has_mbyte) 332 mb_adjustpos(curbuf, pos); 333 #endif 334 335 if (col < wcol) 336 return FAIL; 337 return OK; 338 } 339 340 /* 341 * Increment the cursor position. See inc() for return values. 342 */ 343 int 344 inc_cursor() 345 { 346 return inc(&curwin->w_cursor); 347 } 348 349 /* 350 * Increment the line pointer "lp" crossing line boundaries as necessary. 351 * Return 1 when going to the next line. 352 * Return 2 when moving forward onto a NUL at the end of the line). 353 * Return -1 when at the end of file. 354 * Return 0 otherwise. 355 */ 356 int 357 inc(lp) 358 pos_T *lp; 359 { 360 char_u *p = ml_get_pos(lp); 361 362 if (*p != NUL) /* still within line, move to next char (may be NUL) */ 363 { 364 #ifdef FEAT_MBYTE 365 if (has_mbyte) 366 { 367 int l = (*mb_ptr2len)(p); 368 369 lp->col += l; 370 return ((p[l] != NUL) ? 0 : 2); 371 } 372 #endif 373 lp->col++; 374 #ifdef FEAT_VIRTUALEDIT 375 lp->coladd = 0; 376 #endif 377 return ((p[1] != NUL) ? 0 : 2); 378 } 379 if (lp->lnum != curbuf->b_ml.ml_line_count) /* there is a next line */ 380 { 381 lp->col = 0; 382 lp->lnum++; 383 #ifdef FEAT_VIRTUALEDIT 384 lp->coladd = 0; 385 #endif 386 return 1; 387 } 388 return -1; 389 } 390 391 /* 392 * incl(lp): same as inc(), but skip the NUL at the end of non-empty lines 393 */ 394 int 395 incl(lp) 396 pos_T *lp; 397 { 398 int r; 399 400 if ((r = inc(lp)) >= 1 && lp->col) 401 r = inc(lp); 402 return r; 403 } 404 405 /* 406 * dec(p) 407 * 408 * Decrement the line pointer 'p' crossing line boundaries as necessary. 409 * Return 1 when crossing a line, -1 when at start of file, 0 otherwise. 410 */ 411 int 412 dec_cursor() 413 { 414 return dec(&curwin->w_cursor); 415 } 416 417 int 418 dec(lp) 419 pos_T *lp; 420 { 421 char_u *p; 422 423 #ifdef FEAT_VIRTUALEDIT 424 lp->coladd = 0; 425 #endif 426 if (lp->col > 0) /* still within line */ 427 { 428 lp->col--; 429 #ifdef FEAT_MBYTE 430 if (has_mbyte) 431 { 432 p = ml_get(lp->lnum); 433 lp->col -= (*mb_head_off)(p, p + lp->col); 434 } 435 #endif 436 return 0; 437 } 438 if (lp->lnum > 1) /* there is a prior line */ 439 { 440 lp->lnum--; 441 p = ml_get(lp->lnum); 442 lp->col = (colnr_T)STRLEN(p); 443 #ifdef FEAT_MBYTE 444 if (has_mbyte) 445 lp->col -= (*mb_head_off)(p, p + lp->col); 446 #endif 447 return 1; 448 } 449 return -1; /* at start of file */ 450 } 451 452 /* 453 * decl(lp): same as dec(), but skip the NUL at the end of non-empty lines 454 */ 455 int 456 decl(lp) 457 pos_T *lp; 458 { 459 int r; 460 461 if ((r = dec(lp)) == 1 && lp->col) 462 r = dec(lp); 463 return r; 464 } 465 466 /* 467 * Get the line number relative to the current cursor position, i.e. the 468 * difference between line number and cursor position. Only look for lines that 469 * can be visible, folded lines don't count. 470 */ 471 linenr_T 472 get_cursor_rel_lnum(wp, lnum) 473 win_T *wp; 474 linenr_T lnum; /* line number to get the result for */ 475 { 476 linenr_T cursor = wp->w_cursor.lnum; 477 linenr_T retval = 0; 478 479 #ifdef FEAT_FOLDING 480 if (hasAnyFolding(wp)) 481 { 482 if (lnum > cursor) 483 { 484 while (lnum > cursor) 485 { 486 (void)hasFoldingWin(wp, lnum, &lnum, NULL, TRUE, NULL); 487 /* if lnum and cursor are in the same fold, 488 * now lnum <= cursor */ 489 if (lnum > cursor) 490 retval++; 491 lnum--; 492 } 493 } 494 else if (lnum < cursor) 495 { 496 while (lnum < cursor) 497 { 498 (void)hasFoldingWin(wp, lnum, NULL, &lnum, TRUE, NULL); 499 /* if lnum and cursor are in the same fold, 500 * now lnum >= cursor */ 501 if (lnum < cursor) 502 retval--; 503 lnum++; 504 } 505 } 506 /* else if (lnum == cursor) 507 * retval = 0; 508 */ 509 } 510 else 511 #endif 512 retval = lnum - cursor; 513 514 return retval; 515 } 516 517 /* 518 * Make sure curwin->w_cursor.lnum is valid. 519 */ 520 void 521 check_cursor_lnum() 522 { 523 if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) 524 { 525 #ifdef FEAT_FOLDING 526 /* If there is a closed fold at the end of the file, put the cursor in 527 * its first line. Otherwise in the last line. */ 528 if (!hasFolding(curbuf->b_ml.ml_line_count, 529 &curwin->w_cursor.lnum, NULL)) 530 #endif 531 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 532 } 533 if (curwin->w_cursor.lnum <= 0) 534 curwin->w_cursor.lnum = 1; 535 } 536 537 /* 538 * Make sure curwin->w_cursor.col is valid. 539 */ 540 void 541 check_cursor_col() 542 { 543 check_cursor_col_win(curwin); 544 } 545 546 /* 547 * Make sure win->w_cursor.col is valid. 548 */ 549 void 550 check_cursor_col_win(win) 551 win_T *win; 552 { 553 colnr_T len; 554 #ifdef FEAT_VIRTUALEDIT 555 colnr_T oldcol = win->w_cursor.col; 556 colnr_T oldcoladd = win->w_cursor.col + win->w_cursor.coladd; 557 #endif 558 559 len = (colnr_T)STRLEN(ml_get_buf(win->w_buffer, win->w_cursor.lnum, FALSE)); 560 if (len == 0) 561 win->w_cursor.col = 0; 562 else if (win->w_cursor.col >= len) 563 { 564 /* Allow cursor past end-of-line when: 565 * - in Insert mode or restarting Insert mode 566 * - in Visual mode and 'selection' isn't "old" 567 * - 'virtualedit' is set */ 568 if ((State & INSERT) || restart_edit 569 || (VIsual_active && *p_sel != 'o') 570 #ifdef FEAT_VIRTUALEDIT 571 || (ve_flags & VE_ONEMORE) 572 #endif 573 || virtual_active()) 574 win->w_cursor.col = len; 575 else 576 { 577 win->w_cursor.col = len - 1; 578 #ifdef FEAT_MBYTE 579 /* Move the cursor to the head byte. */ 580 if (has_mbyte) 581 mb_adjustpos(win->w_buffer, &win->w_cursor); 582 #endif 583 } 584 } 585 else if (win->w_cursor.col < 0) 586 win->w_cursor.col = 0; 587 588 #ifdef FEAT_VIRTUALEDIT 589 /* If virtual editing is on, we can leave the cursor on the old position, 590 * only we must set it to virtual. But don't do it when at the end of the 591 * line. */ 592 if (oldcol == MAXCOL) 593 win->w_cursor.coladd = 0; 594 else if (ve_flags == VE_ALL) 595 { 596 if (oldcoladd > win->w_cursor.col) 597 win->w_cursor.coladd = oldcoladd - win->w_cursor.col; 598 else 599 /* avoid weird number when there is a miscalculation or overflow */ 600 win->w_cursor.coladd = 0; 601 } 602 #endif 603 } 604 605 /* 606 * make sure curwin->w_cursor in on a valid character 607 */ 608 void 609 check_cursor() 610 { 611 check_cursor_lnum(); 612 check_cursor_col(); 613 } 614 615 #if defined(FEAT_TEXTOBJ) || defined(PROTO) 616 /* 617 * Make sure curwin->w_cursor is not on the NUL at the end of the line. 618 * Allow it when in Visual mode and 'selection' is not "old". 619 */ 620 void 621 adjust_cursor_col() 622 { 623 if (curwin->w_cursor.col > 0 624 && (!VIsual_active || *p_sel == 'o') 625 && gchar_cursor() == NUL) 626 --curwin->w_cursor.col; 627 } 628 #endif 629 630 /* 631 * When curwin->w_leftcol has changed, adjust the cursor position. 632 * Return TRUE if the cursor was moved. 633 */ 634 int 635 leftcol_changed() 636 { 637 long lastcol; 638 colnr_T s, e; 639 int retval = FALSE; 640 641 changed_cline_bef_curs(); 642 lastcol = curwin->w_leftcol + W_WIDTH(curwin) - curwin_col_off() - 1; 643 validate_virtcol(); 644 645 /* 646 * If the cursor is right or left of the screen, move it to last or first 647 * character. 648 */ 649 if (curwin->w_virtcol > (colnr_T)(lastcol - p_siso)) 650 { 651 retval = TRUE; 652 coladvance((colnr_T)(lastcol - p_siso)); 653 } 654 else if (curwin->w_virtcol < curwin->w_leftcol + p_siso) 655 { 656 retval = TRUE; 657 (void)coladvance((colnr_T)(curwin->w_leftcol + p_siso)); 658 } 659 660 /* 661 * If the start of the character under the cursor is not on the screen, 662 * advance the cursor one more char. If this fails (last char of the 663 * line) adjust the scrolling. 664 */ 665 getvvcol(curwin, &curwin->w_cursor, &s, NULL, &e); 666 if (e > (colnr_T)lastcol) 667 { 668 retval = TRUE; 669 coladvance(s - 1); 670 } 671 else if (s < curwin->w_leftcol) 672 { 673 retval = TRUE; 674 if (coladvance(e + 1) == FAIL) /* there isn't another character */ 675 { 676 curwin->w_leftcol = s; /* adjust w_leftcol instead */ 677 changed_cline_bef_curs(); 678 } 679 } 680 681 if (retval) 682 curwin->w_set_curswant = TRUE; 683 redraw_later(NOT_VALID); 684 return retval; 685 } 686 687 /********************************************************************** 688 * Various routines dealing with allocation and deallocation of memory. 689 */ 690 691 #if defined(MEM_PROFILE) || defined(PROTO) 692 693 # define MEM_SIZES 8200 694 static long_u mem_allocs[MEM_SIZES]; 695 static long_u mem_frees[MEM_SIZES]; 696 static long_u mem_allocated; 697 static long_u mem_freed; 698 static long_u mem_peak; 699 static long_u num_alloc; 700 static long_u num_freed; 701 702 static void mem_pre_alloc_s __ARGS((size_t *sizep)); 703 static void mem_pre_alloc_l __ARGS((long_u *sizep)); 704 static void mem_post_alloc __ARGS((void **pp, size_t size)); 705 static void mem_pre_free __ARGS((void **pp)); 706 707 static void 708 mem_pre_alloc_s(sizep) 709 size_t *sizep; 710 { 711 *sizep += sizeof(size_t); 712 } 713 714 static void 715 mem_pre_alloc_l(sizep) 716 long_u *sizep; 717 { 718 *sizep += sizeof(size_t); 719 } 720 721 static void 722 mem_post_alloc(pp, size) 723 void **pp; 724 size_t size; 725 { 726 if (*pp == NULL) 727 return; 728 size -= sizeof(size_t); 729 *(long_u *)*pp = size; 730 if (size <= MEM_SIZES-1) 731 mem_allocs[size-1]++; 732 else 733 mem_allocs[MEM_SIZES-1]++; 734 mem_allocated += size; 735 if (mem_allocated - mem_freed > mem_peak) 736 mem_peak = mem_allocated - mem_freed; 737 num_alloc++; 738 *pp = (void *)((char *)*pp + sizeof(size_t)); 739 } 740 741 static void 742 mem_pre_free(pp) 743 void **pp; 744 { 745 long_u size; 746 747 *pp = (void *)((char *)*pp - sizeof(size_t)); 748 size = *(size_t *)*pp; 749 if (size <= MEM_SIZES-1) 750 mem_frees[size-1]++; 751 else 752 mem_frees[MEM_SIZES-1]++; 753 mem_freed += size; 754 num_freed++; 755 } 756 757 /* 758 * called on exit via atexit() 759 */ 760 void 761 vim_mem_profile_dump() 762 { 763 int i, j; 764 765 printf("\r\n"); 766 j = 0; 767 for (i = 0; i < MEM_SIZES - 1; i++) 768 { 769 if (mem_allocs[i] || mem_frees[i]) 770 { 771 if (mem_frees[i] > mem_allocs[i]) 772 printf("\r\n%s", _("ERROR: ")); 773 printf("[%4d / %4lu-%-4lu] ", i + 1, mem_allocs[i], mem_frees[i]); 774 j++; 775 if (j > 3) 776 { 777 j = 0; 778 printf("\r\n"); 779 } 780 } 781 } 782 783 i = MEM_SIZES - 1; 784 if (mem_allocs[i]) 785 { 786 printf("\r\n"); 787 if (mem_frees[i] > mem_allocs[i]) 788 puts(_("ERROR: ")); 789 printf("[>%d / %4lu-%-4lu]", i, mem_allocs[i], mem_frees[i]); 790 } 791 792 printf(_("\n[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"), 793 mem_allocated, mem_freed, mem_allocated - mem_freed, mem_peak); 794 printf(_("[calls] total re/malloc()'s %lu, total free()'s %lu\n\n"), 795 num_alloc, num_freed); 796 } 797 798 #endif /* MEM_PROFILE */ 799 800 /* 801 * Some memory is reserved for error messages and for being able to 802 * call mf_release_all(), which needs some memory for mf_trans_add(). 803 */ 804 #if defined(MSDOS) && !defined(DJGPP) 805 # define SMALL_MEM 806 # define KEEP_ROOM 8192L 807 #else 808 # define KEEP_ROOM (2 * 8192L) 809 #endif 810 #define KEEP_ROOM_KB (KEEP_ROOM / 1024L) 811 812 /* 813 * Note: if unsigned is 16 bits we can only allocate up to 64K with alloc(). 814 * Use lalloc for larger blocks. 815 */ 816 char_u * 817 alloc(size) 818 unsigned size; 819 { 820 return (lalloc((long_u)size, TRUE)); 821 } 822 823 /* 824 * Allocate memory and set all bytes to zero. 825 */ 826 char_u * 827 alloc_clear(size) 828 unsigned size; 829 { 830 char_u *p; 831 832 p = lalloc((long_u)size, TRUE); 833 if (p != NULL) 834 (void)vim_memset(p, 0, (size_t)size); 835 return p; 836 } 837 838 /* 839 * alloc() with check for maximum line length 840 */ 841 char_u * 842 alloc_check(size) 843 unsigned size; 844 { 845 #if !defined(UNIX) && !defined(__EMX__) 846 if (sizeof(int) == 2 && size > 0x7fff) 847 { 848 /* Don't hide this message */ 849 emsg_silent = 0; 850 EMSG(_("E340: Line is becoming too long")); 851 return NULL; 852 } 853 #endif 854 return (lalloc((long_u)size, TRUE)); 855 } 856 857 /* 858 * Allocate memory like lalloc() and set all bytes to zero. 859 */ 860 char_u * 861 lalloc_clear(size, message) 862 long_u size; 863 int message; 864 { 865 char_u *p; 866 867 p = (lalloc(size, message)); 868 if (p != NULL) 869 (void)vim_memset(p, 0, (size_t)size); 870 return p; 871 } 872 873 /* 874 * Low level memory allocation function. 875 * This is used often, KEEP IT FAST! 876 */ 877 char_u * 878 lalloc(size, message) 879 long_u size; 880 int message; 881 { 882 char_u *p; /* pointer to new storage space */ 883 static int releasing = FALSE; /* don't do mf_release_all() recursive */ 884 int try_again; 885 #if defined(HAVE_AVAIL_MEM) && !defined(SMALL_MEM) 886 static long_u allocated = 0; /* allocated since last avail check */ 887 #endif 888 889 /* Safety check for allocating zero bytes */ 890 if (size == 0) 891 { 892 /* Don't hide this message */ 893 emsg_silent = 0; 894 EMSGN(_("E341: Internal error: lalloc(%ld, )"), size); 895 return NULL; 896 } 897 898 #ifdef MEM_PROFILE 899 mem_pre_alloc_l(&size); 900 #endif 901 902 #if defined(MSDOS) && !defined(DJGPP) 903 if (size >= 0xfff0) /* in MSDOS we can't deal with >64K blocks */ 904 p = NULL; 905 else 906 #endif 907 908 /* 909 * Loop when out of memory: Try to release some memfile blocks and 910 * if some blocks are released call malloc again. 911 */ 912 for (;;) 913 { 914 /* 915 * Handle three kind of systems: 916 * 1. No check for available memory: Just return. 917 * 2. Slow check for available memory: call mch_avail_mem() after 918 * allocating KEEP_ROOM amount of memory. 919 * 3. Strict check for available memory: call mch_avail_mem() 920 */ 921 if ((p = (char_u *)malloc((size_t)size)) != NULL) 922 { 923 #ifndef HAVE_AVAIL_MEM 924 /* 1. No check for available memory: Just return. */ 925 goto theend; 926 #else 927 # ifndef SMALL_MEM 928 /* 2. Slow check for available memory: call mch_avail_mem() after 929 * allocating (KEEP_ROOM / 2) amount of memory. */ 930 allocated += size; 931 if (allocated < KEEP_ROOM / 2) 932 goto theend; 933 allocated = 0; 934 # endif 935 /* 3. check for available memory: call mch_avail_mem() */ 936 if (mch_avail_mem(TRUE) < KEEP_ROOM_KB && !releasing) 937 { 938 free((char *)p); /* System is low... no go! */ 939 p = NULL; 940 } 941 else 942 goto theend; 943 #endif 944 } 945 /* 946 * Remember that mf_release_all() is being called to avoid an endless 947 * loop, because mf_release_all() may call alloc() recursively. 948 */ 949 if (releasing) 950 break; 951 releasing = TRUE; 952 953 clear_sb_text(); /* free any scrollback text */ 954 try_again = mf_release_all(); /* release as many blocks as possible */ 955 #ifdef FEAT_EVAL 956 try_again |= garbage_collect(); /* cleanup recursive lists/dicts */ 957 #endif 958 959 releasing = FALSE; 960 if (!try_again) 961 break; 962 } 963 964 if (message && p == NULL) 965 do_outofmem_msg(size); 966 967 theend: 968 #ifdef MEM_PROFILE 969 mem_post_alloc((void **)&p, (size_t)size); 970 #endif 971 return p; 972 } 973 974 #if defined(MEM_PROFILE) || defined(PROTO) 975 /* 976 * realloc() with memory profiling. 977 */ 978 void * 979 mem_realloc(ptr, size) 980 void *ptr; 981 size_t size; 982 { 983 void *p; 984 985 mem_pre_free(&ptr); 986 mem_pre_alloc_s(&size); 987 988 p = realloc(ptr, size); 989 990 mem_post_alloc(&p, size); 991 992 return p; 993 } 994 #endif 995 996 /* 997 * Avoid repeating the error message many times (they take 1 second each). 998 * Did_outofmem_msg is reset when a character is read. 999 */ 1000 void 1001 do_outofmem_msg(size) 1002 long_u size; 1003 { 1004 if (!did_outofmem_msg) 1005 { 1006 /* Don't hide this message */ 1007 emsg_silent = 0; 1008 1009 /* Must come first to avoid coming back here when printing the error 1010 * message fails, e.g. when setting v:errmsg. */ 1011 did_outofmem_msg = TRUE; 1012 1013 EMSGN(_("E342: Out of memory! (allocating %lu bytes)"), size); 1014 } 1015 } 1016 1017 #if defined(EXITFREE) || defined(PROTO) 1018 1019 # if defined(FEAT_SEARCHPATH) 1020 static void free_findfile __ARGS((void)); 1021 # endif 1022 1023 /* 1024 * Free everything that we allocated. 1025 * Can be used to detect memory leaks, e.g., with ccmalloc. 1026 * NOTE: This is tricky! Things are freed that functions depend on. Don't be 1027 * surprised if Vim crashes... 1028 * Some things can't be freed, esp. things local to a library function. 1029 */ 1030 void 1031 free_all_mem() 1032 { 1033 buf_T *buf, *nextbuf; 1034 static int entered = FALSE; 1035 1036 /* When we cause a crash here it is caught and Vim tries to exit cleanly. 1037 * Don't try freeing everything again. */ 1038 if (entered) 1039 return; 1040 entered = TRUE; 1041 1042 # ifdef FEAT_AUTOCMD 1043 /* Don't want to trigger autocommands from here on. */ 1044 block_autocmds(); 1045 # endif 1046 1047 # ifdef FEAT_WINDOWS 1048 /* Close all tabs and windows. Reset 'equalalways' to avoid redraws. */ 1049 p_ea = FALSE; 1050 if (first_tabpage->tp_next != NULL) 1051 do_cmdline_cmd((char_u *)"tabonly!"); 1052 if (firstwin != lastwin) 1053 do_cmdline_cmd((char_u *)"only!"); 1054 # endif 1055 1056 # if defined(FEAT_SPELL) 1057 /* Free all spell info. */ 1058 spell_free_all(); 1059 # endif 1060 1061 # if defined(FEAT_USR_CMDS) 1062 /* Clear user commands (before deleting buffers). */ 1063 ex_comclear(NULL); 1064 # endif 1065 1066 # ifdef FEAT_MENU 1067 /* Clear menus. */ 1068 do_cmdline_cmd((char_u *)"aunmenu *"); 1069 # ifdef FEAT_MULTI_LANG 1070 do_cmdline_cmd((char_u *)"menutranslate clear"); 1071 # endif 1072 # endif 1073 1074 /* Clear mappings, abbreviations, breakpoints. */ 1075 do_cmdline_cmd((char_u *)"lmapclear"); 1076 do_cmdline_cmd((char_u *)"xmapclear"); 1077 do_cmdline_cmd((char_u *)"mapclear"); 1078 do_cmdline_cmd((char_u *)"mapclear!"); 1079 do_cmdline_cmd((char_u *)"abclear"); 1080 # if defined(FEAT_EVAL) 1081 do_cmdline_cmd((char_u *)"breakdel *"); 1082 # endif 1083 # if defined(FEAT_PROFILE) 1084 do_cmdline_cmd((char_u *)"profdel *"); 1085 # endif 1086 # if defined(FEAT_KEYMAP) 1087 do_cmdline_cmd((char_u *)"set keymap="); 1088 #endif 1089 1090 # ifdef FEAT_TITLE 1091 free_titles(); 1092 # endif 1093 # if defined(FEAT_SEARCHPATH) 1094 free_findfile(); 1095 # endif 1096 1097 /* Obviously named calls. */ 1098 # if defined(FEAT_AUTOCMD) 1099 free_all_autocmds(); 1100 # endif 1101 clear_termcodes(); 1102 free_all_options(); 1103 free_all_marks(); 1104 alist_clear(&global_alist); 1105 free_homedir(); 1106 # if defined(FEAT_CMDL_COMPL) 1107 free_users(); 1108 # endif 1109 free_search_patterns(); 1110 free_old_sub(); 1111 free_last_insert(); 1112 free_prev_shellcmd(); 1113 free_regexp_stuff(); 1114 free_tag_stuff(); 1115 free_cd_dir(); 1116 # ifdef FEAT_SIGNS 1117 free_signs(); 1118 # endif 1119 # ifdef FEAT_EVAL 1120 set_expr_line(NULL); 1121 # endif 1122 # ifdef FEAT_DIFF 1123 diff_clear(curtab); 1124 # endif 1125 clear_sb_text(); /* free any scrollback text */ 1126 1127 /* Free some global vars. */ 1128 vim_free(username); 1129 # ifdef FEAT_CLIPBOARD 1130 vim_regfree(clip_exclude_prog); 1131 # endif 1132 vim_free(last_cmdline); 1133 # ifdef FEAT_CMDHIST 1134 vim_free(new_last_cmdline); 1135 # endif 1136 set_keep_msg(NULL, 0); 1137 vim_free(ff_expand_buffer); 1138 1139 /* Clear cmdline history. */ 1140 p_hi = 0; 1141 # ifdef FEAT_CMDHIST 1142 init_history(); 1143 # endif 1144 1145 #ifdef FEAT_QUICKFIX 1146 { 1147 win_T *win; 1148 tabpage_T *tab; 1149 1150 qf_free_all(NULL); 1151 /* Free all location lists */ 1152 FOR_ALL_TAB_WINDOWS(tab, win) 1153 qf_free_all(win); 1154 } 1155 #endif 1156 1157 /* Close all script inputs. */ 1158 close_all_scripts(); 1159 1160 #if defined(FEAT_WINDOWS) 1161 /* Destroy all windows. Must come before freeing buffers. */ 1162 win_free_all(); 1163 #endif 1164 1165 /* Free all buffers. Reset 'autochdir' to avoid accessing things that 1166 * were freed already. */ 1167 #ifdef FEAT_AUTOCHDIR 1168 p_acd = FALSE; 1169 #endif 1170 for (buf = firstbuf; buf != NULL; ) 1171 { 1172 nextbuf = buf->b_next; 1173 close_buffer(NULL, buf, DOBUF_WIPE, FALSE); 1174 if (buf_valid(buf)) 1175 buf = nextbuf; /* didn't work, try next one */ 1176 else 1177 buf = firstbuf; 1178 } 1179 1180 #ifdef FEAT_ARABIC 1181 free_cmdline_buf(); 1182 #endif 1183 1184 /* Clear registers. */ 1185 clear_registers(); 1186 ResetRedobuff(); 1187 ResetRedobuff(); 1188 1189 #if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11) 1190 vim_free(serverDelayedStartName); 1191 #endif 1192 1193 /* highlight info */ 1194 free_highlight(); 1195 1196 reset_last_sourcing(); 1197 1198 #ifdef FEAT_WINDOWS 1199 free_tabpage(first_tabpage); 1200 first_tabpage = NULL; 1201 #endif 1202 1203 # ifdef UNIX 1204 /* Machine-specific free. */ 1205 mch_free_mem(); 1206 # endif 1207 1208 /* message history */ 1209 for (;;) 1210 if (delete_first_msg() == FAIL) 1211 break; 1212 1213 # ifdef FEAT_EVAL 1214 eval_clear(); 1215 # endif 1216 1217 free_termoptions(); 1218 1219 /* screenlines (can't display anything now!) */ 1220 free_screenlines(); 1221 1222 #if defined(USE_XSMP) 1223 xsmp_close(); 1224 #endif 1225 #ifdef FEAT_GUI_GTK 1226 gui_mch_free_all(); 1227 #endif 1228 clear_hl_tables(); 1229 1230 vim_free(IObuff); 1231 vim_free(NameBuff); 1232 } 1233 #endif 1234 1235 /* 1236 * Copy "string" into newly allocated memory. 1237 */ 1238 char_u * 1239 vim_strsave(string) 1240 char_u *string; 1241 { 1242 char_u *p; 1243 unsigned len; 1244 1245 len = (unsigned)STRLEN(string) + 1; 1246 p = alloc(len); 1247 if (p != NULL) 1248 mch_memmove(p, string, (size_t)len); 1249 return p; 1250 } 1251 1252 /* 1253 * Copy up to "len" bytes of "string" into newly allocated memory and 1254 * terminate with a NUL. 1255 * The allocated memory always has size "len + 1", also when "string" is 1256 * shorter. 1257 */ 1258 char_u * 1259 vim_strnsave(string, len) 1260 char_u *string; 1261 int len; 1262 { 1263 char_u *p; 1264 1265 p = alloc((unsigned)(len + 1)); 1266 if (p != NULL) 1267 { 1268 STRNCPY(p, string, len); 1269 p[len] = NUL; 1270 } 1271 return p; 1272 } 1273 1274 /* 1275 * Same as vim_strsave(), but any characters found in esc_chars are preceded 1276 * by a backslash. 1277 */ 1278 char_u * 1279 vim_strsave_escaped(string, esc_chars) 1280 char_u *string; 1281 char_u *esc_chars; 1282 { 1283 return vim_strsave_escaped_ext(string, esc_chars, '\\', FALSE); 1284 } 1285 1286 /* 1287 * Same as vim_strsave_escaped(), but when "bsl" is TRUE also escape 1288 * characters where rem_backslash() would remove the backslash. 1289 * Escape the characters with "cc". 1290 */ 1291 char_u * 1292 vim_strsave_escaped_ext(string, esc_chars, cc, bsl) 1293 char_u *string; 1294 char_u *esc_chars; 1295 int cc; 1296 int bsl; 1297 { 1298 char_u *p; 1299 char_u *p2; 1300 char_u *escaped_string; 1301 unsigned length; 1302 #ifdef FEAT_MBYTE 1303 int l; 1304 #endif 1305 1306 /* 1307 * First count the number of backslashes required. 1308 * Then allocate the memory and insert them. 1309 */ 1310 length = 1; /* count the trailing NUL */ 1311 for (p = string; *p; p++) 1312 { 1313 #ifdef FEAT_MBYTE 1314 if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) 1315 { 1316 length += l; /* count a multibyte char */ 1317 p += l - 1; 1318 continue; 1319 } 1320 #endif 1321 if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p))) 1322 ++length; /* count a backslash */ 1323 ++length; /* count an ordinary char */ 1324 } 1325 escaped_string = alloc(length); 1326 if (escaped_string != NULL) 1327 { 1328 p2 = escaped_string; 1329 for (p = string; *p; p++) 1330 { 1331 #ifdef FEAT_MBYTE 1332 if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) 1333 { 1334 mch_memmove(p2, p, (size_t)l); 1335 p2 += l; 1336 p += l - 1; /* skip multibyte char */ 1337 continue; 1338 } 1339 #endif 1340 if (vim_strchr(esc_chars, *p) != NULL || (bsl && rem_backslash(p))) 1341 *p2++ = cc; 1342 *p2++ = *p; 1343 } 1344 *p2 = NUL; 1345 } 1346 return escaped_string; 1347 } 1348 1349 /* 1350 * Return TRUE when 'shell' has "csh" in the tail. 1351 */ 1352 int 1353 csh_like_shell() 1354 { 1355 return (strstr((char *)gettail(p_sh), "csh") != NULL); 1356 } 1357 1358 /* 1359 * Escape "string" for use as a shell argument with system(). 1360 * This uses single quotes, except when we know we need to use double quotes 1361 * (MS-DOS and MS-Windows without 'shellslash' set). 1362 * Escape a newline, depending on the 'shell' option. 1363 * When "do_special" is TRUE also replace "!", "%", "#" and things starting 1364 * with "<" like "<cfile>". 1365 * When "do_newline" is FALSE do not escape newline unless it is csh shell. 1366 * Returns the result in allocated memory, NULL if we have run out. 1367 */ 1368 char_u * 1369 vim_strsave_shellescape(string, do_special, do_newline) 1370 char_u *string; 1371 int do_special; 1372 int do_newline; 1373 { 1374 unsigned length; 1375 char_u *p; 1376 char_u *d; 1377 char_u *escaped_string; 1378 int l; 1379 int csh_like; 1380 1381 /* Only csh and similar shells expand '!' within single quotes. For sh and 1382 * the like we must not put a backslash before it, it will be taken 1383 * literally. If do_special is set the '!' will be escaped twice. 1384 * Csh also needs to have "\n" escaped twice when do_special is set. */ 1385 csh_like = csh_like_shell(); 1386 1387 /* First count the number of extra bytes required. */ 1388 length = (unsigned)STRLEN(string) + 3; /* two quotes and a trailing NUL */ 1389 for (p = string; *p != NUL; mb_ptr_adv(p)) 1390 { 1391 # if defined(WIN32) || defined(WIN16) || defined(DOS) 1392 if (!p_ssl) 1393 { 1394 if (*p == '"') 1395 ++length; /* " -> "" */ 1396 } 1397 else 1398 # endif 1399 if (*p == '\'') 1400 length += 3; /* ' => '\'' */ 1401 if ((*p == '\n' && (csh_like || do_newline)) 1402 || (*p == '!' && (csh_like || do_special))) 1403 { 1404 ++length; /* insert backslash */ 1405 if (csh_like && do_special) 1406 ++length; /* insert backslash */ 1407 } 1408 if (do_special && find_cmdline_var(p, &l) >= 0) 1409 { 1410 ++length; /* insert backslash */ 1411 p += l - 1; 1412 } 1413 } 1414 1415 /* Allocate memory for the result and fill it. */ 1416 escaped_string = alloc(length); 1417 if (escaped_string != NULL) 1418 { 1419 d = escaped_string; 1420 1421 /* add opening quote */ 1422 # if defined(WIN32) || defined(WIN16) || defined(DOS) 1423 if (!p_ssl) 1424 *d++ = '"'; 1425 else 1426 # endif 1427 *d++ = '\''; 1428 1429 for (p = string; *p != NUL; ) 1430 { 1431 # if defined(WIN32) || defined(WIN16) || defined(DOS) 1432 if (!p_ssl) 1433 { 1434 if (*p == '"') 1435 { 1436 *d++ = '"'; 1437 *d++ = '"'; 1438 ++p; 1439 continue; 1440 } 1441 } 1442 else 1443 # endif 1444 if (*p == '\'') 1445 { 1446 *d++ = '\''; 1447 *d++ = '\\'; 1448 *d++ = '\''; 1449 *d++ = '\''; 1450 ++p; 1451 continue; 1452 } 1453 if ((*p == '\n' && (csh_like || do_newline)) 1454 || (*p == '!' && (csh_like || do_special))) 1455 { 1456 *d++ = '\\'; 1457 if (csh_like && do_special) 1458 *d++ = '\\'; 1459 *d++ = *p++; 1460 continue; 1461 } 1462 if (do_special && find_cmdline_var(p, &l) >= 0) 1463 { 1464 *d++ = '\\'; /* insert backslash */ 1465 while (--l >= 0) /* copy the var */ 1466 *d++ = *p++; 1467 continue; 1468 } 1469 1470 MB_COPY_CHAR(p, d); 1471 } 1472 1473 /* add terminating quote and finish with a NUL */ 1474 # if defined(WIN32) || defined(WIN16) || defined(DOS) 1475 if (!p_ssl) 1476 *d++ = '"'; 1477 else 1478 # endif 1479 *d++ = '\''; 1480 *d = NUL; 1481 } 1482 1483 return escaped_string; 1484 } 1485 1486 /* 1487 * Like vim_strsave(), but make all characters uppercase. 1488 * This uses ASCII lower-to-upper case translation, language independent. 1489 */ 1490 char_u * 1491 vim_strsave_up(string) 1492 char_u *string; 1493 { 1494 char_u *p1; 1495 1496 p1 = vim_strsave(string); 1497 vim_strup(p1); 1498 return p1; 1499 } 1500 1501 /* 1502 * Like vim_strnsave(), but make all characters uppercase. 1503 * This uses ASCII lower-to-upper case translation, language independent. 1504 */ 1505 char_u * 1506 vim_strnsave_up(string, len) 1507 char_u *string; 1508 int len; 1509 { 1510 char_u *p1; 1511 1512 p1 = vim_strnsave(string, len); 1513 vim_strup(p1); 1514 return p1; 1515 } 1516 1517 /* 1518 * ASCII lower-to-upper case translation, language independent. 1519 */ 1520 void 1521 vim_strup(p) 1522 char_u *p; 1523 { 1524 char_u *p2; 1525 int c; 1526 1527 if (p != NULL) 1528 { 1529 p2 = p; 1530 while ((c = *p2) != NUL) 1531 #ifdef EBCDIC 1532 *p2++ = isalpha(c) ? toupper(c) : c; 1533 #else 1534 *p2++ = (c < 'a' || c > 'z') ? c : (c - 0x20); 1535 #endif 1536 } 1537 } 1538 1539 #if defined(FEAT_EVAL) || defined(FEAT_SPELL) || defined(PROTO) 1540 /* 1541 * Make string "s" all upper-case and return it in allocated memory. 1542 * Handles multi-byte characters as well as possible. 1543 * Returns NULL when out of memory. 1544 */ 1545 char_u * 1546 strup_save(orig) 1547 char_u *orig; 1548 { 1549 char_u *p; 1550 char_u *res; 1551 1552 res = p = vim_strsave(orig); 1553 1554 if (res != NULL) 1555 while (*p != NUL) 1556 { 1557 # ifdef FEAT_MBYTE 1558 int l; 1559 1560 if (enc_utf8) 1561 { 1562 int c, uc; 1563 int newl; 1564 char_u *s; 1565 1566 c = utf_ptr2char(p); 1567 uc = utf_toupper(c); 1568 1569 /* Reallocate string when byte count changes. This is rare, 1570 * thus it's OK to do another malloc()/free(). */ 1571 l = utf_ptr2len(p); 1572 newl = utf_char2len(uc); 1573 if (newl != l) 1574 { 1575 s = alloc((unsigned)STRLEN(res) + 1 + newl - l); 1576 if (s == NULL) 1577 break; 1578 mch_memmove(s, res, p - res); 1579 STRCPY(s + (p - res) + newl, p + l); 1580 p = s + (p - res); 1581 vim_free(res); 1582 res = s; 1583 } 1584 1585 utf_char2bytes(uc, p); 1586 p += newl; 1587 } 1588 else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) 1589 p += l; /* skip multi-byte character */ 1590 else 1591 # endif 1592 { 1593 *p = TOUPPER_LOC(*p); /* note that toupper() can be a macro */ 1594 p++; 1595 } 1596 } 1597 1598 return res; 1599 } 1600 #endif 1601 1602 /* 1603 * copy a space a number of times 1604 */ 1605 void 1606 copy_spaces(ptr, count) 1607 char_u *ptr; 1608 size_t count; 1609 { 1610 size_t i = count; 1611 char_u *p = ptr; 1612 1613 while (i--) 1614 *p++ = ' '; 1615 } 1616 1617 #if defined(FEAT_VISUALEXTRA) || defined(PROTO) 1618 /* 1619 * Copy a character a number of times. 1620 * Does not work for multi-byte characters! 1621 */ 1622 void 1623 copy_chars(ptr, count, c) 1624 char_u *ptr; 1625 size_t count; 1626 int c; 1627 { 1628 size_t i = count; 1629 char_u *p = ptr; 1630 1631 while (i--) 1632 *p++ = c; 1633 } 1634 #endif 1635 1636 /* 1637 * delete spaces at the end of a string 1638 */ 1639 void 1640 del_trailing_spaces(ptr) 1641 char_u *ptr; 1642 { 1643 char_u *q; 1644 1645 q = ptr + STRLEN(ptr); 1646 while (--q > ptr && vim_iswhite(q[0]) && q[-1] != '\\' && q[-1] != Ctrl_V) 1647 *q = NUL; 1648 } 1649 1650 /* 1651 * Like strncpy(), but always terminate the result with one NUL. 1652 * "to" must be "len + 1" long! 1653 */ 1654 void 1655 vim_strncpy(to, from, len) 1656 char_u *to; 1657 char_u *from; 1658 size_t len; 1659 { 1660 STRNCPY(to, from, len); 1661 to[len] = NUL; 1662 } 1663 1664 /* 1665 * Like strcat(), but make sure the result fits in "tosize" bytes and is 1666 * always NUL terminated. 1667 */ 1668 void 1669 vim_strcat(to, from, tosize) 1670 char_u *to; 1671 char_u *from; 1672 size_t tosize; 1673 { 1674 size_t tolen = STRLEN(to); 1675 size_t fromlen = STRLEN(from); 1676 1677 if (tolen + fromlen + 1 > tosize) 1678 { 1679 mch_memmove(to + tolen, from, tosize - tolen - 1); 1680 to[tosize - 1] = NUL; 1681 } 1682 else 1683 STRCPY(to + tolen, from); 1684 } 1685 1686 /* 1687 * Isolate one part of a string option where parts are separated with 1688 * "sep_chars". 1689 * The part is copied into "buf[maxlen]". 1690 * "*option" is advanced to the next part. 1691 * The length is returned. 1692 */ 1693 int 1694 copy_option_part(option, buf, maxlen, sep_chars) 1695 char_u **option; 1696 char_u *buf; 1697 int maxlen; 1698 char *sep_chars; 1699 { 1700 int len = 0; 1701 char_u *p = *option; 1702 1703 /* skip '.' at start of option part, for 'suffixes' */ 1704 if (*p == '.') 1705 buf[len++] = *p++; 1706 while (*p != NUL && vim_strchr((char_u *)sep_chars, *p) == NULL) 1707 { 1708 /* 1709 * Skip backslash before a separator character and space. 1710 */ 1711 if (p[0] == '\\' && vim_strchr((char_u *)sep_chars, p[1]) != NULL) 1712 ++p; 1713 if (len < maxlen - 1) 1714 buf[len++] = *p; 1715 ++p; 1716 } 1717 buf[len] = NUL; 1718 1719 if (*p != NUL && *p != ',') /* skip non-standard separator */ 1720 ++p; 1721 p = skip_to_option_part(p); /* p points to next file name */ 1722 1723 *option = p; 1724 return len; 1725 } 1726 1727 /* 1728 * Replacement for free() that ignores NULL pointers. 1729 * Also skip free() when exiting for sure, this helps when we caught a deadly 1730 * signal that was caused by a crash in free(). 1731 */ 1732 void 1733 vim_free(x) 1734 void *x; 1735 { 1736 if (x != NULL && !really_exiting) 1737 { 1738 #ifdef MEM_PROFILE 1739 mem_pre_free(&x); 1740 #endif 1741 free(x); 1742 } 1743 } 1744 1745 #ifndef HAVE_MEMSET 1746 void * 1747 vim_memset(ptr, c, size) 1748 void *ptr; 1749 int c; 1750 size_t size; 1751 { 1752 char *p = ptr; 1753 1754 while (size-- > 0) 1755 *p++ = c; 1756 return ptr; 1757 } 1758 #endif 1759 1760 #ifdef VIM_MEMCMP 1761 /* 1762 * Return zero when "b1" and "b2" are the same for "len" bytes. 1763 * Return non-zero otherwise. 1764 */ 1765 int 1766 vim_memcmp(b1, b2, len) 1767 void *b1; 1768 void *b2; 1769 size_t len; 1770 { 1771 char_u *p1 = (char_u *)b1, *p2 = (char_u *)b2; 1772 1773 for ( ; len > 0; --len) 1774 { 1775 if (*p1 != *p2) 1776 return 1; 1777 ++p1; 1778 ++p2; 1779 } 1780 return 0; 1781 } 1782 #endif 1783 1784 #ifdef VIM_MEMMOVE 1785 /* 1786 * Version of memmove() that handles overlapping source and destination. 1787 * For systems that don't have a function that is guaranteed to do that (SYSV). 1788 */ 1789 void 1790 mch_memmove(dst_arg, src_arg, len) 1791 void *src_arg, *dst_arg; 1792 size_t len; 1793 { 1794 /* 1795 * A void doesn't have a size, we use char pointers. 1796 */ 1797 char *dst = dst_arg, *src = src_arg; 1798 1799 /* overlap, copy backwards */ 1800 if (dst > src && dst < src + len) 1801 { 1802 src += len; 1803 dst += len; 1804 while (len-- > 0) 1805 *--dst = *--src; 1806 } 1807 else /* copy forwards */ 1808 while (len-- > 0) 1809 *dst++ = *src++; 1810 } 1811 #endif 1812 1813 #if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) || defined(PROTO) 1814 /* 1815 * Compare two strings, ignoring case, using current locale. 1816 * Doesn't work for multi-byte characters. 1817 * return 0 for match, < 0 for smaller, > 0 for bigger 1818 */ 1819 int 1820 vim_stricmp(s1, s2) 1821 char *s1; 1822 char *s2; 1823 { 1824 int i; 1825 1826 for (;;) 1827 { 1828 i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2); 1829 if (i != 0) 1830 return i; /* this character different */ 1831 if (*s1 == NUL) 1832 break; /* strings match until NUL */ 1833 ++s1; 1834 ++s2; 1835 } 1836 return 0; /* strings match */ 1837 } 1838 #endif 1839 1840 #if (!defined(HAVE_STRNCASECMP) && !defined(HAVE_STRNICMP)) || defined(PROTO) 1841 /* 1842 * Compare two strings, for length "len", ignoring case, using current locale. 1843 * Doesn't work for multi-byte characters. 1844 * return 0 for match, < 0 for smaller, > 0 for bigger 1845 */ 1846 int 1847 vim_strnicmp(s1, s2, len) 1848 char *s1; 1849 char *s2; 1850 size_t len; 1851 { 1852 int i; 1853 1854 while (len > 0) 1855 { 1856 i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2); 1857 if (i != 0) 1858 return i; /* this character different */ 1859 if (*s1 == NUL) 1860 break; /* strings match until NUL */ 1861 ++s1; 1862 ++s2; 1863 --len; 1864 } 1865 return 0; /* strings match */ 1866 } 1867 #endif 1868 1869 /* 1870 * Version of strchr() and strrchr() that handle unsigned char strings 1871 * with characters from 128 to 255 correctly. It also doesn't return a 1872 * pointer to the NUL at the end of the string. 1873 */ 1874 char_u * 1875 vim_strchr(string, c) 1876 char_u *string; 1877 int c; 1878 { 1879 char_u *p; 1880 int b; 1881 1882 p = string; 1883 #ifdef FEAT_MBYTE 1884 if (enc_utf8 && c >= 0x80) 1885 { 1886 while (*p != NUL) 1887 { 1888 if (utf_ptr2char(p) == c) 1889 return p; 1890 p += (*mb_ptr2len)(p); 1891 } 1892 return NULL; 1893 } 1894 if (enc_dbcs != 0 && c > 255) 1895 { 1896 int n2 = c & 0xff; 1897 1898 c = ((unsigned)c >> 8) & 0xff; 1899 while ((b = *p) != NUL) 1900 { 1901 if (b == c && p[1] == n2) 1902 return p; 1903 p += (*mb_ptr2len)(p); 1904 } 1905 return NULL; 1906 } 1907 if (has_mbyte) 1908 { 1909 while ((b = *p) != NUL) 1910 { 1911 if (b == c) 1912 return p; 1913 p += (*mb_ptr2len)(p); 1914 } 1915 return NULL; 1916 } 1917 #endif 1918 while ((b = *p) != NUL) 1919 { 1920 if (b == c) 1921 return p; 1922 ++p; 1923 } 1924 return NULL; 1925 } 1926 1927 /* 1928 * Version of strchr() that only works for bytes and handles unsigned char 1929 * strings with characters above 128 correctly. It also doesn't return a 1930 * pointer to the NUL at the end of the string. 1931 */ 1932 char_u * 1933 vim_strbyte(string, c) 1934 char_u *string; 1935 int c; 1936 { 1937 char_u *p = string; 1938 1939 while (*p != NUL) 1940 { 1941 if (*p == c) 1942 return p; 1943 ++p; 1944 } 1945 return NULL; 1946 } 1947 1948 /* 1949 * Search for last occurrence of "c" in "string". 1950 * Return NULL if not found. 1951 * Does not handle multi-byte char for "c"! 1952 */ 1953 char_u * 1954 vim_strrchr(string, c) 1955 char_u *string; 1956 int c; 1957 { 1958 char_u *retval = NULL; 1959 char_u *p = string; 1960 1961 while (*p) 1962 { 1963 if (*p == c) 1964 retval = p; 1965 mb_ptr_adv(p); 1966 } 1967 return retval; 1968 } 1969 1970 /* 1971 * Vim's version of strpbrk(), in case it's missing. 1972 * Don't generate a prototype for this, causes problems when it's not used. 1973 */ 1974 #ifndef PROTO 1975 # ifndef HAVE_STRPBRK 1976 # ifdef vim_strpbrk 1977 # undef vim_strpbrk 1978 # endif 1979 char_u * 1980 vim_strpbrk(s, charset) 1981 char_u *s; 1982 char_u *charset; 1983 { 1984 while (*s) 1985 { 1986 if (vim_strchr(charset, *s) != NULL) 1987 return s; 1988 mb_ptr_adv(s); 1989 } 1990 return NULL; 1991 } 1992 # endif 1993 #endif 1994 1995 /* 1996 * Vim has its own isspace() function, because on some machines isspace() 1997 * can't handle characters above 128. 1998 */ 1999 int 2000 vim_isspace(x) 2001 int x; 2002 { 2003 return ((x >= 9 && x <= 13) || x == ' '); 2004 } 2005 2006 /************************************************************************ 2007 * Functions for handling growing arrays. 2008 */ 2009 2010 /* 2011 * Clear an allocated growing array. 2012 */ 2013 void 2014 ga_clear(gap) 2015 garray_T *gap; 2016 { 2017 vim_free(gap->ga_data); 2018 ga_init(gap); 2019 } 2020 2021 /* 2022 * Clear a growing array that contains a list of strings. 2023 */ 2024 void 2025 ga_clear_strings(gap) 2026 garray_T *gap; 2027 { 2028 int i; 2029 2030 for (i = 0; i < gap->ga_len; ++i) 2031 vim_free(((char_u **)(gap->ga_data))[i]); 2032 ga_clear(gap); 2033 } 2034 2035 /* 2036 * Initialize a growing array. Don't forget to set ga_itemsize and 2037 * ga_growsize! Or use ga_init2(). 2038 */ 2039 void 2040 ga_init(gap) 2041 garray_T *gap; 2042 { 2043 gap->ga_data = NULL; 2044 gap->ga_maxlen = 0; 2045 gap->ga_len = 0; 2046 } 2047 2048 void 2049 ga_init2(gap, itemsize, growsize) 2050 garray_T *gap; 2051 int itemsize; 2052 int growsize; 2053 { 2054 ga_init(gap); 2055 gap->ga_itemsize = itemsize; 2056 gap->ga_growsize = growsize; 2057 } 2058 2059 /* 2060 * Make room in growing array "gap" for at least "n" items. 2061 * Return FAIL for failure, OK otherwise. 2062 */ 2063 int 2064 ga_grow(gap, n) 2065 garray_T *gap; 2066 int n; 2067 { 2068 size_t old_len; 2069 size_t new_len; 2070 char_u *pp; 2071 2072 if (gap->ga_maxlen - gap->ga_len < n) 2073 { 2074 if (n < gap->ga_growsize) 2075 n = gap->ga_growsize; 2076 new_len = gap->ga_itemsize * (gap->ga_len + n); 2077 pp = (gap->ga_data == NULL) 2078 ? alloc((unsigned)new_len) : vim_realloc(gap->ga_data, new_len); 2079 if (pp == NULL) 2080 return FAIL; 2081 old_len = gap->ga_itemsize * gap->ga_maxlen; 2082 vim_memset(pp + old_len, 0, new_len - old_len); 2083 gap->ga_maxlen = gap->ga_len + n; 2084 gap->ga_data = pp; 2085 } 2086 return OK; 2087 } 2088 2089 /* 2090 * For a growing array that contains a list of strings: concatenate all the 2091 * strings with a separating "sep". 2092 * Returns NULL when out of memory. 2093 */ 2094 char_u * 2095 ga_concat_strings(gap, sep) 2096 garray_T *gap; 2097 char *sep; 2098 { 2099 int i; 2100 int len = 0; 2101 int sep_len = (int)STRLEN(sep); 2102 char_u *s; 2103 char_u *p; 2104 2105 for (i = 0; i < gap->ga_len; ++i) 2106 len += (int)STRLEN(((char_u **)(gap->ga_data))[i]) + sep_len; 2107 2108 s = alloc(len + 1); 2109 if (s != NULL) 2110 { 2111 *s = NUL; 2112 p = s; 2113 for (i = 0; i < gap->ga_len; ++i) 2114 { 2115 if (p != s) 2116 { 2117 STRCPY(p, sep); 2118 p += sep_len; 2119 } 2120 STRCPY(p, ((char_u **)(gap->ga_data))[i]); 2121 p += STRLEN(p); 2122 } 2123 } 2124 return s; 2125 } 2126 2127 /* 2128 * Concatenate a string to a growarray which contains characters. 2129 * Note: Does NOT copy the NUL at the end! 2130 */ 2131 void 2132 ga_concat(gap, s) 2133 garray_T *gap; 2134 char_u *s; 2135 { 2136 int len = (int)STRLEN(s); 2137 2138 if (ga_grow(gap, len) == OK) 2139 { 2140 mch_memmove((char *)gap->ga_data + gap->ga_len, s, (size_t)len); 2141 gap->ga_len += len; 2142 } 2143 } 2144 2145 /* 2146 * Append one byte to a growarray which contains bytes. 2147 */ 2148 void 2149 ga_append(gap, c) 2150 garray_T *gap; 2151 int c; 2152 { 2153 if (ga_grow(gap, 1) == OK) 2154 { 2155 *((char *)gap->ga_data + gap->ga_len) = c; 2156 ++gap->ga_len; 2157 } 2158 } 2159 2160 #if (defined(UNIX) && !defined(USE_SYSTEM)) || defined(WIN3264) \ 2161 || defined(PROTO) 2162 /* 2163 * Append the text in "gap" below the cursor line and clear "gap". 2164 */ 2165 void 2166 append_ga_line(gap) 2167 garray_T *gap; 2168 { 2169 /* Remove trailing CR. */ 2170 if (gap->ga_len > 0 2171 && !curbuf->b_p_bin 2172 && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR) 2173 --gap->ga_len; 2174 ga_append(gap, NUL); 2175 ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE); 2176 gap->ga_len = 0; 2177 } 2178 #endif 2179 2180 /************************************************************************ 2181 * functions that use lookup tables for various things, generally to do with 2182 * special key codes. 2183 */ 2184 2185 /* 2186 * Some useful tables. 2187 */ 2188 2189 static struct modmasktable 2190 { 2191 short mod_mask; /* Bit-mask for particular key modifier */ 2192 short mod_flag; /* Bit(s) for particular key modifier */ 2193 char_u name; /* Single letter name of modifier */ 2194 } mod_mask_table[] = 2195 { 2196 {MOD_MASK_ALT, MOD_MASK_ALT, (char_u)'M'}, 2197 {MOD_MASK_META, MOD_MASK_META, (char_u)'T'}, 2198 {MOD_MASK_CTRL, MOD_MASK_CTRL, (char_u)'C'}, 2199 {MOD_MASK_SHIFT, MOD_MASK_SHIFT, (char_u)'S'}, 2200 {MOD_MASK_MULTI_CLICK, MOD_MASK_2CLICK, (char_u)'2'}, 2201 {MOD_MASK_MULTI_CLICK, MOD_MASK_3CLICK, (char_u)'3'}, 2202 {MOD_MASK_MULTI_CLICK, MOD_MASK_4CLICK, (char_u)'4'}, 2203 #ifdef MACOS 2204 {MOD_MASK_CMD, MOD_MASK_CMD, (char_u)'D'}, 2205 #endif 2206 /* 'A' must be the last one */ 2207 {MOD_MASK_ALT, MOD_MASK_ALT, (char_u)'A'}, 2208 {0, 0, NUL} 2209 }; 2210 2211 /* 2212 * Shifted key terminal codes and their unshifted equivalent. 2213 * Don't add mouse codes here, they are handled separately! 2214 */ 2215 #define MOD_KEYS_ENTRY_SIZE 5 2216 2217 static char_u modifier_keys_table[] = 2218 { 2219 /* mod mask with modifier without modifier */ 2220 MOD_MASK_SHIFT, '&', '9', '@', '1', /* begin */ 2221 MOD_MASK_SHIFT, '&', '0', '@', '2', /* cancel */ 2222 MOD_MASK_SHIFT, '*', '1', '@', '4', /* command */ 2223 MOD_MASK_SHIFT, '*', '2', '@', '5', /* copy */ 2224 MOD_MASK_SHIFT, '*', '3', '@', '6', /* create */ 2225 MOD_MASK_SHIFT, '*', '4', 'k', 'D', /* delete char */ 2226 MOD_MASK_SHIFT, '*', '5', 'k', 'L', /* delete line */ 2227 MOD_MASK_SHIFT, '*', '7', '@', '7', /* end */ 2228 MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_END, '@', '7', /* end */ 2229 MOD_MASK_SHIFT, '*', '9', '@', '9', /* exit */ 2230 MOD_MASK_SHIFT, '*', '0', '@', '0', /* find */ 2231 MOD_MASK_SHIFT, '#', '1', '%', '1', /* help */ 2232 MOD_MASK_SHIFT, '#', '2', 'k', 'h', /* home */ 2233 MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_HOME, 'k', 'h', /* home */ 2234 MOD_MASK_SHIFT, '#', '3', 'k', 'I', /* insert */ 2235 MOD_MASK_SHIFT, '#', '4', 'k', 'l', /* left arrow */ 2236 MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_LEFT, 'k', 'l', /* left arrow */ 2237 MOD_MASK_SHIFT, '%', 'a', '%', '3', /* message */ 2238 MOD_MASK_SHIFT, '%', 'b', '%', '4', /* move */ 2239 MOD_MASK_SHIFT, '%', 'c', '%', '5', /* next */ 2240 MOD_MASK_SHIFT, '%', 'd', '%', '7', /* options */ 2241 MOD_MASK_SHIFT, '%', 'e', '%', '8', /* previous */ 2242 MOD_MASK_SHIFT, '%', 'f', '%', '9', /* print */ 2243 MOD_MASK_SHIFT, '%', 'g', '%', '0', /* redo */ 2244 MOD_MASK_SHIFT, '%', 'h', '&', '3', /* replace */ 2245 MOD_MASK_SHIFT, '%', 'i', 'k', 'r', /* right arr. */ 2246 MOD_MASK_CTRL, KS_EXTRA, (int)KE_C_RIGHT, 'k', 'r', /* right arr. */ 2247 MOD_MASK_SHIFT, '%', 'j', '&', '5', /* resume */ 2248 MOD_MASK_SHIFT, '!', '1', '&', '6', /* save */ 2249 MOD_MASK_SHIFT, '!', '2', '&', '7', /* suspend */ 2250 MOD_MASK_SHIFT, '!', '3', '&', '8', /* undo */ 2251 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_UP, 'k', 'u', /* up arrow */ 2252 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_DOWN, 'k', 'd', /* down arrow */ 2253 2254 /* vt100 F1 */ 2255 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF1, KS_EXTRA, (int)KE_XF1, 2256 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF2, KS_EXTRA, (int)KE_XF2, 2257 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF3, KS_EXTRA, (int)KE_XF3, 2258 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF4, KS_EXTRA, (int)KE_XF4, 2259 2260 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F1, 'k', '1', /* F1 */ 2261 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F2, 'k', '2', 2262 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F3, 'k', '3', 2263 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F4, 'k', '4', 2264 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F5, 'k', '5', 2265 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F6, 'k', '6', 2266 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F7, 'k', '7', 2267 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F8, 'k', '8', 2268 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F9, 'k', '9', 2269 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F10, 'k', ';', /* F10 */ 2270 2271 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F11, 'F', '1', 2272 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F12, 'F', '2', 2273 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F13, 'F', '3', 2274 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F14, 'F', '4', 2275 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F15, 'F', '5', 2276 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F16, 'F', '6', 2277 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F17, 'F', '7', 2278 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F18, 'F', '8', 2279 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F19, 'F', '9', 2280 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F20, 'F', 'A', 2281 2282 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F21, 'F', 'B', 2283 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F22, 'F', 'C', 2284 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F23, 'F', 'D', 2285 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F24, 'F', 'E', 2286 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F25, 'F', 'F', 2287 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F26, 'F', 'G', 2288 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F27, 'F', 'H', 2289 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F28, 'F', 'I', 2290 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F29, 'F', 'J', 2291 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F30, 'F', 'K', 2292 2293 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F31, 'F', 'L', 2294 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F32, 'F', 'M', 2295 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F33, 'F', 'N', 2296 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F34, 'F', 'O', 2297 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F35, 'F', 'P', 2298 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F36, 'F', 'Q', 2299 MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F37, 'F', 'R', 2300 2301 /* TAB pseudo code*/ 2302 MOD_MASK_SHIFT, 'k', 'B', KS_EXTRA, (int)KE_TAB, 2303 2304 NUL 2305 }; 2306 2307 static struct key_name_entry 2308 { 2309 int key; /* Special key code or ascii value */ 2310 char_u *name; /* Name of key */ 2311 } key_names_table[] = 2312 { 2313 {' ', (char_u *)"Space"}, 2314 {TAB, (char_u *)"Tab"}, 2315 {K_TAB, (char_u *)"Tab"}, 2316 {NL, (char_u *)"NL"}, 2317 {NL, (char_u *)"NewLine"}, /* Alternative name */ 2318 {NL, (char_u *)"LineFeed"}, /* Alternative name */ 2319 {NL, (char_u *)"LF"}, /* Alternative name */ 2320 {CAR, (char_u *)"CR"}, 2321 {CAR, (char_u *)"Return"}, /* Alternative name */ 2322 {CAR, (char_u *)"Enter"}, /* Alternative name */ 2323 {K_BS, (char_u *)"BS"}, 2324 {K_BS, (char_u *)"BackSpace"}, /* Alternative name */ 2325 {ESC, (char_u *)"Esc"}, 2326 {CSI, (char_u *)"CSI"}, 2327 {K_CSI, (char_u *)"xCSI"}, 2328 {'|', (char_u *)"Bar"}, 2329 {'\\', (char_u *)"Bslash"}, 2330 {K_DEL, (char_u *)"Del"}, 2331 {K_DEL, (char_u *)"Delete"}, /* Alternative name */ 2332 {K_KDEL, (char_u *)"kDel"}, 2333 {K_UP, (char_u *)"Up"}, 2334 {K_DOWN, (char_u *)"Down"}, 2335 {K_LEFT, (char_u *)"Left"}, 2336 {K_RIGHT, (char_u *)"Right"}, 2337 {K_XUP, (char_u *)"xUp"}, 2338 {K_XDOWN, (char_u *)"xDown"}, 2339 {K_XLEFT, (char_u *)"xLeft"}, 2340 {K_XRIGHT, (char_u *)"xRight"}, 2341 2342 {K_F1, (char_u *)"F1"}, 2343 {K_F2, (char_u *)"F2"}, 2344 {K_F3, (char_u *)"F3"}, 2345 {K_F4, (char_u *)"F4"}, 2346 {K_F5, (char_u *)"F5"}, 2347 {K_F6, (char_u *)"F6"}, 2348 {K_F7, (char_u *)"F7"}, 2349 {K_F8, (char_u *)"F8"}, 2350 {K_F9, (char_u *)"F9"}, 2351 {K_F10, (char_u *)"F10"}, 2352 2353 {K_F11, (char_u *)"F11"}, 2354 {K_F12, (char_u *)"F12"}, 2355 {K_F13, (char_u *)"F13"}, 2356 {K_F14, (char_u *)"F14"}, 2357 {K_F15, (char_u *)"F15"}, 2358 {K_F16, (char_u *)"F16"}, 2359 {K_F17, (char_u *)"F17"}, 2360 {K_F18, (char_u *)"F18"}, 2361 {K_F19, (char_u *)"F19"}, 2362 {K_F20, (char_u *)"F20"}, 2363 2364 {K_F21, (char_u *)"F21"}, 2365 {K_F22, (char_u *)"F22"}, 2366 {K_F23, (char_u *)"F23"}, 2367 {K_F24, (char_u *)"F24"}, 2368 {K_F25, (char_u *)"F25"}, 2369 {K_F26, (char_u *)"F26"}, 2370 {K_F27, (char_u *)"F27"}, 2371 {K_F28, (char_u *)"F28"}, 2372 {K_F29, (char_u *)"F29"}, 2373 {K_F30, (char_u *)"F30"}, 2374 2375 {K_F31, (char_u *)"F31"}, 2376 {K_F32, (char_u *)"F32"}, 2377 {K_F33, (char_u *)"F33"}, 2378 {K_F34, (char_u *)"F34"}, 2379 {K_F35, (char_u *)"F35"}, 2380 {K_F36, (char_u *)"F36"}, 2381 {K_F37, (char_u *)"F37"}, 2382 2383 {K_XF1, (char_u *)"xF1"}, 2384 {K_XF2, (char_u *)"xF2"}, 2385 {K_XF3, (char_u *)"xF3"}, 2386 {K_XF4, (char_u *)"xF4"}, 2387 2388 {K_HELP, (char_u *)"Help"}, 2389 {K_UNDO, (char_u *)"Undo"}, 2390 {K_INS, (char_u *)"Insert"}, 2391 {K_INS, (char_u *)"Ins"}, /* Alternative name */ 2392 {K_KINS, (char_u *)"kInsert"}, 2393 {K_HOME, (char_u *)"Home"}, 2394 {K_KHOME, (char_u *)"kHome"}, 2395 {K_XHOME, (char_u *)"xHome"}, 2396 {K_ZHOME, (char_u *)"zHome"}, 2397 {K_END, (char_u *)"End"}, 2398 {K_KEND, (char_u *)"kEnd"}, 2399 {K_XEND, (char_u *)"xEnd"}, 2400 {K_ZEND, (char_u *)"zEnd"}, 2401 {K_PAGEUP, (char_u *)"PageUp"}, 2402 {K_PAGEDOWN, (char_u *)"PageDown"}, 2403 {K_KPAGEUP, (char_u *)"kPageUp"}, 2404 {K_KPAGEDOWN, (char_u *)"kPageDown"}, 2405 2406 {K_KPLUS, (char_u *)"kPlus"}, 2407 {K_KMINUS, (char_u *)"kMinus"}, 2408 {K_KDIVIDE, (char_u *)"kDivide"}, 2409 {K_KMULTIPLY, (char_u *)"kMultiply"}, 2410 {K_KENTER, (char_u *)"kEnter"}, 2411 {K_KPOINT, (char_u *)"kPoint"}, 2412 2413 {K_K0, (char_u *)"k0"}, 2414 {K_K1, (char_u *)"k1"}, 2415 {K_K2, (char_u *)"k2"}, 2416 {K_K3, (char_u *)"k3"}, 2417 {K_K4, (char_u *)"k4"}, 2418 {K_K5, (char_u *)"k5"}, 2419 {K_K6, (char_u *)"k6"}, 2420 {K_K7, (char_u *)"k7"}, 2421 {K_K8, (char_u *)"k8"}, 2422 {K_K9, (char_u *)"k9"}, 2423 2424 {'<', (char_u *)"lt"}, 2425 2426 {K_MOUSE, (char_u *)"Mouse"}, 2427 #ifdef FEAT_MOUSE_NET 2428 {K_NETTERM_MOUSE, (char_u *)"NetMouse"}, 2429 #endif 2430 #ifdef FEAT_MOUSE_DEC 2431 {K_DEC_MOUSE, (char_u *)"DecMouse"}, 2432 #endif 2433 #ifdef FEAT_MOUSE_JSB 2434 {K_JSBTERM_MOUSE, (char_u *)"JsbMouse"}, 2435 #endif 2436 #ifdef FEAT_MOUSE_PTERM 2437 {K_PTERM_MOUSE, (char_u *)"PtermMouse"}, 2438 #endif 2439 #ifdef FEAT_MOUSE_URXVT 2440 {K_URXVT_MOUSE, (char_u *)"UrxvtMouse"}, 2441 #endif 2442 #ifdef FEAT_MOUSE_SGR 2443 {K_SGR_MOUSE, (char_u *)"SgrMouse"}, 2444 #endif 2445 {K_LEFTMOUSE, (char_u *)"LeftMouse"}, 2446 {K_LEFTMOUSE_NM, (char_u *)"LeftMouseNM"}, 2447 {K_LEFTDRAG, (char_u *)"LeftDrag"}, 2448 {K_LEFTRELEASE, (char_u *)"LeftRelease"}, 2449 {K_LEFTRELEASE_NM, (char_u *)"LeftReleaseNM"}, 2450 {K_MIDDLEMOUSE, (char_u *)"MiddleMouse"}, 2451 {K_MIDDLEDRAG, (char_u *)"MiddleDrag"}, 2452 {K_MIDDLERELEASE, (char_u *)"MiddleRelease"}, 2453 {K_RIGHTMOUSE, (char_u *)"RightMouse"}, 2454 {K_RIGHTDRAG, (char_u *)"RightDrag"}, 2455 {K_RIGHTRELEASE, (char_u *)"RightRelease"}, 2456 {K_MOUSEDOWN, (char_u *)"ScrollWheelUp"}, 2457 {K_MOUSEUP, (char_u *)"ScrollWheelDown"}, 2458 {K_MOUSELEFT, (char_u *)"ScrollWheelRight"}, 2459 {K_MOUSERIGHT, (char_u *)"ScrollWheelLeft"}, 2460 {K_MOUSEDOWN, (char_u *)"MouseDown"}, /* OBSOLETE: Use */ 2461 {K_MOUSEUP, (char_u *)"MouseUp"}, /* ScrollWheelXXX instead */ 2462 {K_X1MOUSE, (char_u *)"X1Mouse"}, 2463 {K_X1DRAG, (char_u *)"X1Drag"}, 2464 {K_X1RELEASE, (char_u *)"X1Release"}, 2465 {K_X2MOUSE, (char_u *)"X2Mouse"}, 2466 {K_X2DRAG, (char_u *)"X2Drag"}, 2467 {K_X2RELEASE, (char_u *)"X2Release"}, 2468 {K_DROP, (char_u *)"Drop"}, 2469 {K_ZERO, (char_u *)"Nul"}, 2470 #ifdef FEAT_EVAL 2471 {K_SNR, (char_u *)"SNR"}, 2472 #endif 2473 {K_PLUG, (char_u *)"Plug"}, 2474 {K_CURSORHOLD, (char_u *)"CursorHold"}, 2475 {0, NULL} 2476 }; 2477 2478 #define KEY_NAMES_TABLE_LEN (sizeof(key_names_table) / sizeof(struct key_name_entry)) 2479 2480 #ifdef FEAT_MOUSE 2481 static struct mousetable 2482 { 2483 int pseudo_code; /* Code for pseudo mouse event */ 2484 int button; /* Which mouse button is it? */ 2485 int is_click; /* Is it a mouse button click event? */ 2486 int is_drag; /* Is it a mouse drag event? */ 2487 } mouse_table[] = 2488 { 2489 {(int)KE_LEFTMOUSE, MOUSE_LEFT, TRUE, FALSE}, 2490 #ifdef FEAT_GUI 2491 {(int)KE_LEFTMOUSE_NM, MOUSE_LEFT, TRUE, FALSE}, 2492 #endif 2493 {(int)KE_LEFTDRAG, MOUSE_LEFT, FALSE, TRUE}, 2494 {(int)KE_LEFTRELEASE, MOUSE_LEFT, FALSE, FALSE}, 2495 #ifdef FEAT_GUI 2496 {(int)KE_LEFTRELEASE_NM, MOUSE_LEFT, FALSE, FALSE}, 2497 #endif 2498 {(int)KE_MIDDLEMOUSE, MOUSE_MIDDLE, TRUE, FALSE}, 2499 {(int)KE_MIDDLEDRAG, MOUSE_MIDDLE, FALSE, TRUE}, 2500 {(int)KE_MIDDLERELEASE, MOUSE_MIDDLE, FALSE, FALSE}, 2501 {(int)KE_RIGHTMOUSE, MOUSE_RIGHT, TRUE, FALSE}, 2502 {(int)KE_RIGHTDRAG, MOUSE_RIGHT, FALSE, TRUE}, 2503 {(int)KE_RIGHTRELEASE, MOUSE_RIGHT, FALSE, FALSE}, 2504 {(int)KE_X1MOUSE, MOUSE_X1, TRUE, FALSE}, 2505 {(int)KE_X1DRAG, MOUSE_X1, FALSE, TRUE}, 2506 {(int)KE_X1RELEASE, MOUSE_X1, FALSE, FALSE}, 2507 {(int)KE_X2MOUSE, MOUSE_X2, TRUE, FALSE}, 2508 {(int)KE_X2DRAG, MOUSE_X2, FALSE, TRUE}, 2509 {(int)KE_X2RELEASE, MOUSE_X2, FALSE, FALSE}, 2510 /* DRAG without CLICK */ 2511 {(int)KE_IGNORE, MOUSE_RELEASE, FALSE, TRUE}, 2512 /* RELEASE without CLICK */ 2513 {(int)KE_IGNORE, MOUSE_RELEASE, FALSE, FALSE}, 2514 {0, 0, 0, 0}, 2515 }; 2516 #endif /* FEAT_MOUSE */ 2517 2518 /* 2519 * Return the modifier mask bit (MOD_MASK_*) which corresponds to the given 2520 * modifier name ('S' for Shift, 'C' for Ctrl etc). 2521 */ 2522 int 2523 name_to_mod_mask(c) 2524 int c; 2525 { 2526 int i; 2527 2528 c = TOUPPER_ASC(c); 2529 for (i = 0; mod_mask_table[i].mod_mask != 0; i++) 2530 if (c == mod_mask_table[i].name) 2531 return mod_mask_table[i].mod_flag; 2532 return 0; 2533 } 2534 2535 /* 2536 * Check if if there is a special key code for "key" that includes the 2537 * modifiers specified. 2538 */ 2539 int 2540 simplify_key(key, modifiers) 2541 int key; 2542 int *modifiers; 2543 { 2544 int i; 2545 int key0; 2546 int key1; 2547 2548 if (*modifiers & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT)) 2549 { 2550 /* TAB is a special case */ 2551 if (key == TAB && (*modifiers & MOD_MASK_SHIFT)) 2552 { 2553 *modifiers &= ~MOD_MASK_SHIFT; 2554 return K_S_TAB; 2555 } 2556 key0 = KEY2TERMCAP0(key); 2557 key1 = KEY2TERMCAP1(key); 2558 for (i = 0; modifier_keys_table[i] != NUL; i += MOD_KEYS_ENTRY_SIZE) 2559 if (key0 == modifier_keys_table[i + 3] 2560 && key1 == modifier_keys_table[i + 4] 2561 && (*modifiers & modifier_keys_table[i])) 2562 { 2563 *modifiers &= ~modifier_keys_table[i]; 2564 return TERMCAP2KEY(modifier_keys_table[i + 1], 2565 modifier_keys_table[i + 2]); 2566 } 2567 } 2568 return key; 2569 } 2570 2571 /* 2572 * Change <xHome> to <Home>, <xUp> to <Up>, etc. 2573 */ 2574 int 2575 handle_x_keys(key) 2576 int key; 2577 { 2578 switch (key) 2579 { 2580 case K_XUP: return K_UP; 2581 case K_XDOWN: return K_DOWN; 2582 case K_XLEFT: return K_LEFT; 2583 case K_XRIGHT: return K_RIGHT; 2584 case K_XHOME: return K_HOME; 2585 case K_ZHOME: return K_HOME; 2586 case K_XEND: return K_END; 2587 case K_ZEND: return K_END; 2588 case K_XF1: return K_F1; 2589 case K_XF2: return K_F2; 2590 case K_XF3: return K_F3; 2591 case K_XF4: return K_F4; 2592 case K_S_XF1: return K_S_F1; 2593 case K_S_XF2: return K_S_F2; 2594 case K_S_XF3: return K_S_F3; 2595 case K_S_XF4: return K_S_F4; 2596 } 2597 return key; 2598 } 2599 2600 /* 2601 * Return a string which contains the name of the given key when the given 2602 * modifiers are down. 2603 */ 2604 char_u * 2605 get_special_key_name(c, modifiers) 2606 int c; 2607 int modifiers; 2608 { 2609 static char_u string[MAX_KEY_NAME_LEN + 1]; 2610 2611 int i, idx; 2612 int table_idx; 2613 char_u *s; 2614 2615 string[0] = '<'; 2616 idx = 1; 2617 2618 /* Key that stands for a normal character. */ 2619 if (IS_SPECIAL(c) && KEY2TERMCAP0(c) == KS_KEY) 2620 c = KEY2TERMCAP1(c); 2621 2622 /* 2623 * Translate shifted special keys into unshifted keys and set modifier. 2624 * Same for CTRL and ALT modifiers. 2625 */ 2626 if (IS_SPECIAL(c)) 2627 { 2628 for (i = 0; modifier_keys_table[i] != 0; i += MOD_KEYS_ENTRY_SIZE) 2629 if ( KEY2TERMCAP0(c) == (int)modifier_keys_table[i + 1] 2630 && (int)KEY2TERMCAP1(c) == (int)modifier_keys_table[i + 2]) 2631 { 2632 modifiers |= modifier_keys_table[i]; 2633 c = TERMCAP2KEY(modifier_keys_table[i + 3], 2634 modifier_keys_table[i + 4]); 2635 break; 2636 } 2637 } 2638 2639 /* try to find the key in the special key table */ 2640 table_idx = find_special_key_in_table(c); 2641 2642 /* 2643 * When not a known special key, and not a printable character, try to 2644 * extract modifiers. 2645 */ 2646 if (c > 0 2647 #ifdef FEAT_MBYTE 2648 && (*mb_char2len)(c) == 1 2649 #endif 2650 ) 2651 { 2652 if (table_idx < 0 2653 && (!vim_isprintc(c) || (c & 0x7f) == ' ') 2654 && (c & 0x80)) 2655 { 2656 c &= 0x7f; 2657 modifiers |= MOD_MASK_ALT; 2658 /* try again, to find the un-alted key in the special key table */ 2659 table_idx = find_special_key_in_table(c); 2660 } 2661 if (table_idx < 0 && !vim_isprintc(c) && c < ' ') 2662 { 2663 #ifdef EBCDIC 2664 c = CtrlChar(c); 2665 #else 2666 c += '@'; 2667 #endif 2668 modifiers |= MOD_MASK_CTRL; 2669 } 2670 } 2671 2672 /* translate the modifier into a string */ 2673 for (i = 0; mod_mask_table[i].name != 'A'; i++) 2674 if ((modifiers & mod_mask_table[i].mod_mask) 2675 == mod_mask_table[i].mod_flag) 2676 { 2677 string[idx++] = mod_mask_table[i].name; 2678 string[idx++] = (char_u)'-'; 2679 } 2680 2681 if (table_idx < 0) /* unknown special key, may output t_xx */ 2682 { 2683 if (IS_SPECIAL(c)) 2684 { 2685 string[idx++] = 't'; 2686 string[idx++] = '_'; 2687 string[idx++] = KEY2TERMCAP0(c); 2688 string[idx++] = KEY2TERMCAP1(c); 2689 } 2690 /* Not a special key, only modifiers, output directly */ 2691 else 2692 { 2693 #ifdef FEAT_MBYTE 2694 if (has_mbyte && (*mb_char2len)(c) > 1) 2695 idx += (*mb_char2bytes)(c, string + idx); 2696 else 2697 #endif 2698 if (vim_isprintc(c)) 2699 string[idx++] = c; 2700 else 2701 { 2702 s = transchar(c); 2703 while (*s) 2704 string[idx++] = *s++; 2705 } 2706 } 2707 } 2708 else /* use name of special key */ 2709 { 2710 STRCPY(string + idx, key_names_table[table_idx].name); 2711 idx = (int)STRLEN(string); 2712 } 2713 string[idx++] = '>'; 2714 string[idx] = NUL; 2715 return string; 2716 } 2717 2718 /* 2719 * Try translating a <> name at (*srcp)[] to dst[]. 2720 * Return the number of characters added to dst[], zero for no match. 2721 * If there is a match, srcp is advanced to after the <> name. 2722 * dst[] must be big enough to hold the result (up to six characters)! 2723 */ 2724 int 2725 trans_special(srcp, dst, keycode) 2726 char_u **srcp; 2727 char_u *dst; 2728 int keycode; /* prefer key code, e.g. K_DEL instead of DEL */ 2729 { 2730 int modifiers = 0; 2731 int key; 2732 int dlen = 0; 2733 2734 key = find_special_key(srcp, &modifiers, keycode, FALSE); 2735 if (key == 0) 2736 return 0; 2737 2738 /* Put the appropriate modifier in a string */ 2739 if (modifiers != 0) 2740 { 2741 dst[dlen++] = K_SPECIAL; 2742 dst[dlen++] = KS_MODIFIER; 2743 dst[dlen++] = modifiers; 2744 } 2745 2746 if (IS_SPECIAL(key)) 2747 { 2748 dst[dlen++] = K_SPECIAL; 2749 dst[dlen++] = KEY2TERMCAP0(key); 2750 dst[dlen++] = KEY2TERMCAP1(key); 2751 } 2752 #ifdef FEAT_MBYTE 2753 else if (has_mbyte && !keycode) 2754 dlen += (*mb_char2bytes)(key, dst + dlen); 2755 #endif 2756 else if (keycode) 2757 dlen = (int)(add_char2buf(key, dst + dlen) - dst); 2758 else 2759 dst[dlen++] = key; 2760 2761 return dlen; 2762 } 2763 2764 /* 2765 * Try translating a <> name at (*srcp)[], return the key and modifiers. 2766 * srcp is advanced to after the <> name. 2767 * returns 0 if there is no match. 2768 */ 2769 int 2770 find_special_key(srcp, modp, keycode, keep_x_key) 2771 char_u **srcp; 2772 int *modp; 2773 int keycode; /* prefer key code, e.g. K_DEL instead of DEL */ 2774 int keep_x_key; /* don't translate xHome to Home key */ 2775 { 2776 char_u *last_dash; 2777 char_u *end_of_name; 2778 char_u *src; 2779 char_u *bp; 2780 int modifiers; 2781 int bit; 2782 int key; 2783 unsigned long n; 2784 int l; 2785 2786 src = *srcp; 2787 if (src[0] != '<') 2788 return 0; 2789 2790 /* Find end of modifier list */ 2791 last_dash = src; 2792 for (bp = src + 1; *bp == '-' || vim_isIDc(*bp); bp++) 2793 { 2794 if (*bp == '-') 2795 { 2796 last_dash = bp; 2797 if (bp[1] != NUL) 2798 { 2799 #ifdef FEAT_MBYTE 2800 if (has_mbyte) 2801 l = mb_ptr2len(bp + 1); 2802 else 2803 #endif 2804 l = 1; 2805 if (bp[l + 1] == '>') 2806 bp += l; /* anything accepted, like <C-?> */ 2807 } 2808 } 2809 if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3]) 2810 bp += 3; /* skip t_xx, xx may be '-' or '>' */ 2811 else if (STRNICMP(bp, "char-", 5) == 0) 2812 { 2813 vim_str2nr(bp + 5, NULL, &l, TRUE, TRUE, NULL, NULL); 2814 bp += l + 5; 2815 break; 2816 } 2817 } 2818 2819 if (*bp == '>') /* found matching '>' */ 2820 { 2821 end_of_name = bp + 1; 2822 2823 /* Which modifiers are given? */ 2824 modifiers = 0x0; 2825 for (bp = src + 1; bp < last_dash; bp++) 2826 { 2827 if (*bp != '-') 2828 { 2829 bit = name_to_mod_mask(*bp); 2830 if (bit == 0x0) 2831 break; /* Illegal modifier name */ 2832 modifiers |= bit; 2833 } 2834 } 2835 2836 /* 2837 * Legal modifier name. 2838 */ 2839 if (bp >= last_dash) 2840 { 2841 if (STRNICMP(last_dash + 1, "char-", 5) == 0 2842 && VIM_ISDIGIT(last_dash[6])) 2843 { 2844 /* <Char-123> or <Char-033> or <Char-0x33> */ 2845 vim_str2nr(last_dash + 6, NULL, NULL, TRUE, TRUE, NULL, &n); 2846 key = (int)n; 2847 } 2848 else 2849 { 2850 /* 2851 * Modifier with single letter, or special key name. 2852 */ 2853 #ifdef FEAT_MBYTE 2854 if (has_mbyte) 2855 l = mb_ptr2len(last_dash + 1); 2856 else 2857 #endif 2858 l = 1; 2859 if (modifiers != 0 && last_dash[l + 1] == '>') 2860 key = PTR2CHAR(last_dash + 1); 2861 else 2862 { 2863 key = get_special_key_code(last_dash + 1); 2864 if (!keep_x_key) 2865 key = handle_x_keys(key); 2866 } 2867 } 2868 2869 /* 2870 * get_special_key_code() may return NUL for invalid 2871 * special key name. 2872 */ 2873 if (key != NUL) 2874 { 2875 /* 2876 * Only use a modifier when there is no special key code that 2877 * includes the modifier. 2878 */ 2879 key = simplify_key(key, &modifiers); 2880 2881 if (!keycode) 2882 { 2883 /* don't want keycode, use single byte code */ 2884 if (key == K_BS) 2885 key = BS; 2886 else if (key == K_DEL || key == K_KDEL) 2887 key = DEL; 2888 } 2889 2890 /* 2891 * Normal Key with modifier: Try to make a single byte code. 2892 */ 2893 if (!IS_SPECIAL(key)) 2894 key = extract_modifiers(key, &modifiers); 2895 2896 *modp = modifiers; 2897 *srcp = end_of_name; 2898 return key; 2899 } 2900 } 2901 } 2902 return 0; 2903 } 2904 2905 /* 2906 * Try to include modifiers in the key. 2907 * Changes "Shift-a" to 'A', "Alt-A" to 0xc0, etc. 2908 */ 2909 int 2910 extract_modifiers(key, modp) 2911 int key; 2912 int *modp; 2913 { 2914 int modifiers = *modp; 2915 2916 #ifdef MACOS 2917 /* Command-key really special, no fancynest */ 2918 if (!(modifiers & MOD_MASK_CMD)) 2919 #endif 2920 if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key)) 2921 { 2922 key = TOUPPER_ASC(key); 2923 modifiers &= ~MOD_MASK_SHIFT; 2924 } 2925 if ((modifiers & MOD_MASK_CTRL) 2926 #ifdef EBCDIC 2927 /* * TODO: EBCDIC Better use: 2928 * && (Ctrl_chr(key) || key == '?') 2929 * ??? */ 2930 && strchr("?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_", key) 2931 != NULL 2932 #else 2933 && ((key >= '?' && key <= '_') || ASCII_ISALPHA(key)) 2934 #endif 2935 ) 2936 { 2937 key = Ctrl_chr(key); 2938 modifiers &= ~MOD_MASK_CTRL; 2939 /* <C-@> is <Nul> */ 2940 if (key == 0) 2941 key = K_ZERO; 2942 } 2943 #ifdef MACOS 2944 /* Command-key really special, no fancynest */ 2945 if (!(modifiers & MOD_MASK_CMD)) 2946 #endif 2947 if ((modifiers & MOD_MASK_ALT) && key < 0x80 2948 #ifdef FEAT_MBYTE 2949 && !enc_dbcs /* avoid creating a lead byte */ 2950 #endif 2951 ) 2952 { 2953 key |= 0x80; 2954 modifiers &= ~MOD_MASK_ALT; /* remove the META modifier */ 2955 } 2956 2957 *modp = modifiers; 2958 return key; 2959 } 2960 2961 /* 2962 * Try to find key "c" in the special key table. 2963 * Return the index when found, -1 when not found. 2964 */ 2965 int 2966 find_special_key_in_table(c) 2967 int c; 2968 { 2969 int i; 2970 2971 for (i = 0; key_names_table[i].name != NULL; i++) 2972 if (c == key_names_table[i].key) 2973 break; 2974 if (key_names_table[i].name == NULL) 2975 i = -1; 2976 return i; 2977 } 2978 2979 /* 2980 * Find the special key with the given name (the given string does not have to 2981 * end with NUL, the name is assumed to end before the first non-idchar). 2982 * If the name starts with "t_" the next two characters are interpreted as a 2983 * termcap name. 2984 * Return the key code, or 0 if not found. 2985 */ 2986 int 2987 get_special_key_code(name) 2988 char_u *name; 2989 { 2990 char_u *table_name; 2991 char_u string[3]; 2992 int i, j; 2993 2994 /* 2995 * If it's <t_xx> we get the code for xx from the termcap 2996 */ 2997 if (name[0] == 't' && name[1] == '_' && name[2] != NUL && name[3] != NUL) 2998 { 2999 string[0] = name[2]; 3000 string[1] = name[3]; 3001 string[2] = NUL; 3002 if (add_termcap_entry(string, FALSE) == OK) 3003 return TERMCAP2KEY(name[2], name[3]); 3004 } 3005 else 3006 for (i = 0; key_names_table[i].name != NULL; i++) 3007 { 3008 table_name = key_names_table[i].name; 3009 for (j = 0; vim_isIDc(name[j]) && table_name[j] != NUL; j++) 3010 if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j])) 3011 break; 3012 if (!vim_isIDc(name[j]) && table_name[j] == NUL) 3013 return key_names_table[i].key; 3014 } 3015 return 0; 3016 } 3017 3018 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 3019 char_u * 3020 get_key_name(i) 3021 int i; 3022 { 3023 if (i >= (int)KEY_NAMES_TABLE_LEN) 3024 return NULL; 3025 return key_names_table[i].name; 3026 } 3027 #endif 3028 3029 #if defined(FEAT_MOUSE) || defined(PROTO) 3030 /* 3031 * Look up the given mouse code to return the relevant information in the other 3032 * arguments. Return which button is down or was released. 3033 */ 3034 int 3035 get_mouse_button(code, is_click, is_drag) 3036 int code; 3037 int *is_click; 3038 int *is_drag; 3039 { 3040 int i; 3041 3042 for (i = 0; mouse_table[i].pseudo_code; i++) 3043 if (code == mouse_table[i].pseudo_code) 3044 { 3045 *is_click = mouse_table[i].is_click; 3046 *is_drag = mouse_table[i].is_drag; 3047 return mouse_table[i].button; 3048 } 3049 return 0; /* Shouldn't get here */ 3050 } 3051 3052 /* 3053 * Return the appropriate pseudo mouse event token (KE_LEFTMOUSE etc) based on 3054 * the given information about which mouse button is down, and whether the 3055 * mouse was clicked, dragged or released. 3056 */ 3057 int 3058 get_pseudo_mouse_code(button, is_click, is_drag) 3059 int button; /* eg MOUSE_LEFT */ 3060 int is_click; 3061 int is_drag; 3062 { 3063 int i; 3064 3065 for (i = 0; mouse_table[i].pseudo_code; i++) 3066 if (button == mouse_table[i].button 3067 && is_click == mouse_table[i].is_click 3068 && is_drag == mouse_table[i].is_drag) 3069 { 3070 #ifdef FEAT_GUI 3071 /* Trick: a non mappable left click and release has mouse_col -1 3072 * or added MOUSE_COLOFF. Used for 'mousefocus' in 3073 * gui_mouse_moved() */ 3074 if (mouse_col < 0 || mouse_col > MOUSE_COLOFF) 3075 { 3076 if (mouse_col < 0) 3077 mouse_col = 0; 3078 else 3079 mouse_col -= MOUSE_COLOFF; 3080 if (mouse_table[i].pseudo_code == (int)KE_LEFTMOUSE) 3081 return (int)KE_LEFTMOUSE_NM; 3082 if (mouse_table[i].pseudo_code == (int)KE_LEFTRELEASE) 3083 return (int)KE_LEFTRELEASE_NM; 3084 } 3085 #endif 3086 return mouse_table[i].pseudo_code; 3087 } 3088 return (int)KE_IGNORE; /* not recognized, ignore it */ 3089 } 3090 #endif /* FEAT_MOUSE */ 3091 3092 /* 3093 * Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC. 3094 */ 3095 int 3096 get_fileformat(buf) 3097 buf_T *buf; 3098 { 3099 int c = *buf->b_p_ff; 3100 3101 if (buf->b_p_bin || c == 'u') 3102 return EOL_UNIX; 3103 if (c == 'm') 3104 return EOL_MAC; 3105 return EOL_DOS; 3106 } 3107 3108 /* 3109 * Like get_fileformat(), but override 'fileformat' with "p" for "++opt=val" 3110 * argument. 3111 */ 3112 int 3113 get_fileformat_force(buf, eap) 3114 buf_T *buf; 3115 exarg_T *eap; /* can be NULL! */ 3116 { 3117 int c; 3118 3119 if (eap != NULL && eap->force_ff != 0) 3120 c = eap->cmd[eap->force_ff]; 3121 else 3122 { 3123 if ((eap != NULL && eap->force_bin != 0) 3124 ? (eap->force_bin == FORCE_BIN) : buf->b_p_bin) 3125 return EOL_UNIX; 3126 c = *buf->b_p_ff; 3127 } 3128 if (c == 'u') 3129 return EOL_UNIX; 3130 if (c == 'm') 3131 return EOL_MAC; 3132 return EOL_DOS; 3133 } 3134 3135 /* 3136 * Set the current end-of-line type to EOL_DOS, EOL_UNIX or EOL_MAC. 3137 * Sets both 'textmode' and 'fileformat'. 3138 * Note: Does _not_ set global value of 'textmode'! 3139 */ 3140 void 3141 set_fileformat(t, opt_flags) 3142 int t; 3143 int opt_flags; /* OPT_LOCAL and/or OPT_GLOBAL */ 3144 { 3145 char *p = NULL; 3146 3147 switch (t) 3148 { 3149 case EOL_DOS: 3150 p = FF_DOS; 3151 curbuf->b_p_tx = TRUE; 3152 break; 3153 case EOL_UNIX: 3154 p = FF_UNIX; 3155 curbuf->b_p_tx = FALSE; 3156 break; 3157 case EOL_MAC: 3158 p = FF_MAC; 3159 curbuf->b_p_tx = FALSE; 3160 break; 3161 } 3162 if (p != NULL) 3163 set_string_option_direct((char_u *)"ff", -1, (char_u *)p, 3164 OPT_FREE | opt_flags, 0); 3165 3166 #ifdef FEAT_WINDOWS 3167 /* This may cause the buffer to become (un)modified. */ 3168 check_status(curbuf); 3169 redraw_tabline = TRUE; 3170 #endif 3171 #ifdef FEAT_TITLE 3172 need_maketitle = TRUE; /* set window title later */ 3173 #endif 3174 } 3175 3176 /* 3177 * Return the default fileformat from 'fileformats'. 3178 */ 3179 int 3180 default_fileformat() 3181 { 3182 switch (*p_ffs) 3183 { 3184 case 'm': return EOL_MAC; 3185 case 'd': return EOL_DOS; 3186 } 3187 return EOL_UNIX; 3188 } 3189 3190 /* 3191 * Call shell. Calls mch_call_shell, with 'shellxquote' added. 3192 */ 3193 int 3194 call_shell(cmd, opt) 3195 char_u *cmd; 3196 int opt; 3197 { 3198 char_u *ncmd; 3199 int retval; 3200 #ifdef FEAT_PROFILE 3201 proftime_T wait_time; 3202 #endif 3203 3204 if (p_verbose > 3) 3205 { 3206 verbose_enter(); 3207 smsg((char_u *)_("Calling shell to execute: \"%s\""), 3208 cmd == NULL ? p_sh : cmd); 3209 out_char('\n'); 3210 cursor_on(); 3211 verbose_leave(); 3212 } 3213 3214 #ifdef FEAT_PROFILE 3215 if (do_profiling == PROF_YES) 3216 prof_child_enter(&wait_time); 3217 #endif 3218 3219 if (*p_sh == NUL) 3220 { 3221 EMSG(_(e_shellempty)); 3222 retval = -1; 3223 } 3224 else 3225 { 3226 #ifdef FEAT_GUI_MSWIN 3227 /* Don't hide the pointer while executing a shell command. */ 3228 gui_mch_mousehide(FALSE); 3229 #endif 3230 #ifdef FEAT_GUI 3231 ++hold_gui_events; 3232 #endif 3233 /* The external command may update a tags file, clear cached tags. */ 3234 tag_freematch(); 3235 3236 if (cmd == NULL || *p_sxq == NUL) 3237 retval = mch_call_shell(cmd, opt); 3238 else 3239 { 3240 char_u *ecmd = cmd; 3241 3242 if (*p_sxe != NUL && STRCMP(p_sxq, "(") == 0) 3243 { 3244 ecmd = vim_strsave_escaped_ext(cmd, p_sxe, '^', FALSE); 3245 if (ecmd == NULL) 3246 ecmd = cmd; 3247 } 3248 ncmd = alloc((unsigned)(STRLEN(ecmd) + STRLEN(p_sxq) * 2 + 1)); 3249 if (ncmd != NULL) 3250 { 3251 STRCPY(ncmd, p_sxq); 3252 STRCAT(ncmd, ecmd); 3253 /* When 'shellxquote' is ( append ). 3254 * When 'shellxquote' is "( append )". */ 3255 STRCAT(ncmd, STRCMP(p_sxq, "(") == 0 ? (char_u *)")" 3256 : STRCMP(p_sxq, "\"(") == 0 ? (char_u *)")\"" 3257 : p_sxq); 3258 retval = mch_call_shell(ncmd, opt); 3259 vim_free(ncmd); 3260 } 3261 else 3262 retval = -1; 3263 if (ecmd != cmd) 3264 vim_free(ecmd); 3265 } 3266 #ifdef FEAT_GUI 3267 --hold_gui_events; 3268 #endif 3269 /* 3270 * Check the window size, in case it changed while executing the 3271 * external command. 3272 */ 3273 shell_resized_check(); 3274 } 3275 3276 #ifdef FEAT_EVAL 3277 set_vim_var_nr(VV_SHELL_ERROR, (long)retval); 3278 # ifdef FEAT_PROFILE 3279 if (do_profiling == PROF_YES) 3280 prof_child_exit(&wait_time); 3281 # endif 3282 #endif 3283 3284 return retval; 3285 } 3286 3287 /* 3288 * VISUAL, SELECTMODE and OP_PENDING State are never set, they are equal to 3289 * NORMAL State with a condition. This function returns the real State. 3290 */ 3291 int 3292 get_real_state() 3293 { 3294 if (State & NORMAL) 3295 { 3296 if (VIsual_active) 3297 { 3298 if (VIsual_select) 3299 return SELECTMODE; 3300 return VISUAL; 3301 } 3302 else if (finish_op) 3303 return OP_PENDING; 3304 } 3305 return State; 3306 } 3307 3308 #if defined(FEAT_MBYTE) || defined(PROTO) 3309 /* 3310 * Return TRUE if "p" points to just after a path separator. 3311 * Takes care of multi-byte characters. 3312 * "b" must point to the start of the file name 3313 */ 3314 int 3315 after_pathsep(b, p) 3316 char_u *b; 3317 char_u *p; 3318 { 3319 return p > b && vim_ispathsep(p[-1]) 3320 && (!has_mbyte || (*mb_head_off)(b, p - 1) == 0); 3321 } 3322 #endif 3323 3324 /* 3325 * Return TRUE if file names "f1" and "f2" are in the same directory. 3326 * "f1" may be a short name, "f2" must be a full path. 3327 */ 3328 int 3329 same_directory(f1, f2) 3330 char_u *f1; 3331 char_u *f2; 3332 { 3333 char_u ffname[MAXPATHL]; 3334 char_u *t1; 3335 char_u *t2; 3336 3337 /* safety check */ 3338 if (f1 == NULL || f2 == NULL) 3339 return FALSE; 3340 3341 (void)vim_FullName(f1, ffname, MAXPATHL, FALSE); 3342 t1 = gettail_sep(ffname); 3343 t2 = gettail_sep(f2); 3344 return (t1 - ffname == t2 - f2 3345 && pathcmp((char *)ffname, (char *)f2, (int)(t1 - ffname)) == 0); 3346 } 3347 3348 #if defined(FEAT_SESSION) || defined(MSWIN) || defined(FEAT_GUI_MAC) \ 3349 || ((defined(FEAT_GUI_GTK)) \ 3350 && ( defined(FEAT_WINDOWS) || defined(FEAT_DND)) ) \ 3351 || defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) \ 3352 || defined(PROTO) 3353 /* 3354 * Change to a file's directory. 3355 * Caller must call shorten_fnames()! 3356 * Return OK or FAIL. 3357 */ 3358 int 3359 vim_chdirfile(fname) 3360 char_u *fname; 3361 { 3362 char_u dir[MAXPATHL]; 3363 3364 vim_strncpy(dir, fname, MAXPATHL - 1); 3365 *gettail_sep(dir) = NUL; 3366 return mch_chdir((char *)dir) == 0 ? OK : FAIL; 3367 } 3368 #endif 3369 3370 #if defined(STAT_IGNORES_SLASH) || defined(PROTO) 3371 /* 3372 * Check if "name" ends in a slash and is not a directory. 3373 * Used for systems where stat() ignores a trailing slash on a file name. 3374 * The Vim code assumes a trailing slash is only ignored for a directory. 3375 */ 3376 int 3377 illegal_slash(name) 3378 char *name; 3379 { 3380 if (name[0] == NUL) 3381 return FALSE; /* no file name is not illegal */ 3382 if (name[strlen(name) - 1] != '/') 3383 return FALSE; /* no trailing slash */ 3384 if (mch_isdir((char_u *)name)) 3385 return FALSE; /* trailing slash for a directory */ 3386 return TRUE; 3387 } 3388 #endif 3389 3390 #if defined(CURSOR_SHAPE) || defined(PROTO) 3391 3392 /* 3393 * Handling of cursor and mouse pointer shapes in various modes. 3394 */ 3395 3396 cursorentry_T shape_table[SHAPE_IDX_COUNT] = 3397 { 3398 /* The values will be filled in from the 'guicursor' and 'mouseshape' 3399 * defaults when Vim starts. 3400 * Adjust the SHAPE_IDX_ defines when making changes! */ 3401 {0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE}, 3402 {0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE}, 3403 {0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE}, 3404 {0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE}, 3405 {0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE}, 3406 {0, 0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE}, 3407 {0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE}, 3408 {0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE}, 3409 {0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE}, 3410 {0, 0, 0, 0L, 0L, 0L, 0, 0, "e", SHAPE_MOUSE}, 3411 {0, 0, 0, 0L, 0L, 0L, 0, 0, "s", SHAPE_MOUSE}, 3412 {0, 0, 0, 0L, 0L, 0L, 0, 0, "sd", SHAPE_MOUSE}, 3413 {0, 0, 0, 0L, 0L, 0L, 0, 0, "vs", SHAPE_MOUSE}, 3414 {0, 0, 0, 0L, 0L, 0L, 0, 0, "vd", SHAPE_MOUSE}, 3415 {0, 0, 0, 0L, 0L, 0L, 0, 0, "m", SHAPE_MOUSE}, 3416 {0, 0, 0, 0L, 0L, 0L, 0, 0, "ml", SHAPE_MOUSE}, 3417 {0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR}, 3418 }; 3419 3420 #ifdef FEAT_MOUSESHAPE 3421 /* 3422 * Table with names for mouse shapes. Keep in sync with all the tables for 3423 * mch_set_mouse_shape()!. 3424 */ 3425 static char * mshape_names[] = 3426 { 3427 "arrow", /* default, must be the first one */ 3428 "blank", /* hidden */ 3429 "beam", 3430 "updown", 3431 "udsizing", 3432 "leftright", 3433 "lrsizing", 3434 "busy", 3435 "no", 3436 "crosshair", 3437 "hand1", 3438 "hand2", 3439 "pencil", 3440 "question", 3441 "rightup-arrow", 3442 "up-arrow", 3443 NULL 3444 }; 3445 #endif 3446 3447 /* 3448 * Parse the 'guicursor' option ("what" is SHAPE_CURSOR) or 'mouseshape' 3449 * ("what" is SHAPE_MOUSE). 3450 * Returns error message for an illegal option, NULL otherwise. 3451 */ 3452 char_u * 3453 parse_shape_opt(what) 3454 int what; 3455 { 3456 char_u *modep; 3457 char_u *colonp; 3458 char_u *commap; 3459 char_u *slashp; 3460 char_u *p, *endp; 3461 int idx = 0; /* init for GCC */ 3462 int all_idx; 3463 int len; 3464 int i; 3465 long n; 3466 int found_ve = FALSE; /* found "ve" flag */ 3467 int round; 3468 3469 /* 3470 * First round: check for errors; second round: do it for real. 3471 */ 3472 for (round = 1; round <= 2; ++round) 3473 { 3474 /* 3475 * Repeat for all comma separated parts. 3476 */ 3477 #ifdef FEAT_MOUSESHAPE 3478 if (what == SHAPE_MOUSE) 3479 modep = p_mouseshape; 3480 else 3481 #endif 3482 modep = p_guicursor; 3483 while (*modep != NUL) 3484 { 3485 colonp = vim_strchr(modep, ':'); 3486 if (colonp == NULL) 3487 return (char_u *)N_("E545: Missing colon"); 3488 if (colonp == modep) 3489 return (char_u *)N_("E546: Illegal mode"); 3490 commap = vim_strchr(modep, ','); 3491 3492 /* 3493 * Repeat for all mode's before the colon. 3494 * For the 'a' mode, we loop to handle all the modes. 3495 */ 3496 all_idx = -1; 3497 while (modep < colonp || all_idx >= 0) 3498 { 3499 if (all_idx < 0) 3500 { 3501 /* Find the mode. */ 3502 if (modep[1] == '-' || modep[1] == ':') 3503 len = 1; 3504 else 3505 len = 2; 3506 if (len == 1 && TOLOWER_ASC(modep[0]) == 'a') 3507 all_idx = SHAPE_IDX_COUNT - 1; 3508 else 3509 { 3510 for (idx = 0; idx < SHAPE_IDX_COUNT; ++idx) 3511 if (STRNICMP(modep, shape_table[idx].name, len) 3512 == 0) 3513 break; 3514 if (idx == SHAPE_IDX_COUNT 3515 || (shape_table[idx].used_for & what) == 0) 3516 return (char_u *)N_("E546: Illegal mode"); 3517 if (len == 2 && modep[0] == 'v' && modep[1] == 'e') 3518 found_ve = TRUE; 3519 } 3520 modep += len + 1; 3521 } 3522 3523 if (all_idx >= 0) 3524 idx = all_idx--; 3525 else if (round == 2) 3526 { 3527 #ifdef FEAT_MOUSESHAPE 3528 if (what == SHAPE_MOUSE) 3529 { 3530 /* Set the default, for the missing parts */ 3531 shape_table[idx].mshape = 0; 3532 } 3533 else 3534 #endif 3535 { 3536 /* Set the defaults, for the missing parts */ 3537 shape_table[idx].shape = SHAPE_BLOCK; 3538 shape_table[idx].blinkwait = 700L; 3539 shape_table[idx].blinkon = 400L; 3540 shape_table[idx].blinkoff = 250L; 3541 } 3542 } 3543 3544 /* Parse the part after the colon */ 3545 for (p = colonp + 1; *p && *p != ','; ) 3546 { 3547 #ifdef FEAT_MOUSESHAPE 3548 if (what == SHAPE_MOUSE) 3549 { 3550 for (i = 0; ; ++i) 3551 { 3552 if (mshape_names[i] == NULL) 3553 { 3554 if (!VIM_ISDIGIT(*p)) 3555 return (char_u *)N_("E547: Illegal mouseshape"); 3556 if (round == 2) 3557 shape_table[idx].mshape = 3558 getdigits(&p) + MSHAPE_NUMBERED; 3559 else 3560 (void)getdigits(&p); 3561 break; 3562 } 3563 len = (int)STRLEN(mshape_names[i]); 3564 if (STRNICMP(p, mshape_names[i], len) == 0) 3565 { 3566 if (round == 2) 3567 shape_table[idx].mshape = i; 3568 p += len; 3569 break; 3570 } 3571 } 3572 } 3573 else /* if (what == SHAPE_MOUSE) */ 3574 #endif 3575 { 3576 /* 3577 * First handle the ones with a number argument. 3578 */ 3579 i = *p; 3580 len = 0; 3581 if (STRNICMP(p, "ver", 3) == 0) 3582 len = 3; 3583 else if (STRNICMP(p, "hor", 3) == 0) 3584 len = 3; 3585 else if (STRNICMP(p, "blinkwait", 9) == 0) 3586 len = 9; 3587 else if (STRNICMP(p, "blinkon", 7) == 0) 3588 len = 7; 3589 else if (STRNICMP(p, "blinkoff", 8) == 0) 3590 len = 8; 3591 if (len != 0) 3592 { 3593 p += len; 3594 if (!VIM_ISDIGIT(*p)) 3595 return (char_u *)N_("E548: digit expected"); 3596 n = getdigits(&p); 3597 if (len == 3) /* "ver" or "hor" */ 3598 { 3599 if (n == 0) 3600 return (char_u *)N_("E549: Illegal percentage"); 3601 if (round == 2) 3602 { 3603 if (TOLOWER_ASC(i) == 'v') 3604 shape_table[idx].shape = SHAPE_VER; 3605 else 3606 shape_table[idx].shape = SHAPE_HOR; 3607 shape_table[idx].percentage = n; 3608 } 3609 } 3610 else if (round == 2) 3611 { 3612 if (len == 9) 3613 shape_table[idx].blinkwait = n; 3614 else if (len == 7) 3615 shape_table[idx].blinkon = n; 3616 else 3617 shape_table[idx].blinkoff = n; 3618 } 3619 } 3620 else if (STRNICMP(p, "block", 5) == 0) 3621 { 3622 if (round == 2) 3623 shape_table[idx].shape = SHAPE_BLOCK; 3624 p += 5; 3625 } 3626 else /* must be a highlight group name then */ 3627 { 3628 endp = vim_strchr(p, '-'); 3629 if (commap == NULL) /* last part */ 3630 { 3631 if (endp == NULL) 3632 endp = p + STRLEN(p); /* find end of part */ 3633 } 3634 else if (endp > commap || endp == NULL) 3635 endp = commap; 3636 slashp = vim_strchr(p, '/'); 3637 if (slashp != NULL && slashp < endp) 3638 { 3639 /* "group/langmap_group" */ 3640 i = syn_check_group(p, (int)(slashp - p)); 3641 p = slashp + 1; 3642 } 3643 if (round == 2) 3644 { 3645 shape_table[idx].id = syn_check_group(p, 3646 (int)(endp - p)); 3647 shape_table[idx].id_lm = shape_table[idx].id; 3648 if (slashp != NULL && slashp < endp) 3649 shape_table[idx].id = i; 3650 } 3651 p = endp; 3652 } 3653 } /* if (what != SHAPE_MOUSE) */ 3654 3655 if (*p == '-') 3656 ++p; 3657 } 3658 } 3659 modep = p; 3660 if (*modep == ',') 3661 ++modep; 3662 } 3663 } 3664 3665 /* If the 's' flag is not given, use the 'v' cursor for 's' */ 3666 if (!found_ve) 3667 { 3668 #ifdef FEAT_MOUSESHAPE 3669 if (what == SHAPE_MOUSE) 3670 { 3671 shape_table[SHAPE_IDX_VE].mshape = shape_table[SHAPE_IDX_V].mshape; 3672 } 3673 else 3674 #endif 3675 { 3676 shape_table[SHAPE_IDX_VE].shape = shape_table[SHAPE_IDX_V].shape; 3677 shape_table[SHAPE_IDX_VE].percentage = 3678 shape_table[SHAPE_IDX_V].percentage; 3679 shape_table[SHAPE_IDX_VE].blinkwait = 3680 shape_table[SHAPE_IDX_V].blinkwait; 3681 shape_table[SHAPE_IDX_VE].blinkon = 3682 shape_table[SHAPE_IDX_V].blinkon; 3683 shape_table[SHAPE_IDX_VE].blinkoff = 3684 shape_table[SHAPE_IDX_V].blinkoff; 3685 shape_table[SHAPE_IDX_VE].id = shape_table[SHAPE_IDX_V].id; 3686 shape_table[SHAPE_IDX_VE].id_lm = shape_table[SHAPE_IDX_V].id_lm; 3687 } 3688 } 3689 3690 return NULL; 3691 } 3692 3693 # if defined(MCH_CURSOR_SHAPE) || defined(FEAT_GUI) \ 3694 || defined(FEAT_MOUSESHAPE) || defined(PROTO) 3695 /* 3696 * Return the index into shape_table[] for the current mode. 3697 * When "mouse" is TRUE, consider indexes valid for the mouse pointer. 3698 */ 3699 int 3700 get_shape_idx(mouse) 3701 int mouse; 3702 { 3703 #ifdef FEAT_MOUSESHAPE 3704 if (mouse && (State == HITRETURN || State == ASKMORE)) 3705 { 3706 # ifdef FEAT_GUI 3707 int x, y; 3708 gui_mch_getmouse(&x, &y); 3709 if (Y_2_ROW(y) == Rows - 1) 3710 return SHAPE_IDX_MOREL; 3711 # endif 3712 return SHAPE_IDX_MORE; 3713 } 3714 if (mouse && drag_status_line) 3715 return SHAPE_IDX_SDRAG; 3716 # ifdef FEAT_VERTSPLIT 3717 if (mouse && drag_sep_line) 3718 return SHAPE_IDX_VDRAG; 3719 # endif 3720 #endif 3721 if (!mouse && State == SHOWMATCH) 3722 return SHAPE_IDX_SM; 3723 #ifdef FEAT_VREPLACE 3724 if (State & VREPLACE_FLAG) 3725 return SHAPE_IDX_R; 3726 #endif 3727 if (State & REPLACE_FLAG) 3728 return SHAPE_IDX_R; 3729 if (State & INSERT) 3730 return SHAPE_IDX_I; 3731 if (State & CMDLINE) 3732 { 3733 if (cmdline_at_end()) 3734 return SHAPE_IDX_C; 3735 if (cmdline_overstrike()) 3736 return SHAPE_IDX_CR; 3737 return SHAPE_IDX_CI; 3738 } 3739 if (finish_op) 3740 return SHAPE_IDX_O; 3741 if (VIsual_active) 3742 { 3743 if (*p_sel == 'e') 3744 return SHAPE_IDX_VE; 3745 else 3746 return SHAPE_IDX_V; 3747 } 3748 return SHAPE_IDX_N; 3749 } 3750 #endif 3751 3752 # if defined(FEAT_MOUSESHAPE) || defined(PROTO) 3753 static int old_mouse_shape = 0; 3754 3755 /* 3756 * Set the mouse shape: 3757 * If "shape" is -1, use shape depending on the current mode, 3758 * depending on the current state. 3759 * If "shape" is -2, only update the shape when it's CLINE or STATUS (used 3760 * when the mouse moves off the status or command line). 3761 */ 3762 void 3763 update_mouseshape(shape_idx) 3764 int shape_idx; 3765 { 3766 int new_mouse_shape; 3767 3768 /* Only works in GUI mode. */ 3769 if (!gui.in_use || gui.starting) 3770 return; 3771 3772 /* Postpone the updating when more is to come. Speeds up executing of 3773 * mappings. */ 3774 if (shape_idx == -1 && char_avail()) 3775 { 3776 postponed_mouseshape = TRUE; 3777 return; 3778 } 3779 3780 /* When ignoring the mouse don't change shape on the statusline. */ 3781 if (*p_mouse == NUL 3782 && (shape_idx == SHAPE_IDX_CLINE 3783 || shape_idx == SHAPE_IDX_STATUS 3784 || shape_idx == SHAPE_IDX_VSEP)) 3785 shape_idx = -2; 3786 3787 if (shape_idx == -2 3788 && old_mouse_shape != shape_table[SHAPE_IDX_CLINE].mshape 3789 && old_mouse_shape != shape_table[SHAPE_IDX_STATUS].mshape 3790 && old_mouse_shape != shape_table[SHAPE_IDX_VSEP].mshape) 3791 return; 3792 if (shape_idx < 0) 3793 new_mouse_shape = shape_table[get_shape_idx(TRUE)].mshape; 3794 else 3795 new_mouse_shape = shape_table[shape_idx].mshape; 3796 if (new_mouse_shape != old_mouse_shape) 3797 { 3798 mch_set_mouse_shape(new_mouse_shape); 3799 old_mouse_shape = new_mouse_shape; 3800 } 3801 postponed_mouseshape = FALSE; 3802 } 3803 # endif 3804 3805 #endif /* CURSOR_SHAPE */ 3806 3807 3808 /* TODO: make some #ifdef for this */ 3809 /*--------[ file searching ]-------------------------------------------------*/ 3810 /* 3811 * File searching functions for 'path', 'tags' and 'cdpath' options. 3812 * External visible functions: 3813 * vim_findfile_init() creates/initialises the search context 3814 * vim_findfile_free_visited() free list of visited files/dirs of search 3815 * context 3816 * vim_findfile() find a file in the search context 3817 * vim_findfile_cleanup() cleanup/free search context created by 3818 * vim_findfile_init() 3819 * 3820 * All static functions and variables start with 'ff_' 3821 * 3822 * In general it works like this: 3823 * First you create yourself a search context by calling vim_findfile_init(). 3824 * It is possible to give a search context from a previous call to 3825 * vim_findfile_init(), so it can be reused. After this you call vim_findfile() 3826 * until you are satisfied with the result or it returns NULL. On every call it 3827 * returns the next file which matches the conditions given to 3828 * vim_findfile_init(). If it doesn't find a next file it returns NULL. 3829 * 3830 * It is possible to call vim_findfile_init() again to reinitialise your search 3831 * with some new parameters. Don't forget to pass your old search context to 3832 * it, so it can reuse it and especially reuse the list of already visited 3833 * directories. If you want to delete the list of already visited directories 3834 * simply call vim_findfile_free_visited(). 3835 * 3836 * When you are done call vim_findfile_cleanup() to free the search context. 3837 * 3838 * The function vim_findfile_init() has a long comment, which describes the 3839 * needed parameters. 3840 * 3841 * 3842 * 3843 * ATTENTION: 3844 * ========== 3845 * Also we use an allocated search context here, this functions are NOT 3846 * thread-safe!!!!! 3847 * 3848 * To minimize parameter passing (or because I'm to lazy), only the 3849 * external visible functions get a search context as a parameter. This is 3850 * then assigned to a static global, which is used throughout the local 3851 * functions. 3852 */ 3853 3854 /* 3855 * type for the directory search stack 3856 */ 3857 typedef struct ff_stack 3858 { 3859 struct ff_stack *ffs_prev; 3860 3861 /* the fix part (no wildcards) and the part containing the wildcards 3862 * of the search path 3863 */ 3864 char_u *ffs_fix_path; 3865 #ifdef FEAT_PATH_EXTRA 3866 char_u *ffs_wc_path; 3867 #endif 3868 3869 /* files/dirs found in the above directory, matched by the first wildcard 3870 * of wc_part 3871 */ 3872 char_u **ffs_filearray; 3873 int ffs_filearray_size; 3874 char_u ffs_filearray_cur; /* needed for partly handled dirs */ 3875 3876 /* to store status of partly handled directories 3877 * 0: we work on this directory for the first time 3878 * 1: this directory was partly searched in an earlier step 3879 */ 3880 int ffs_stage; 3881 3882 /* How deep are we in the directory tree? 3883 * Counts backward from value of level parameter to vim_findfile_init 3884 */ 3885 int ffs_level; 3886 3887 /* Did we already expand '**' to an empty string? */ 3888 int ffs_star_star_empty; 3889 } ff_stack_T; 3890 3891 /* 3892 * type for already visited directories or files. 3893 */ 3894 typedef struct ff_visited 3895 { 3896 struct ff_visited *ffv_next; 3897 3898 #ifdef FEAT_PATH_EXTRA 3899 /* Visited directories are different if the wildcard string are 3900 * different. So we have to save it. 3901 */ 3902 char_u *ffv_wc_path; 3903 #endif 3904 /* for unix use inode etc for comparison (needed because of links), else 3905 * use filename. 3906 */ 3907 #ifdef UNIX 3908 int ffv_dev_valid; /* ffv_dev and ffv_ino were set */ 3909 dev_t ffv_dev; /* device number */ 3910 ino_t ffv_ino; /* inode number */ 3911 #endif 3912 /* The memory for this struct is allocated according to the length of 3913 * ffv_fname. 3914 */ 3915 char_u ffv_fname[1]; /* actually longer */ 3916 } ff_visited_T; 3917 3918 /* 3919 * We might have to manage several visited lists during a search. 3920 * This is especially needed for the tags option. If tags is set to: 3921 * "./++/tags,./++/TAGS,++/tags" (replace + with *) 3922 * So we have to do 3 searches: 3923 * 1) search from the current files directory downward for the file "tags" 3924 * 2) search from the current files directory downward for the file "TAGS" 3925 * 3) search from Vims current directory downwards for the file "tags" 3926 * As you can see, the first and the third search are for the same file, so for 3927 * the third search we can use the visited list of the first search. For the 3928 * second search we must start from a empty visited list. 3929 * The struct ff_visited_list_hdr is used to manage a linked list of already 3930 * visited lists. 3931 */ 3932 typedef struct ff_visited_list_hdr 3933 { 3934 struct ff_visited_list_hdr *ffvl_next; 3935 3936 /* the filename the attached visited list is for */ 3937 char_u *ffvl_filename; 3938 3939 ff_visited_T *ffvl_visited_list; 3940 3941 } ff_visited_list_hdr_T; 3942 3943 3944 /* 3945 * '**' can be expanded to several directory levels. 3946 * Set the default maximum depth. 3947 */ 3948 #define FF_MAX_STAR_STAR_EXPAND ((char_u)30) 3949 3950 /* 3951 * The search context: 3952 * ffsc_stack_ptr: the stack for the dirs to search 3953 * ffsc_visited_list: the currently active visited list 3954 * ffsc_dir_visited_list: the currently active visited list for search dirs 3955 * ffsc_visited_lists_list: the list of all visited lists 3956 * ffsc_dir_visited_lists_list: the list of all visited lists for search dirs 3957 * ffsc_file_to_search: the file to search for 3958 * ffsc_start_dir: the starting directory, if search path was relative 3959 * ffsc_fix_path: the fix part of the given path (without wildcards) 3960 * Needed for upward search. 3961 * ffsc_wc_path: the part of the given path containing wildcards 3962 * ffsc_level: how many levels of dirs to search downwards 3963 * ffsc_stopdirs_v: array of stop directories for upward search 3964 * ffsc_find_what: FINDFILE_BOTH, FINDFILE_DIR or FINDFILE_FILE 3965 * ffsc_tagfile: searching for tags file, don't use 'suffixesadd' 3966 */ 3967 typedef struct ff_search_ctx_T 3968 { 3969 ff_stack_T *ffsc_stack_ptr; 3970 ff_visited_list_hdr_T *ffsc_visited_list; 3971 ff_visited_list_hdr_T *ffsc_dir_visited_list; 3972 ff_visited_list_hdr_T *ffsc_visited_lists_list; 3973 ff_visited_list_hdr_T *ffsc_dir_visited_lists_list; 3974 char_u *ffsc_file_to_search; 3975 char_u *ffsc_start_dir; 3976 char_u *ffsc_fix_path; 3977 #ifdef FEAT_PATH_EXTRA 3978 char_u *ffsc_wc_path; 3979 int ffsc_level; 3980 char_u **ffsc_stopdirs_v; 3981 #endif 3982 int ffsc_find_what; 3983 int ffsc_tagfile; 3984 } ff_search_ctx_T; 3985 3986 /* locally needed functions */ 3987 #ifdef FEAT_PATH_EXTRA 3988 static int ff_check_visited __ARGS((ff_visited_T **, char_u *, char_u *)); 3989 #else 3990 static int ff_check_visited __ARGS((ff_visited_T **, char_u *)); 3991 #endif 3992 static void vim_findfile_free_visited_list __ARGS((ff_visited_list_hdr_T **list_headp)); 3993 static void ff_free_visited_list __ARGS((ff_visited_T *vl)); 3994 static ff_visited_list_hdr_T* ff_get_visited_list __ARGS((char_u *, ff_visited_list_hdr_T **list_headp)); 3995 #ifdef FEAT_PATH_EXTRA 3996 static int ff_wc_equal __ARGS((char_u *s1, char_u *s2)); 3997 #endif 3998 3999 static void ff_push __ARGS((ff_search_ctx_T *search_ctx, ff_stack_T *stack_ptr)); 4000 static ff_stack_T *ff_pop __ARGS((ff_search_ctx_T *search_ctx)); 4001 static void ff_clear __ARGS((ff_search_ctx_T *search_ctx)); 4002 static void ff_free_stack_element __ARGS((ff_stack_T *stack_ptr)); 4003 #ifdef FEAT_PATH_EXTRA 4004 static ff_stack_T *ff_create_stack_element __ARGS((char_u *, char_u *, int, int)); 4005 #else 4006 static ff_stack_T *ff_create_stack_element __ARGS((char_u *, int, int)); 4007 #endif 4008 #ifdef FEAT_PATH_EXTRA 4009 static int ff_path_in_stoplist __ARGS((char_u *, int, char_u **)); 4010 #endif 4011 4012 static char_u e_pathtoolong[] = N_("E854: path too long for completion"); 4013 4014 #if 0 4015 /* 4016 * if someone likes findfirst/findnext, here are the functions 4017 * NOT TESTED!! 4018 */ 4019 4020 static void *ff_fn_search_context = NULL; 4021 4022 char_u * 4023 vim_findfirst(path, filename, level) 4024 char_u *path; 4025 char_u *filename; 4026 int level; 4027 { 4028 ff_fn_search_context = 4029 vim_findfile_init(path, filename, NULL, level, TRUE, FALSE, 4030 ff_fn_search_context, rel_fname); 4031 if (NULL == ff_fn_search_context) 4032 return NULL; 4033 else 4034 return vim_findnext() 4035 } 4036 4037 char_u * 4038 vim_findnext() 4039 { 4040 char_u *ret = vim_findfile(ff_fn_search_context); 4041 4042 if (NULL == ret) 4043 { 4044 vim_findfile_cleanup(ff_fn_search_context); 4045 ff_fn_search_context = NULL; 4046 } 4047 return ret; 4048 } 4049 #endif 4050 4051 /* 4052 * Initialization routine for vim_findfile(). 4053 * 4054 * Returns the newly allocated search context or NULL if an error occurred. 4055 * 4056 * Don't forget to clean up by calling vim_findfile_cleanup() if you are done 4057 * with the search context. 4058 * 4059 * Find the file 'filename' in the directory 'path'. 4060 * The parameter 'path' may contain wildcards. If so only search 'level' 4061 * directories deep. The parameter 'level' is the absolute maximum and is 4062 * not related to restricts given to the '**' wildcard. If 'level' is 100 4063 * and you use '**200' vim_findfile() will stop after 100 levels. 4064 * 4065 * 'filename' cannot contain wildcards! It is used as-is, no backslashes to 4066 * escape special characters. 4067 * 4068 * If 'stopdirs' is not NULL and nothing is found downward, the search is 4069 * restarted on the next higher directory level. This is repeated until the 4070 * start-directory of a search is contained in 'stopdirs'. 'stopdirs' has the 4071 * format ";*<dirname>*\(;<dirname>\)*;\=$". 4072 * 4073 * If the 'path' is relative, the starting dir for the search is either VIM's 4074 * current dir or if the path starts with "./" the current files dir. 4075 * If the 'path' is absolute, the starting dir is that part of the path before 4076 * the first wildcard. 4077 * 4078 * Upward search is only done on the starting dir. 4079 * 4080 * If 'free_visited' is TRUE the list of already visited files/directories is 4081 * cleared. Set this to FALSE if you just want to search from another 4082 * directory, but want to be sure that no directory from a previous search is 4083 * searched again. This is useful if you search for a file at different places. 4084 * The list of visited files/dirs can also be cleared with the function 4085 * vim_findfile_free_visited(). 4086 * 4087 * Set the parameter 'find_what' to FINDFILE_DIR if you want to search for 4088 * directories only, FINDFILE_FILE for files only, FINDFILE_BOTH for both. 4089 * 4090 * A search context returned by a previous call to vim_findfile_init() can be 4091 * passed in the parameter "search_ctx_arg". This context is reused and 4092 * reinitialized with the new parameters. The list of already visited 4093 * directories from this context is only deleted if the parameter 4094 * "free_visited" is true. Be aware that the passed "search_ctx_arg" is freed 4095 * if the reinitialization fails. 4096 * 4097 * If you don't have a search context from a previous call "search_ctx_arg" 4098 * must be NULL. 4099 * 4100 * This function silently ignores a few errors, vim_findfile() will have 4101 * limited functionality then. 4102 */ 4103 void * 4104 vim_findfile_init(path, filename, stopdirs, level, free_visited, find_what, 4105 search_ctx_arg, tagfile, rel_fname) 4106 char_u *path; 4107 char_u *filename; 4108 char_u *stopdirs UNUSED; 4109 int level; 4110 int free_visited; 4111 int find_what; 4112 void *search_ctx_arg; 4113 int tagfile; /* expanding names of tags files */ 4114 char_u *rel_fname; /* file name to use for "." */ 4115 { 4116 #ifdef FEAT_PATH_EXTRA 4117 char_u *wc_part; 4118 #endif 4119 ff_stack_T *sptr; 4120 ff_search_ctx_T *search_ctx; 4121 4122 /* If a search context is given by the caller, reuse it, else allocate a 4123 * new one. 4124 */ 4125 if (search_ctx_arg != NULL) 4126 search_ctx = search_ctx_arg; 4127 else 4128 { 4129 search_ctx = (ff_search_ctx_T*)alloc((unsigned)sizeof(ff_search_ctx_T)); 4130 if (search_ctx == NULL) 4131 goto error_return; 4132 vim_memset(search_ctx, 0, sizeof(ff_search_ctx_T)); 4133 } 4134 search_ctx->ffsc_find_what = find_what; 4135 search_ctx->ffsc_tagfile = tagfile; 4136 4137 /* clear the search context, but NOT the visited lists */ 4138 ff_clear(search_ctx); 4139 4140 /* clear visited list if wanted */ 4141 if (free_visited == TRUE) 4142 vim_findfile_free_visited(search_ctx); 4143 else 4144 { 4145 /* Reuse old visited lists. Get the visited list for the given 4146 * filename. If no list for the current filename exists, creates a new 4147 * one. */ 4148 search_ctx->ffsc_visited_list = ff_get_visited_list(filename, 4149 &search_ctx->ffsc_visited_lists_list); 4150 if (search_ctx->ffsc_visited_list == NULL) 4151 goto error_return; 4152 search_ctx->ffsc_dir_visited_list = ff_get_visited_list(filename, 4153 &search_ctx->ffsc_dir_visited_lists_list); 4154 if (search_ctx->ffsc_dir_visited_list == NULL) 4155 goto error_return; 4156 } 4157 4158 if (ff_expand_buffer == NULL) 4159 { 4160 ff_expand_buffer = (char_u*)alloc(MAXPATHL); 4161 if (ff_expand_buffer == NULL) 4162 goto error_return; 4163 } 4164 4165 /* Store information on starting dir now if path is relative. 4166 * If path is absolute, we do that later. */ 4167 if (path[0] == '.' 4168 && (vim_ispathsep(path[1]) || path[1] == NUL) 4169 && (!tagfile || vim_strchr(p_cpo, CPO_DOTTAG) == NULL) 4170 && rel_fname != NULL) 4171 { 4172 int len = (int)(gettail(rel_fname) - rel_fname); 4173 4174 if (!vim_isAbsName(rel_fname) && len + 1 < MAXPATHL) 4175 { 4176 /* Make the start dir an absolute path name. */ 4177 vim_strncpy(ff_expand_buffer, rel_fname, len); 4178 search_ctx->ffsc_start_dir = FullName_save(ff_expand_buffer, FALSE); 4179 } 4180 else 4181 search_ctx->ffsc_start_dir = vim_strnsave(rel_fname, len); 4182 if (search_ctx->ffsc_start_dir == NULL) 4183 goto error_return; 4184 if (*++path != NUL) 4185 ++path; 4186 } 4187 else if (*path == NUL || !vim_isAbsName(path)) 4188 { 4189 #ifdef BACKSLASH_IN_FILENAME 4190 /* "c:dir" needs "c:" to be expanded, otherwise use current dir */ 4191 if (*path != NUL && path[1] == ':') 4192 { 4193 char_u drive[3]; 4194 4195 drive[0] = path[0]; 4196 drive[1] = ':'; 4197 drive[2] = NUL; 4198 if (vim_FullName(drive, ff_expand_buffer, MAXPATHL, TRUE) == FAIL) 4199 goto error_return; 4200 path += 2; 4201 } 4202 else 4203 #endif 4204 if (mch_dirname(ff_expand_buffer, MAXPATHL) == FAIL) 4205 goto error_return; 4206 4207 search_ctx->ffsc_start_dir = vim_strsave(ff_expand_buffer); 4208 if (search_ctx->ffsc_start_dir == NULL) 4209 goto error_return; 4210 4211 #ifdef BACKSLASH_IN_FILENAME 4212 /* A path that starts with "/dir" is relative to the drive, not to the 4213 * directory (but not for "//machine/dir"). Only use the drive name. */ 4214 if ((*path == '/' || *path == '\\') 4215 && path[1] != path[0] 4216 && search_ctx->ffsc_start_dir[1] == ':') 4217 search_ctx->ffsc_start_dir[2] = NUL; 4218 #endif 4219 } 4220 4221 #ifdef FEAT_PATH_EXTRA 4222 /* 4223 * If stopdirs are given, split them into an array of pointers. 4224 * If this fails (mem allocation), there is no upward search at all or a 4225 * stop directory is not recognized -> continue silently. 4226 * If stopdirs just contains a ";" or is empty, 4227 * search_ctx->ffsc_stopdirs_v will only contain a NULL pointer. This 4228 * is handled as unlimited upward search. See function 4229 * ff_path_in_stoplist() for details. 4230 */ 4231 if (stopdirs != NULL) 4232 { 4233 char_u *walker = stopdirs; 4234 int dircount; 4235 4236 while (*walker == ';') 4237 walker++; 4238 4239 dircount = 1; 4240 search_ctx->ffsc_stopdirs_v = 4241 (char_u **)alloc((unsigned)sizeof(char_u *)); 4242 4243 if (search_ctx->ffsc_stopdirs_v != NULL) 4244 { 4245 do 4246 { 4247 char_u *helper; 4248 void *ptr; 4249 4250 helper = walker; 4251 ptr = vim_realloc(search_ctx->ffsc_stopdirs_v, 4252 (dircount + 1) * sizeof(char_u *)); 4253 if (ptr) 4254 search_ctx->ffsc_stopdirs_v = ptr; 4255 else 4256 /* ignore, keep what we have and continue */ 4257 break; 4258 walker = vim_strchr(walker, ';'); 4259 if (walker) 4260 { 4261 search_ctx->ffsc_stopdirs_v[dircount-1] = 4262 vim_strnsave(helper, (int)(walker - helper)); 4263 walker++; 4264 } 4265 else 4266 /* this might be "", which means ascent till top 4267 * of directory tree. 4268 */ 4269 search_ctx->ffsc_stopdirs_v[dircount-1] = 4270 vim_strsave(helper); 4271 4272 dircount++; 4273 4274 } while (walker != NULL); 4275 search_ctx->ffsc_stopdirs_v[dircount-1] = NULL; 4276 } 4277 } 4278 #endif 4279 4280 #ifdef FEAT_PATH_EXTRA 4281 search_ctx->ffsc_level = level; 4282 4283 /* split into: 4284 * -fix path 4285 * -wildcard_stuff (might be NULL) 4286 */ 4287 wc_part = vim_strchr(path, '*'); 4288 if (wc_part != NULL) 4289 { 4290 int llevel; 4291 int len; 4292 char *errpt; 4293 4294 /* save the fix part of the path */ 4295 search_ctx->ffsc_fix_path = vim_strnsave(path, (int)(wc_part - path)); 4296 4297 /* 4298 * copy wc_path and add restricts to the '**' wildcard. 4299 * The octet after a '**' is used as a (binary) counter. 4300 * So '**3' is transposed to '**^C' ('^C' is ASCII value 3) 4301 * or '**76' is transposed to '**N'( 'N' is ASCII value 76). 4302 * For EBCDIC you get different character values. 4303 * If no restrict is given after '**' the default is used. 4304 * Due to this technique the path looks awful if you print it as a 4305 * string. 4306 */ 4307 len = 0; 4308 while (*wc_part != NUL) 4309 { 4310 if (len + 5 >= MAXPATHL) 4311 { 4312 EMSG(_(e_pathtoolong)); 4313 break; 4314 } 4315 if (STRNCMP(wc_part, "**", 2) == 0) 4316 { 4317 ff_expand_buffer[len++] = *wc_part++; 4318 ff_expand_buffer[len++] = *wc_part++; 4319 4320 llevel = strtol((char *)wc_part, &errpt, 10); 4321 if ((char_u *)errpt != wc_part && llevel > 0 && llevel < 255) 4322 ff_expand_buffer[len++] = llevel; 4323 else if ((char_u *)errpt != wc_part && llevel == 0) 4324 /* restrict is 0 -> remove already added '**' */ 4325 len -= 2; 4326 else 4327 ff_expand_buffer[len++] = FF_MAX_STAR_STAR_EXPAND; 4328 wc_part = (char_u *)errpt; 4329 if (*wc_part != NUL && !vim_ispathsep(*wc_part)) 4330 { 4331 EMSG2(_("E343: Invalid path: '**[number]' must be at the end of the path or be followed by '%s'."), PATHSEPSTR); 4332 goto error_return; 4333 } 4334 } 4335 else 4336 ff_expand_buffer[len++] = *wc_part++; 4337 } 4338 ff_expand_buffer[len] = NUL; 4339 search_ctx->ffsc_wc_path = vim_strsave(ff_expand_buffer); 4340 4341 if (search_ctx->ffsc_wc_path == NULL) 4342 goto error_return; 4343 } 4344 else 4345 #endif 4346 search_ctx->ffsc_fix_path = vim_strsave(path); 4347 4348 if (search_ctx->ffsc_start_dir == NULL) 4349 { 4350 /* store the fix part as startdir. 4351 * This is needed if the parameter path is fully qualified. 4352 */ 4353 search_ctx->ffsc_start_dir = vim_strsave(search_ctx->ffsc_fix_path); 4354 if (search_ctx->ffsc_start_dir == NULL) 4355 goto error_return; 4356 search_ctx->ffsc_fix_path[0] = NUL; 4357 } 4358 4359 /* create an absolute path */ 4360 if (STRLEN(search_ctx->ffsc_start_dir) 4361 + STRLEN(search_ctx->ffsc_fix_path) + 3 >= MAXPATHL) 4362 { 4363 EMSG(_(e_pathtoolong)); 4364 goto error_return; 4365 } 4366 STRCPY(ff_expand_buffer, search_ctx->ffsc_start_dir); 4367 add_pathsep(ff_expand_buffer); 4368 { 4369 int eb_len = (int)STRLEN(ff_expand_buffer); 4370 char_u *buf = alloc(eb_len 4371 + (int)STRLEN(search_ctx->ffsc_fix_path) + 1); 4372 4373 STRCPY(buf, ff_expand_buffer); 4374 STRCPY(buf + eb_len, search_ctx->ffsc_fix_path); 4375 if (mch_isdir(buf)) 4376 { 4377 STRCAT(ff_expand_buffer, search_ctx->ffsc_fix_path); 4378 add_pathsep(ff_expand_buffer); 4379 } 4380 #ifdef FEAT_PATH_EXTRA 4381 else 4382 { 4383 char_u *p = gettail(search_ctx->ffsc_fix_path); 4384 char_u *wc_path = NULL; 4385 char_u *temp = NULL; 4386 int len = 0; 4387 4388 if (p > search_ctx->ffsc_fix_path) 4389 { 4390 len = (int)(p - search_ctx->ffsc_fix_path) - 1; 4391 STRNCAT(ff_expand_buffer, search_ctx->ffsc_fix_path, len); 4392 add_pathsep(ff_expand_buffer); 4393 } 4394 else 4395 len = (int)STRLEN(search_ctx->ffsc_fix_path); 4396 4397 if (search_ctx->ffsc_wc_path != NULL) 4398 { 4399 wc_path = vim_strsave(search_ctx->ffsc_wc_path); 4400 temp = alloc((int)(STRLEN(search_ctx->ffsc_wc_path) 4401 + STRLEN(search_ctx->ffsc_fix_path + len) 4402 + 1)); 4403 } 4404 4405 if (temp == NULL || wc_path == NULL) 4406 { 4407 vim_free(buf); 4408 vim_free(temp); 4409 vim_free(wc_path); 4410 goto error_return; 4411 } 4412 4413 STRCPY(temp, search_ctx->ffsc_fix_path + len); 4414 STRCAT(temp, search_ctx->ffsc_wc_path); 4415 vim_free(search_ctx->ffsc_wc_path); 4416 vim_free(wc_path); 4417 search_ctx->ffsc_wc_path = temp; 4418 } 4419 #endif 4420 vim_free(buf); 4421 } 4422 4423 sptr = ff_create_stack_element(ff_expand_buffer, 4424 #ifdef FEAT_PATH_EXTRA 4425 search_ctx->ffsc_wc_path, 4426 #endif 4427 level, 0); 4428 4429 if (sptr == NULL) 4430 goto error_return; 4431 4432 ff_push(search_ctx, sptr); 4433 4434 search_ctx->ffsc_file_to_search = vim_strsave(filename); 4435 if (search_ctx->ffsc_file_to_search == NULL) 4436 goto error_return; 4437 4438 return search_ctx; 4439 4440 error_return: 4441 /* 4442 * We clear the search context now! 4443 * Even when the caller gave us a (perhaps valid) context we free it here, 4444 * as we might have already destroyed it. 4445 */ 4446 vim_findfile_cleanup(search_ctx); 4447 return NULL; 4448 } 4449 4450 #if defined(FEAT_PATH_EXTRA) || defined(PROTO) 4451 /* 4452 * Get the stopdir string. Check that ';' is not escaped. 4453 */ 4454 char_u * 4455 vim_findfile_stopdir(buf) 4456 char_u *buf; 4457 { 4458 char_u *r_ptr = buf; 4459 4460 while (*r_ptr != NUL && *r_ptr != ';') 4461 { 4462 if (r_ptr[0] == '\\' && r_ptr[1] == ';') 4463 { 4464 /* Overwrite the escape char, 4465 * use STRLEN(r_ptr) to move the trailing '\0'. */ 4466 STRMOVE(r_ptr, r_ptr + 1); 4467 r_ptr++; 4468 } 4469 r_ptr++; 4470 } 4471 if (*r_ptr == ';') 4472 { 4473 *r_ptr = 0; 4474 r_ptr++; 4475 } 4476 else if (*r_ptr == NUL) 4477 r_ptr = NULL; 4478 return r_ptr; 4479 } 4480 #endif 4481 4482 /* 4483 * Clean up the given search context. Can handle a NULL pointer. 4484 */ 4485 void 4486 vim_findfile_cleanup(ctx) 4487 void *ctx; 4488 { 4489 if (ctx == NULL) 4490 return; 4491 4492 vim_findfile_free_visited(ctx); 4493 ff_clear(ctx); 4494 vim_free(ctx); 4495 } 4496 4497 /* 4498 * Find a file in a search context. 4499 * The search context was created with vim_findfile_init() above. 4500 * Return a pointer to an allocated file name or NULL if nothing found. 4501 * To get all matching files call this function until you get NULL. 4502 * 4503 * If the passed search_context is NULL, NULL is returned. 4504 * 4505 * The search algorithm is depth first. To change this replace the 4506 * stack with a list (don't forget to leave partly searched directories on the 4507 * top of the list). 4508 */ 4509 char_u * 4510 vim_findfile(search_ctx_arg) 4511 void *search_ctx_arg; 4512 { 4513 char_u *file_path; 4514 #ifdef FEAT_PATH_EXTRA 4515 char_u *rest_of_wildcards; 4516 char_u *path_end = NULL; 4517 #endif 4518 ff_stack_T *stackp; 4519 #if defined(FEAT_SEARCHPATH) || defined(FEAT_PATH_EXTRA) 4520 int len; 4521 #endif 4522 int i; 4523 char_u *p; 4524 #ifdef FEAT_SEARCHPATH 4525 char_u *suf; 4526 #endif 4527 ff_search_ctx_T *search_ctx; 4528 4529 if (search_ctx_arg == NULL) 4530 return NULL; 4531 4532 search_ctx = (ff_search_ctx_T *)search_ctx_arg; 4533 4534 /* 4535 * filepath is used as buffer for various actions and as the storage to 4536 * return a found filename. 4537 */ 4538 if ((file_path = alloc((int)MAXPATHL)) == NULL) 4539 return NULL; 4540 4541 #ifdef FEAT_PATH_EXTRA 4542 /* store the end of the start dir -- needed for upward search */ 4543 if (search_ctx->ffsc_start_dir != NULL) 4544 path_end = &search_ctx->ffsc_start_dir[ 4545 STRLEN(search_ctx->ffsc_start_dir)]; 4546 #endif 4547 4548 #ifdef FEAT_PATH_EXTRA 4549 /* upward search loop */ 4550 for (;;) 4551 { 4552 #endif 4553 /* downward search loop */ 4554 for (;;) 4555 { 4556 /* check if user user wants to stop the search*/ 4557 ui_breakcheck(); 4558 if (got_int) 4559 break; 4560 4561 /* get directory to work on from stack */ 4562 stackp = ff_pop(search_ctx); 4563 if (stackp == NULL) 4564 break; 4565 4566 /* 4567 * TODO: decide if we leave this test in 4568 * 4569 * GOOD: don't search a directory(-tree) twice. 4570 * BAD: - check linked list for every new directory entered. 4571 * - check for double files also done below 4572 * 4573 * Here we check if we already searched this directory. 4574 * We already searched a directory if: 4575 * 1) The directory is the same. 4576 * 2) We would use the same wildcard string. 4577 * 4578 * Good if you have links on same directory via several ways 4579 * or you have selfreferences in directories (e.g. SuSE Linux 6.3: 4580 * /etc/rc.d/init.d is linked to /etc/rc.d -> endless loop) 4581 * 4582 * This check is only needed for directories we work on for the 4583 * first time (hence stackp->ff_filearray == NULL) 4584 */ 4585 if (stackp->ffs_filearray == NULL 4586 && ff_check_visited(&search_ctx->ffsc_dir_visited_list 4587 ->ffvl_visited_list, 4588 stackp->ffs_fix_path 4589 #ifdef FEAT_PATH_EXTRA 4590 , stackp->ffs_wc_path 4591 #endif 4592 ) == FAIL) 4593 { 4594 #ifdef FF_VERBOSE 4595 if (p_verbose >= 5) 4596 { 4597 verbose_enter_scroll(); 4598 smsg((char_u *)"Already Searched: %s (%s)", 4599 stackp->ffs_fix_path, stackp->ffs_wc_path); 4600 /* don't overwrite this either */ 4601 msg_puts((char_u *)"\n"); 4602 verbose_leave_scroll(); 4603 } 4604 #endif 4605 ff_free_stack_element(stackp); 4606 continue; 4607 } 4608 #ifdef FF_VERBOSE 4609 else if (p_verbose >= 5) 4610 { 4611 verbose_enter_scroll(); 4612 smsg((char_u *)"Searching: %s (%s)", 4613 stackp->ffs_fix_path, stackp->ffs_wc_path); 4614 /* don't overwrite this either */ 4615 msg_puts((char_u *)"\n"); 4616 verbose_leave_scroll(); 4617 } 4618 #endif 4619 4620 /* check depth */ 4621 if (stackp->ffs_level <= 0) 4622 { 4623 ff_free_stack_element(stackp); 4624 continue; 4625 } 4626 4627 file_path[0] = NUL; 4628 4629 /* 4630 * If no filearray till now expand wildcards 4631 * The function expand_wildcards() can handle an array of paths 4632 * and all possible expands are returned in one array. We use this 4633 * to handle the expansion of '**' into an empty string. 4634 */ 4635 if (stackp->ffs_filearray == NULL) 4636 { 4637 char_u *dirptrs[2]; 4638 4639 /* we use filepath to build the path expand_wildcards() should 4640 * expand. 4641 */ 4642 dirptrs[0] = file_path; 4643 dirptrs[1] = NULL; 4644 4645 /* if we have a start dir copy it in */ 4646 if (!vim_isAbsName(stackp->ffs_fix_path) 4647 && search_ctx->ffsc_start_dir) 4648 { 4649 STRCPY(file_path, search_ctx->ffsc_start_dir); 4650 add_pathsep(file_path); 4651 } 4652 4653 /* append the fix part of the search path */ 4654 STRCAT(file_path, stackp->ffs_fix_path); 4655 add_pathsep(file_path); 4656 4657 #ifdef FEAT_PATH_EXTRA 4658 rest_of_wildcards = stackp->ffs_wc_path; 4659 if (*rest_of_wildcards != NUL) 4660 { 4661 len = (int)STRLEN(file_path); 4662 if (STRNCMP(rest_of_wildcards, "**", 2) == 0) 4663 { 4664 /* pointer to the restrict byte 4665 * The restrict byte is not a character! 4666 */ 4667 p = rest_of_wildcards + 2; 4668 4669 if (*p > 0) 4670 { 4671 (*p)--; 4672 file_path[len++] = '*'; 4673 } 4674 4675 if (*p == 0) 4676 { 4677 /* remove '**<numb> from wildcards */ 4678 STRMOVE(rest_of_wildcards, rest_of_wildcards + 3); 4679 } 4680 else 4681 rest_of_wildcards += 3; 4682 4683 if (stackp->ffs_star_star_empty == 0) 4684 { 4685 /* if not done before, expand '**' to empty */ 4686 stackp->ffs_star_star_empty = 1; 4687 dirptrs[1] = stackp->ffs_fix_path; 4688 } 4689 } 4690 4691 /* 4692 * Here we copy until the next path separator or the end of 4693 * the path. If we stop at a path separator, there is 4694 * still something else left. This is handled below by 4695 * pushing every directory returned from expand_wildcards() 4696 * on the stack again for further search. 4697 */ 4698 while (*rest_of_wildcards 4699 && !vim_ispathsep(*rest_of_wildcards)) 4700 file_path[len++] = *rest_of_wildcards++; 4701 4702 file_path[len] = NUL; 4703 if (vim_ispathsep(*rest_of_wildcards)) 4704 rest_of_wildcards++; 4705 } 4706 #endif 4707 4708 /* 4709 * Expand wildcards like "*" and "$VAR". 4710 * If the path is a URL don't try this. 4711 */ 4712 if (path_with_url(dirptrs[0])) 4713 { 4714 stackp->ffs_filearray = (char_u **) 4715 alloc((unsigned)sizeof(char *)); 4716 if (stackp->ffs_filearray != NULL 4717 && (stackp->ffs_filearray[0] 4718 = vim_strsave(dirptrs[0])) != NULL) 4719 stackp->ffs_filearray_size = 1; 4720 else 4721 stackp->ffs_filearray_size = 0; 4722 } 4723 else 4724 /* Add EW_NOTWILD because the expanded path may contain 4725 * wildcard characters that are to be taken literally. 4726 * This is a bit of a hack. */ 4727 expand_wildcards((dirptrs[1] == NULL) ? 1 : 2, dirptrs, 4728 &stackp->ffs_filearray_size, 4729 &stackp->ffs_filearray, 4730 EW_DIR|EW_ADDSLASH|EW_SILENT|EW_NOTWILD); 4731 4732 stackp->ffs_filearray_cur = 0; 4733 stackp->ffs_stage = 0; 4734 } 4735 #ifdef FEAT_PATH_EXTRA 4736 else 4737 rest_of_wildcards = &stackp->ffs_wc_path[ 4738 STRLEN(stackp->ffs_wc_path)]; 4739 #endif 4740 4741 if (stackp->ffs_stage == 0) 4742 { 4743 /* this is the first time we work on this directory */ 4744 #ifdef FEAT_PATH_EXTRA 4745 if (*rest_of_wildcards == NUL) 4746 #endif 4747 { 4748 /* 4749 * We don't have further wildcards to expand, so we have to 4750 * check for the final file now. 4751 */ 4752 for (i = stackp->ffs_filearray_cur; 4753 i < stackp->ffs_filearray_size; ++i) 4754 { 4755 if (!path_with_url(stackp->ffs_filearray[i]) 4756 && !mch_isdir(stackp->ffs_filearray[i])) 4757 continue; /* not a directory */ 4758 4759 /* prepare the filename to be checked for existence 4760 * below */ 4761 STRCPY(file_path, stackp->ffs_filearray[i]); 4762 add_pathsep(file_path); 4763 STRCAT(file_path, search_ctx->ffsc_file_to_search); 4764 4765 /* 4766 * Try without extra suffix and then with suffixes 4767 * from 'suffixesadd'. 4768 */ 4769 #ifdef FEAT_SEARCHPATH 4770 len = (int)STRLEN(file_path); 4771 if (search_ctx->ffsc_tagfile) 4772 suf = (char_u *)""; 4773 else 4774 suf = curbuf->b_p_sua; 4775 for (;;) 4776 #endif 4777 { 4778 /* if file exists and we didn't already find it */ 4779 if ((path_with_url(file_path) 4780 || (mch_getperm(file_path) >= 0 4781 && (search_ctx->ffsc_find_what 4782 == FINDFILE_BOTH 4783 || ((search_ctx->ffsc_find_what 4784 == FINDFILE_DIR) 4785 == mch_isdir(file_path))))) 4786 #ifndef FF_VERBOSE 4787 && (ff_check_visited( 4788 &search_ctx->ffsc_visited_list->ffvl_visited_list, 4789 file_path 4790 #ifdef FEAT_PATH_EXTRA 4791 , (char_u *)"" 4792 #endif 4793 ) == OK) 4794 #endif 4795 ) 4796 { 4797 #ifdef FF_VERBOSE 4798 if (ff_check_visited( 4799 &search_ctx->ffsc_visited_list->ffvl_visited_list, 4800 file_path 4801 #ifdef FEAT_PATH_EXTRA 4802 , (char_u *)"" 4803 #endif 4804 ) == FAIL) 4805 { 4806 if (p_verbose >= 5) 4807 { 4808 verbose_enter_scroll(); 4809 smsg((char_u *)"Already: %s", 4810 file_path); 4811 /* don't overwrite this either */ 4812 msg_puts((char_u *)"\n"); 4813 verbose_leave_scroll(); 4814 } 4815 continue; 4816 } 4817 #endif 4818 4819 /* push dir to examine rest of subdirs later */ 4820 stackp->ffs_filearray_cur = i + 1; 4821 ff_push(search_ctx, stackp); 4822 4823 if (!path_with_url(file_path)) 4824 simplify_filename(file_path); 4825 if (mch_dirname(ff_expand_buffer, MAXPATHL) 4826 == OK) 4827 { 4828 p = shorten_fname(file_path, 4829 ff_expand_buffer); 4830 if (p != NULL) 4831 STRMOVE(file_path, p); 4832 } 4833 #ifdef FF_VERBOSE 4834 if (p_verbose >= 5) 4835 { 4836 verbose_enter_scroll(); 4837 smsg((char_u *)"HIT: %s", file_path); 4838 /* don't overwrite this either */ 4839 msg_puts((char_u *)"\n"); 4840 verbose_leave_scroll(); 4841 } 4842 #endif 4843 return file_path; 4844 } 4845 4846 #ifdef FEAT_SEARCHPATH 4847 /* Not found or found already, try next suffix. */ 4848 if (*suf == NUL) 4849 break; 4850 copy_option_part(&suf, file_path + len, 4851 MAXPATHL - len, ","); 4852 #endif 4853 } 4854 } 4855 } 4856 #ifdef FEAT_PATH_EXTRA 4857 else 4858 { 4859 /* 4860 * still wildcards left, push the directories for further 4861 * search 4862 */ 4863 for (i = stackp->ffs_filearray_cur; 4864 i < stackp->ffs_filearray_size; ++i) 4865 { 4866 if (!mch_isdir(stackp->ffs_filearray[i])) 4867 continue; /* not a directory */ 4868 4869 ff_push(search_ctx, 4870 ff_create_stack_element( 4871 stackp->ffs_filearray[i], 4872 rest_of_wildcards, 4873 stackp->ffs_level - 1, 0)); 4874 } 4875 } 4876 #endif 4877 stackp->ffs_filearray_cur = 0; 4878 stackp->ffs_stage = 1; 4879 } 4880 4881 #ifdef FEAT_PATH_EXTRA 4882 /* 4883 * if wildcards contains '**' we have to descent till we reach the 4884 * leaves of the directory tree. 4885 */ 4886 if (STRNCMP(stackp->ffs_wc_path, "**", 2) == 0) 4887 { 4888 for (i = stackp->ffs_filearray_cur; 4889 i < stackp->ffs_filearray_size; ++i) 4890 { 4891 if (fnamecmp(stackp->ffs_filearray[i], 4892 stackp->ffs_fix_path) == 0) 4893 continue; /* don't repush same directory */ 4894 if (!mch_isdir(stackp->ffs_filearray[i])) 4895 continue; /* not a directory */ 4896 ff_push(search_ctx, 4897 ff_create_stack_element(stackp->ffs_filearray[i], 4898 stackp->ffs_wc_path, stackp->ffs_level - 1, 1)); 4899 } 4900 } 4901 #endif 4902 4903 /* we are done with the current directory */ 4904 ff_free_stack_element(stackp); 4905 4906 } 4907 4908 #ifdef FEAT_PATH_EXTRA 4909 /* If we reached this, we didn't find anything downwards. 4910 * Let's check if we should do an upward search. 4911 */ 4912 if (search_ctx->ffsc_start_dir 4913 && search_ctx->ffsc_stopdirs_v != NULL && !got_int) 4914 { 4915 ff_stack_T *sptr; 4916 4917 /* is the last starting directory in the stop list? */ 4918 if (ff_path_in_stoplist(search_ctx->ffsc_start_dir, 4919 (int)(path_end - search_ctx->ffsc_start_dir), 4920 search_ctx->ffsc_stopdirs_v) == TRUE) 4921 break; 4922 4923 /* cut of last dir */ 4924 while (path_end > search_ctx->ffsc_start_dir 4925 && vim_ispathsep(*path_end)) 4926 path_end--; 4927 while (path_end > search_ctx->ffsc_start_dir 4928 && !vim_ispathsep(path_end[-1])) 4929 path_end--; 4930 *path_end = 0; 4931 path_end--; 4932 4933 if (*search_ctx->ffsc_start_dir == 0) 4934 break; 4935 4936 STRCPY(file_path, search_ctx->ffsc_start_dir); 4937 add_pathsep(file_path); 4938 STRCAT(file_path, search_ctx->ffsc_fix_path); 4939 4940 /* create a new stack entry */ 4941 sptr = ff_create_stack_element(file_path, 4942 search_ctx->ffsc_wc_path, search_ctx->ffsc_level, 0); 4943 if (sptr == NULL) 4944 break; 4945 ff_push(search_ctx, sptr); 4946 } 4947 else 4948 break; 4949 } 4950 #endif 4951 4952 vim_free(file_path); 4953 return NULL; 4954 } 4955 4956 /* 4957 * Free the list of lists of visited files and directories 4958 * Can handle it if the passed search_context is NULL; 4959 */ 4960 void 4961 vim_findfile_free_visited(search_ctx_arg) 4962 void *search_ctx_arg; 4963 { 4964 ff_search_ctx_T *search_ctx; 4965 4966 if (search_ctx_arg == NULL) 4967 return; 4968 4969 search_ctx = (ff_search_ctx_T *)search_ctx_arg; 4970 vim_findfile_free_visited_list(&search_ctx->ffsc_visited_lists_list); 4971 vim_findfile_free_visited_list(&search_ctx->ffsc_dir_visited_lists_list); 4972 } 4973 4974 static void 4975 vim_findfile_free_visited_list(list_headp) 4976 ff_visited_list_hdr_T **list_headp; 4977 { 4978 ff_visited_list_hdr_T *vp; 4979 4980 while (*list_headp != NULL) 4981 { 4982 vp = (*list_headp)->ffvl_next; 4983 ff_free_visited_list((*list_headp)->ffvl_visited_list); 4984 4985 vim_free((*list_headp)->ffvl_filename); 4986 vim_free(*list_headp); 4987 *list_headp = vp; 4988 } 4989 *list_headp = NULL; 4990 } 4991 4992 static void 4993 ff_free_visited_list(vl) 4994 ff_visited_T *vl; 4995 { 4996 ff_visited_T *vp; 4997 4998 while (vl != NULL) 4999 { 5000 vp = vl->ffv_next; 5001 #ifdef FEAT_PATH_EXTRA 5002 vim_free(vl->ffv_wc_path); 5003 #endif 5004 vim_free(vl); 5005 vl = vp; 5006 } 5007 vl = NULL; 5008 } 5009 5010 /* 5011 * Returns the already visited list for the given filename. If none is found it 5012 * allocates a new one. 5013 */ 5014 static ff_visited_list_hdr_T* 5015 ff_get_visited_list(filename, list_headp) 5016 char_u *filename; 5017 ff_visited_list_hdr_T **list_headp; 5018 { 5019 ff_visited_list_hdr_T *retptr = NULL; 5020 5021 /* check if a visited list for the given filename exists */ 5022 if (*list_headp != NULL) 5023 { 5024 retptr = *list_headp; 5025 while (retptr != NULL) 5026 { 5027 if (fnamecmp(filename, retptr->ffvl_filename) == 0) 5028 { 5029 #ifdef FF_VERBOSE 5030 if (p_verbose >= 5) 5031 { 5032 verbose_enter_scroll(); 5033 smsg((char_u *)"ff_get_visited_list: FOUND list for %s", 5034 filename); 5035 /* don't overwrite this either */ 5036 msg_puts((char_u *)"\n"); 5037 verbose_leave_scroll(); 5038 } 5039 #endif 5040 return retptr; 5041 } 5042 retptr = retptr->ffvl_next; 5043 } 5044 } 5045 5046 #ifdef FF_VERBOSE 5047 if (p_verbose >= 5) 5048 { 5049 verbose_enter_scroll(); 5050 smsg((char_u *)"ff_get_visited_list: new list for %s", filename); 5051 /* don't overwrite this either */ 5052 msg_puts((char_u *)"\n"); 5053 verbose_leave_scroll(); 5054 } 5055 #endif 5056 5057 /* 5058 * if we reach this we didn't find a list and we have to allocate new list 5059 */ 5060 retptr = (ff_visited_list_hdr_T*)alloc((unsigned)sizeof(*retptr)); 5061 if (retptr == NULL) 5062 return NULL; 5063 5064 retptr->ffvl_visited_list = NULL; 5065 retptr->ffvl_filename = vim_strsave(filename); 5066 if (retptr->ffvl_filename == NULL) 5067 { 5068 vim_free(retptr); 5069 return NULL; 5070 } 5071 retptr->ffvl_next = *list_headp; 5072 *list_headp = retptr; 5073 5074 return retptr; 5075 } 5076 5077 #ifdef FEAT_PATH_EXTRA 5078 /* 5079 * check if two wildcard paths are equal. Returns TRUE or FALSE. 5080 * They are equal if: 5081 * - both paths are NULL 5082 * - they have the same length 5083 * - char by char comparison is OK 5084 * - the only differences are in the counters behind a '**', so 5085 * '**\20' is equal to '**\24' 5086 */ 5087 static int 5088 ff_wc_equal(s1, s2) 5089 char_u *s1; 5090 char_u *s2; 5091 { 5092 int i; 5093 int prev1 = NUL; 5094 int prev2 = NUL; 5095 5096 if (s1 == s2) 5097 return TRUE; 5098 5099 if (s1 == NULL || s2 == NULL) 5100 return FALSE; 5101 5102 if (STRLEN(s1) != STRLEN(s2)) 5103 return FAIL; 5104 5105 for (i = 0; s1[i] != NUL && s2[i] != NUL; i += MB_PTR2LEN(s1 + i)) 5106 { 5107 int c1 = PTR2CHAR(s1 + i); 5108 int c2 = PTR2CHAR(s2 + i); 5109 5110 if ((p_fic ? MB_TOLOWER(c1) != MB_TOLOWER(c2) : c1 != c2) 5111 && (prev1 != '*' || prev2 != '*')) 5112 return FAIL; 5113 prev2 = prev1; 5114 prev1 = c1; 5115 } 5116 return TRUE; 5117 } 5118 #endif 5119 5120 /* 5121 * maintains the list of already visited files and dirs 5122 * returns FAIL if the given file/dir is already in the list 5123 * returns OK if it is newly added 5124 * 5125 * TODO: What to do on memory allocation problems? 5126 * -> return TRUE - Better the file is found several times instead of 5127 * never. 5128 */ 5129 static int 5130 ff_check_visited(visited_list, fname 5131 #ifdef FEAT_PATH_EXTRA 5132 , wc_path 5133 #endif 5134 ) 5135 ff_visited_T **visited_list; 5136 char_u *fname; 5137 #ifdef FEAT_PATH_EXTRA 5138 char_u *wc_path; 5139 #endif 5140 { 5141 ff_visited_T *vp; 5142 #ifdef UNIX 5143 struct stat st; 5144 int url = FALSE; 5145 #endif 5146 5147 /* For an URL we only compare the name, otherwise we compare the 5148 * device/inode (unix) or the full path name (not Unix). */ 5149 if (path_with_url(fname)) 5150 { 5151 vim_strncpy(ff_expand_buffer, fname, MAXPATHL - 1); 5152 #ifdef UNIX 5153 url = TRUE; 5154 #endif 5155 } 5156 else 5157 { 5158 ff_expand_buffer[0] = NUL; 5159 #ifdef UNIX 5160 if (mch_stat((char *)fname, &st) < 0) 5161 #else 5162 if (vim_FullName(fname, ff_expand_buffer, MAXPATHL, TRUE) == FAIL) 5163 #endif 5164 return FAIL; 5165 } 5166 5167 /* check against list of already visited files */ 5168 for (vp = *visited_list; vp != NULL; vp = vp->ffv_next) 5169 { 5170 if ( 5171 #ifdef UNIX 5172 !url ? (vp->ffv_dev_valid && vp->ffv_dev == st.st_dev 5173 && vp->ffv_ino == st.st_ino) 5174 : 5175 #endif 5176 fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0 5177 ) 5178 { 5179 #ifdef FEAT_PATH_EXTRA 5180 /* are the wildcard parts equal */ 5181 if (ff_wc_equal(vp->ffv_wc_path, wc_path) == TRUE) 5182 #endif 5183 /* already visited */ 5184 return FAIL; 5185 } 5186 } 5187 5188 /* 5189 * New file/dir. Add it to the list of visited files/dirs. 5190 */ 5191 vp = (ff_visited_T *)alloc((unsigned)(sizeof(ff_visited_T) 5192 + STRLEN(ff_expand_buffer))); 5193 5194 if (vp != NULL) 5195 { 5196 #ifdef UNIX 5197 if (!url) 5198 { 5199 vp->ffv_dev_valid = TRUE; 5200 vp->ffv_ino = st.st_ino; 5201 vp->ffv_dev = st.st_dev; 5202 vp->ffv_fname[0] = NUL; 5203 } 5204 else 5205 { 5206 vp->ffv_dev_valid = FALSE; 5207 #endif 5208 STRCPY(vp->ffv_fname, ff_expand_buffer); 5209 #ifdef UNIX 5210 } 5211 #endif 5212 #ifdef FEAT_PATH_EXTRA 5213 if (wc_path != NULL) 5214 vp->ffv_wc_path = vim_strsave(wc_path); 5215 else 5216 vp->ffv_wc_path = NULL; 5217 #endif 5218 5219 vp->ffv_next = *visited_list; 5220 *visited_list = vp; 5221 } 5222 5223 return OK; 5224 } 5225 5226 /* 5227 * create stack element from given path pieces 5228 */ 5229 static ff_stack_T * 5230 ff_create_stack_element(fix_part, 5231 #ifdef FEAT_PATH_EXTRA 5232 wc_part, 5233 #endif 5234 level, star_star_empty) 5235 char_u *fix_part; 5236 #ifdef FEAT_PATH_EXTRA 5237 char_u *wc_part; 5238 #endif 5239 int level; 5240 int star_star_empty; 5241 { 5242 ff_stack_T *new; 5243 5244 new = (ff_stack_T *)alloc((unsigned)sizeof(ff_stack_T)); 5245 if (new == NULL) 5246 return NULL; 5247 5248 new->ffs_prev = NULL; 5249 new->ffs_filearray = NULL; 5250 new->ffs_filearray_size = 0; 5251 new->ffs_filearray_cur = 0; 5252 new->ffs_stage = 0; 5253 new->ffs_level = level; 5254 new->ffs_star_star_empty = star_star_empty;; 5255 5256 /* the following saves NULL pointer checks in vim_findfile */ 5257 if (fix_part == NULL) 5258 fix_part = (char_u *)""; 5259 new->ffs_fix_path = vim_strsave(fix_part); 5260 5261 #ifdef FEAT_PATH_EXTRA 5262 if (wc_part == NULL) 5263 wc_part = (char_u *)""; 5264 new->ffs_wc_path = vim_strsave(wc_part); 5265 #endif 5266 5267 if (new->ffs_fix_path == NULL 5268 #ifdef FEAT_PATH_EXTRA 5269 || new->ffs_wc_path == NULL 5270 #endif 5271 ) 5272 { 5273 ff_free_stack_element(new); 5274 new = NULL; 5275 } 5276 5277 return new; 5278 } 5279 5280 /* 5281 * Push a dir on the directory stack. 5282 */ 5283 static void 5284 ff_push(search_ctx, stack_ptr) 5285 ff_search_ctx_T *search_ctx; 5286 ff_stack_T *stack_ptr; 5287 { 5288 /* check for NULL pointer, not to return an error to the user, but 5289 * to prevent a crash */ 5290 if (stack_ptr != NULL) 5291 { 5292 stack_ptr->ffs_prev = search_ctx->ffsc_stack_ptr; 5293 search_ctx->ffsc_stack_ptr = stack_ptr; 5294 } 5295 } 5296 5297 /* 5298 * Pop a dir from the directory stack. 5299 * Returns NULL if stack is empty. 5300 */ 5301 static ff_stack_T * 5302 ff_pop(search_ctx) 5303 ff_search_ctx_T *search_ctx; 5304 { 5305 ff_stack_T *sptr; 5306 5307 sptr = search_ctx->ffsc_stack_ptr; 5308 if (search_ctx->ffsc_stack_ptr != NULL) 5309 search_ctx->ffsc_stack_ptr = search_ctx->ffsc_stack_ptr->ffs_prev; 5310 5311 return sptr; 5312 } 5313 5314 /* 5315 * free the given stack element 5316 */ 5317 static void 5318 ff_free_stack_element(stack_ptr) 5319 ff_stack_T *stack_ptr; 5320 { 5321 /* vim_free handles possible NULL pointers */ 5322 vim_free(stack_ptr->ffs_fix_path); 5323 #ifdef FEAT_PATH_EXTRA 5324 vim_free(stack_ptr->ffs_wc_path); 5325 #endif 5326 5327 if (stack_ptr->ffs_filearray != NULL) 5328 FreeWild(stack_ptr->ffs_filearray_size, stack_ptr->ffs_filearray); 5329 5330 vim_free(stack_ptr); 5331 } 5332 5333 /* 5334 * Clear the search context, but NOT the visited list. 5335 */ 5336 static void 5337 ff_clear(search_ctx) 5338 ff_search_ctx_T *search_ctx; 5339 { 5340 ff_stack_T *sptr; 5341 5342 /* clear up stack */ 5343 while ((sptr = ff_pop(search_ctx)) != NULL) 5344 ff_free_stack_element(sptr); 5345 5346 vim_free(search_ctx->ffsc_file_to_search); 5347 vim_free(search_ctx->ffsc_start_dir); 5348 vim_free(search_ctx->ffsc_fix_path); 5349 #ifdef FEAT_PATH_EXTRA 5350 vim_free(search_ctx->ffsc_wc_path); 5351 #endif 5352 5353 #ifdef FEAT_PATH_EXTRA 5354 if (search_ctx->ffsc_stopdirs_v != NULL) 5355 { 5356 int i = 0; 5357 5358 while (search_ctx->ffsc_stopdirs_v[i] != NULL) 5359 { 5360 vim_free(search_ctx->ffsc_stopdirs_v[i]); 5361 i++; 5362 } 5363 vim_free(search_ctx->ffsc_stopdirs_v); 5364 } 5365 search_ctx->ffsc_stopdirs_v = NULL; 5366 #endif 5367 5368 /* reset everything */ 5369 search_ctx->ffsc_file_to_search = NULL; 5370 search_ctx->ffsc_start_dir = NULL; 5371 search_ctx->ffsc_fix_path = NULL; 5372 #ifdef FEAT_PATH_EXTRA 5373 search_ctx->ffsc_wc_path = NULL; 5374 search_ctx->ffsc_level = 0; 5375 #endif 5376 } 5377 5378 #ifdef FEAT_PATH_EXTRA 5379 /* 5380 * check if the given path is in the stopdirs 5381 * returns TRUE if yes else FALSE 5382 */ 5383 static int 5384 ff_path_in_stoplist(path, path_len, stopdirs_v) 5385 char_u *path; 5386 int path_len; 5387 char_u **stopdirs_v; 5388 { 5389 int i = 0; 5390 5391 /* eat up trailing path separators, except the first */ 5392 while (path_len > 1 && vim_ispathsep(path[path_len - 1])) 5393 path_len--; 5394 5395 /* if no path consider it as match */ 5396 if (path_len == 0) 5397 return TRUE; 5398 5399 for (i = 0; stopdirs_v[i] != NULL; i++) 5400 { 5401 if ((int)STRLEN(stopdirs_v[i]) > path_len) 5402 { 5403 /* match for parent directory. So '/home' also matches 5404 * '/home/rks'. Check for PATHSEP in stopdirs_v[i], else 5405 * '/home/r' would also match '/home/rks' 5406 */ 5407 if (fnamencmp(stopdirs_v[i], path, path_len) == 0 5408 && vim_ispathsep(stopdirs_v[i][path_len])) 5409 return TRUE; 5410 } 5411 else 5412 { 5413 if (fnamecmp(stopdirs_v[i], path) == 0) 5414 return TRUE; 5415 } 5416 } 5417 return FALSE; 5418 } 5419 #endif 5420 5421 #if defined(FEAT_SEARCHPATH) || defined(PROTO) 5422 /* 5423 * Find the file name "ptr[len]" in the path. Also finds directory names. 5424 * 5425 * On the first call set the parameter 'first' to TRUE to initialize 5426 * the search. For repeating calls to FALSE. 5427 * 5428 * Repeating calls will return other files called 'ptr[len]' from the path. 5429 * 5430 * Only on the first call 'ptr' and 'len' are used. For repeating calls they 5431 * don't need valid values. 5432 * 5433 * If nothing found on the first call the option FNAME_MESS will issue the 5434 * message: 5435 * 'Can't find file "<file>" in path' 5436 * On repeating calls: 5437 * 'No more file "<file>" found in path' 5438 * 5439 * options: 5440 * FNAME_MESS give error message when not found 5441 * 5442 * Uses NameBuff[]! 5443 * 5444 * Returns an allocated string for the file name. NULL for error. 5445 * 5446 */ 5447 char_u * 5448 find_file_in_path(ptr, len, options, first, rel_fname) 5449 char_u *ptr; /* file name */ 5450 int len; /* length of file name */ 5451 int options; 5452 int first; /* use count'th matching file name */ 5453 char_u *rel_fname; /* file name searching relative to */ 5454 { 5455 return find_file_in_path_option(ptr, len, options, first, 5456 *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path, 5457 FINDFILE_BOTH, rel_fname, curbuf->b_p_sua); 5458 } 5459 5460 static char_u *ff_file_to_find = NULL; 5461 static void *fdip_search_ctx = NULL; 5462 5463 #if defined(EXITFREE) 5464 static void 5465 free_findfile() 5466 { 5467 vim_free(ff_file_to_find); 5468 vim_findfile_cleanup(fdip_search_ctx); 5469 } 5470 #endif 5471 5472 /* 5473 * Find the directory name "ptr[len]" in the path. 5474 * 5475 * options: 5476 * FNAME_MESS give error message when not found 5477 * 5478 * Uses NameBuff[]! 5479 * 5480 * Returns an allocated string for the file name. NULL for error. 5481 */ 5482 char_u * 5483 find_directory_in_path(ptr, len, options, rel_fname) 5484 char_u *ptr; /* file name */ 5485 int len; /* length of file name */ 5486 int options; 5487 char_u *rel_fname; /* file name searching relative to */ 5488 { 5489 return find_file_in_path_option(ptr, len, options, TRUE, p_cdpath, 5490 FINDFILE_DIR, rel_fname, (char_u *)""); 5491 } 5492 5493 char_u * 5494 find_file_in_path_option(ptr, len, options, first, path_option, find_what, rel_fname, suffixes) 5495 char_u *ptr; /* file name */ 5496 int len; /* length of file name */ 5497 int options; 5498 int first; /* use count'th matching file name */ 5499 char_u *path_option; /* p_path or p_cdpath */ 5500 int find_what; /* FINDFILE_FILE, _DIR or _BOTH */ 5501 char_u *rel_fname; /* file name we are looking relative to. */ 5502 char_u *suffixes; /* list of suffixes, 'suffixesadd' option */ 5503 { 5504 static char_u *dir; 5505 static int did_findfile_init = FALSE; 5506 char_u save_char; 5507 char_u *file_name = NULL; 5508 char_u *buf = NULL; 5509 int rel_to_curdir; 5510 #ifdef AMIGA 5511 struct Process *proc = (struct Process *)FindTask(0L); 5512 APTR save_winptr = proc->pr_WindowPtr; 5513 5514 /* Avoid a requester here for a volume that doesn't exist. */ 5515 proc->pr_WindowPtr = (APTR)-1L; 5516 #endif 5517 5518 if (first == TRUE) 5519 { 5520 /* copy file name into NameBuff, expanding environment variables */ 5521 save_char = ptr[len]; 5522 ptr[len] = NUL; 5523 expand_env(ptr, NameBuff, MAXPATHL); 5524 ptr[len] = save_char; 5525 5526 vim_free(ff_file_to_find); 5527 ff_file_to_find = vim_strsave(NameBuff); 5528 if (ff_file_to_find == NULL) /* out of memory */ 5529 { 5530 file_name = NULL; 5531 goto theend; 5532 } 5533 } 5534 5535 rel_to_curdir = (ff_file_to_find[0] == '.' 5536 && (ff_file_to_find[1] == NUL 5537 || vim_ispathsep(ff_file_to_find[1]) 5538 || (ff_file_to_find[1] == '.' 5539 && (ff_file_to_find[2] == NUL 5540 || vim_ispathsep(ff_file_to_find[2]))))); 5541 if (vim_isAbsName(ff_file_to_find) 5542 /* "..", "../path", "." and "./path": don't use the path_option */ 5543 || rel_to_curdir 5544 #if defined(MSWIN) || defined(MSDOS) || defined(OS2) 5545 /* handle "\tmp" as absolute path */ 5546 || vim_ispathsep(ff_file_to_find[0]) 5547 /* handle "c:name" as absolute path */ 5548 || (ff_file_to_find[0] != NUL && ff_file_to_find[1] == ':') 5549 #endif 5550 #ifdef AMIGA 5551 /* handle ":tmp" as absolute path */ 5552 || ff_file_to_find[0] == ':' 5553 #endif 5554 ) 5555 { 5556 /* 5557 * Absolute path, no need to use "path_option". 5558 * If this is not a first call, return NULL. We already returned a 5559 * filename on the first call. 5560 */ 5561 if (first == TRUE) 5562 { 5563 int l; 5564 int run; 5565 5566 if (path_with_url(ff_file_to_find)) 5567 { 5568 file_name = vim_strsave(ff_file_to_find); 5569 goto theend; 5570 } 5571 5572 /* When FNAME_REL flag given first use the directory of the file. 5573 * Otherwise or when this fails use the current directory. */ 5574 for (run = 1; run <= 2; ++run) 5575 { 5576 l = (int)STRLEN(ff_file_to_find); 5577 if (run == 1 5578 && rel_to_curdir 5579 && (options & FNAME_REL) 5580 && rel_fname != NULL 5581 && STRLEN(rel_fname) + l < MAXPATHL) 5582 { 5583 STRCPY(NameBuff, rel_fname); 5584 STRCPY(gettail(NameBuff), ff_file_to_find); 5585 l = (int)STRLEN(NameBuff); 5586 } 5587 else 5588 { 5589 STRCPY(NameBuff, ff_file_to_find); 5590 run = 2; 5591 } 5592 5593 /* When the file doesn't exist, try adding parts of 5594 * 'suffixesadd'. */ 5595 buf = suffixes; 5596 for (;;) 5597 { 5598 if ( 5599 #ifdef DJGPP 5600 /* "C:" by itself will fail for mch_getperm(), 5601 * assume it's always valid. */ 5602 (find_what != FINDFILE_FILE && NameBuff[0] != NUL 5603 && NameBuff[1] == ':' 5604 && NameBuff[2] == NUL) || 5605 #endif 5606 (mch_getperm(NameBuff) >= 0 5607 && (find_what == FINDFILE_BOTH 5608 || ((find_what == FINDFILE_DIR) 5609 == mch_isdir(NameBuff))))) 5610 { 5611 file_name = vim_strsave(NameBuff); 5612 goto theend; 5613 } 5614 if (*buf == NUL) 5615 break; 5616 copy_option_part(&buf, NameBuff + l, MAXPATHL - l, ","); 5617 } 5618 } 5619 } 5620 } 5621 else 5622 { 5623 /* 5624 * Loop over all paths in the 'path' or 'cdpath' option. 5625 * When "first" is set, first setup to the start of the option. 5626 * Otherwise continue to find the next match. 5627 */ 5628 if (first == TRUE) 5629 { 5630 /* vim_findfile_free_visited can handle a possible NULL pointer */ 5631 vim_findfile_free_visited(fdip_search_ctx); 5632 dir = path_option; 5633 did_findfile_init = FALSE; 5634 } 5635 5636 for (;;) 5637 { 5638 if (did_findfile_init) 5639 { 5640 file_name = vim_findfile(fdip_search_ctx); 5641 if (file_name != NULL) 5642 break; 5643 5644 did_findfile_init = FALSE; 5645 } 5646 else 5647 { 5648 char_u *r_ptr; 5649 5650 if (dir == NULL || *dir == NUL) 5651 { 5652 /* We searched all paths of the option, now we can 5653 * free the search context. */ 5654 vim_findfile_cleanup(fdip_search_ctx); 5655 fdip_search_ctx = NULL; 5656 break; 5657 } 5658 5659 if ((buf = alloc((int)(MAXPATHL))) == NULL) 5660 break; 5661 5662 /* copy next path */ 5663 buf[0] = 0; 5664 copy_option_part(&dir, buf, MAXPATHL, " ,"); 5665 5666 #ifdef FEAT_PATH_EXTRA 5667 /* get the stopdir string */ 5668 r_ptr = vim_findfile_stopdir(buf); 5669 #else 5670 r_ptr = NULL; 5671 #endif 5672 fdip_search_ctx = vim_findfile_init(buf, ff_file_to_find, 5673 r_ptr, 100, FALSE, find_what, 5674 fdip_search_ctx, FALSE, rel_fname); 5675 if (fdip_search_ctx != NULL) 5676 did_findfile_init = TRUE; 5677 vim_free(buf); 5678 } 5679 } 5680 } 5681 if (file_name == NULL && (options & FNAME_MESS)) 5682 { 5683 if (first == TRUE) 5684 { 5685 if (find_what == FINDFILE_DIR) 5686 EMSG2(_("E344: Can't find directory \"%s\" in cdpath"), 5687 ff_file_to_find); 5688 else 5689 EMSG2(_("E345: Can't find file \"%s\" in path"), 5690 ff_file_to_find); 5691 } 5692 else 5693 { 5694 if (find_what == FINDFILE_DIR) 5695 EMSG2(_("E346: No more directory \"%s\" found in cdpath"), 5696 ff_file_to_find); 5697 else 5698 EMSG2(_("E347: No more file \"%s\" found in path"), 5699 ff_file_to_find); 5700 } 5701 } 5702 5703 theend: 5704 #ifdef AMIGA 5705 proc->pr_WindowPtr = save_winptr; 5706 #endif 5707 return file_name; 5708 } 5709 5710 #endif /* FEAT_SEARCHPATH */ 5711 5712 /* 5713 * Change directory to "new_dir". If FEAT_SEARCHPATH is defined, search 5714 * 'cdpath' for relative directory names, otherwise just mch_chdir(). 5715 */ 5716 int 5717 vim_chdir(new_dir) 5718 char_u *new_dir; 5719 { 5720 #ifndef FEAT_SEARCHPATH 5721 return mch_chdir((char *)new_dir); 5722 #else 5723 char_u *dir_name; 5724 int r; 5725 5726 dir_name = find_directory_in_path(new_dir, (int)STRLEN(new_dir), 5727 FNAME_MESS, curbuf->b_ffname); 5728 if (dir_name == NULL) 5729 return -1; 5730 r = mch_chdir((char *)dir_name); 5731 vim_free(dir_name); 5732 return r; 5733 #endif 5734 } 5735 5736 /* 5737 * Get user name from machine-specific function. 5738 * Returns the user name in "buf[len]". 5739 * Some systems are quite slow in obtaining the user name (Windows NT), thus 5740 * cache the result. 5741 * Returns OK or FAIL. 5742 */ 5743 int 5744 get_user_name(buf, len) 5745 char_u *buf; 5746 int len; 5747 { 5748 if (username == NULL) 5749 { 5750 if (mch_get_user_name(buf, len) == FAIL) 5751 return FAIL; 5752 username = vim_strsave(buf); 5753 } 5754 else 5755 vim_strncpy(buf, username, len - 1); 5756 return OK; 5757 } 5758 5759 #ifndef HAVE_QSORT 5760 /* 5761 * Our own qsort(), for systems that don't have it. 5762 * It's simple and slow. From the K&R C book. 5763 */ 5764 void 5765 qsort(base, elm_count, elm_size, cmp) 5766 void *base; 5767 size_t elm_count; 5768 size_t elm_size; 5769 int (*cmp) __ARGS((const void *, const void *)); 5770 { 5771 char_u *buf; 5772 char_u *p1; 5773 char_u *p2; 5774 int i, j; 5775 int gap; 5776 5777 buf = alloc((unsigned)elm_size); 5778 if (buf == NULL) 5779 return; 5780 5781 for (gap = elm_count / 2; gap > 0; gap /= 2) 5782 for (i = gap; i < elm_count; ++i) 5783 for (j = i - gap; j >= 0; j -= gap) 5784 { 5785 /* Compare the elements. */ 5786 p1 = (char_u *)base + j * elm_size; 5787 p2 = (char_u *)base + (j + gap) * elm_size; 5788 if ((*cmp)((void *)p1, (void *)p2) <= 0) 5789 break; 5790 /* Exchange the elements. */ 5791 mch_memmove(buf, p1, elm_size); 5792 mch_memmove(p1, p2, elm_size); 5793 mch_memmove(p2, buf, elm_size); 5794 } 5795 5796 vim_free(buf); 5797 } 5798 #endif 5799 5800 /* 5801 * Sort an array of strings. 5802 */ 5803 static int 5804 #ifdef __BORLANDC__ 5805 _RTLENTRYF 5806 #endif 5807 sort_compare __ARGS((const void *s1, const void *s2)); 5808 5809 static int 5810 #ifdef __BORLANDC__ 5811 _RTLENTRYF 5812 #endif 5813 sort_compare(s1, s2) 5814 const void *s1; 5815 const void *s2; 5816 { 5817 return STRCMP(*(char **)s1, *(char **)s2); 5818 } 5819 5820 void 5821 sort_strings(files, count) 5822 char_u **files; 5823 int count; 5824 { 5825 qsort((void *)files, (size_t)count, sizeof(char_u *), sort_compare); 5826 } 5827 5828 #if !defined(NO_EXPANDPATH) || defined(PROTO) 5829 /* 5830 * Compare path "p[]" to "q[]". 5831 * If "maxlen" >= 0 compare "p[maxlen]" to "q[maxlen]" 5832 * Return value like strcmp(p, q), but consider path separators. 5833 */ 5834 int 5835 pathcmp(p, q, maxlen) 5836 const char *p, *q; 5837 int maxlen; 5838 { 5839 int i; 5840 int c1, c2; 5841 const char *s = NULL; 5842 5843 for (i = 0; maxlen < 0 || i < maxlen; i += MB_PTR2LEN((char_u *)p + i)) 5844 { 5845 c1 = PTR2CHAR((char_u *)p + i); 5846 c2 = PTR2CHAR((char_u *)q + i); 5847 5848 /* End of "p": check if "q" also ends or just has a slash. */ 5849 if (c1 == NUL) 5850 { 5851 if (c2 == NUL) /* full match */ 5852 return 0; 5853 s = q; 5854 break; 5855 } 5856 5857 /* End of "q": check if "p" just has a slash. */ 5858 if (c2 == NUL) 5859 { 5860 s = p; 5861 break; 5862 } 5863 5864 if ((p_fic ? MB_TOUPPER(c1) != MB_TOUPPER(c2) : c1 != c2) 5865 #ifdef BACKSLASH_IN_FILENAME 5866 /* consider '/' and '\\' to be equal */ 5867 && !((c1 == '/' && c2 == '\\') 5868 || (c1 == '\\' && c2 == '/')) 5869 #endif 5870 ) 5871 { 5872 if (vim_ispathsep(c1)) 5873 return -1; 5874 if (vim_ispathsep(c2)) 5875 return 1; 5876 return p_fic ? MB_TOUPPER(c1) - MB_TOUPPER(c2) 5877 : c1 - c2; /* no match */ 5878 } 5879 } 5880 if (s == NULL) /* "i" ran into "maxlen" */ 5881 return 0; 5882 5883 c1 = PTR2CHAR((char_u *)s + i); 5884 c2 = PTR2CHAR((char_u *)s + i + MB_PTR2LEN((char_u *)s + i)); 5885 /* ignore a trailing slash, but not "//" or ":/" */ 5886 if (c2 == NUL 5887 && i > 0 5888 && !after_pathsep((char_u *)s, (char_u *)s + i) 5889 #ifdef BACKSLASH_IN_FILENAME 5890 && (c1 == '/' || c1 == '\\') 5891 #else 5892 && c1 == '/' 5893 #endif 5894 ) 5895 return 0; /* match with trailing slash */ 5896 if (s == q) 5897 return -1; /* no match */ 5898 return 1; 5899 } 5900 #endif 5901 5902 /* 5903 * The putenv() implementation below comes from the "screen" program. 5904 * Included with permission from Juergen Weigert. 5905 * See pty.c for the copyright notice. 5906 */ 5907 5908 /* 5909 * putenv -- put value into environment 5910 * 5911 * Usage: i = putenv (string) 5912 * int i; 5913 * char *string; 5914 * 5915 * where string is of the form <name>=<value>. 5916 * Putenv returns 0 normally, -1 on error (not enough core for malloc). 5917 * 5918 * Putenv may need to add a new name into the environment, or to 5919 * associate a value longer than the current value with a particular 5920 * name. So, to make life simpler, putenv() copies your entire 5921 * environment into the heap (i.e. malloc()) from the stack 5922 * (i.e. where it resides when your process is initiated) the first 5923 * time you call it. 5924 * 5925 * (history removed, not very interesting. See the "screen" sources.) 5926 */ 5927 5928 #if !defined(HAVE_SETENV) && !defined(HAVE_PUTENV) 5929 5930 #define EXTRASIZE 5 /* increment to add to env. size */ 5931 5932 static int envsize = -1; /* current size of environment */ 5933 #ifndef MACOS_CLASSIC 5934 extern 5935 #endif 5936 char **environ; /* the global which is your env. */ 5937 5938 static int findenv __ARGS((char *name)); /* look for a name in the env. */ 5939 static int newenv __ARGS((void)); /* copy env. from stack to heap */ 5940 static int moreenv __ARGS((void)); /* incr. size of env. */ 5941 5942 int 5943 putenv(string) 5944 const char *string; 5945 { 5946 int i; 5947 char *p; 5948 5949 if (envsize < 0) 5950 { /* first time putenv called */ 5951 if (newenv() < 0) /* copy env. to heap */ 5952 return -1; 5953 } 5954 5955 i = findenv((char *)string); /* look for name in environment */ 5956 5957 if (i < 0) 5958 { /* name must be added */ 5959 for (i = 0; environ[i]; i++); 5960 if (i >= (envsize - 1)) 5961 { /* need new slot */ 5962 if (moreenv() < 0) 5963 return -1; 5964 } 5965 p = (char *)alloc((unsigned)(strlen(string) + 1)); 5966 if (p == NULL) /* not enough core */ 5967 return -1; 5968 environ[i + 1] = 0; /* new end of env. */ 5969 } 5970 else 5971 { /* name already in env. */ 5972 p = vim_realloc(environ[i], strlen(string) + 1); 5973 if (p == NULL) 5974 return -1; 5975 } 5976 sprintf(p, "%s", string); /* copy into env. */ 5977 environ[i] = p; 5978 5979 return 0; 5980 } 5981 5982 static int 5983 findenv(name) 5984 char *name; 5985 { 5986 char *namechar, *envchar; 5987 int i, found; 5988 5989 found = 0; 5990 for (i = 0; environ[i] && !found; i++) 5991 { 5992 envchar = environ[i]; 5993 namechar = name; 5994 while (*namechar && *namechar != '=' && (*namechar == *envchar)) 5995 { 5996 namechar++; 5997 envchar++; 5998 } 5999 found = ((*namechar == '\0' || *namechar == '=') && *envchar == '='); 6000 } 6001 return found ? i - 1 : -1; 6002 } 6003 6004 static int 6005 newenv() 6006 { 6007 char **env, *elem; 6008 int i, esize; 6009 6010 #ifdef MACOS 6011 /* for Mac a new, empty environment is created */ 6012 i = 0; 6013 #else 6014 for (i = 0; environ[i]; i++) 6015 ; 6016 #endif 6017 esize = i + EXTRASIZE + 1; 6018 env = (char **)alloc((unsigned)(esize * sizeof (elem))); 6019 if (env == NULL) 6020 return -1; 6021 6022 #ifndef MACOS 6023 for (i = 0; environ[i]; i++) 6024 { 6025 elem = (char *)alloc((unsigned)(strlen(environ[i]) + 1)); 6026 if (elem == NULL) 6027 return -1; 6028 env[i] = elem; 6029 strcpy(elem, environ[i]); 6030 } 6031 #endif 6032 6033 env[i] = 0; 6034 environ = env; 6035 envsize = esize; 6036 return 0; 6037 } 6038 6039 static int 6040 moreenv() 6041 { 6042 int esize; 6043 char **env; 6044 6045 esize = envsize + EXTRASIZE; 6046 env = (char **)vim_realloc((char *)environ, esize * sizeof (*env)); 6047 if (env == 0) 6048 return -1; 6049 environ = env; 6050 envsize = esize; 6051 return 0; 6052 } 6053 6054 # ifdef USE_VIMPTY_GETENV 6055 char_u * 6056 vimpty_getenv(string) 6057 const char_u *string; 6058 { 6059 int i; 6060 char_u *p; 6061 6062 if (envsize < 0) 6063 return NULL; 6064 6065 i = findenv((char *)string); 6066 6067 if (i < 0) 6068 return NULL; 6069 6070 p = vim_strchr((char_u *)environ[i], '='); 6071 return (p + 1); 6072 } 6073 # endif 6074 6075 #endif /* !defined(HAVE_SETENV) && !defined(HAVE_PUTENV) */ 6076 6077 #if defined(FEAT_EVAL) || defined(FEAT_SPELL) || defined(PROTO) 6078 /* 6079 * Return 0 for not writable, 1 for writable file, 2 for a dir which we have 6080 * rights to write into. 6081 */ 6082 int 6083 filewritable(fname) 6084 char_u *fname; 6085 { 6086 int retval = 0; 6087 #if defined(UNIX) || defined(VMS) 6088 int perm = 0; 6089 #endif 6090 6091 #if defined(UNIX) || defined(VMS) 6092 perm = mch_getperm(fname); 6093 #endif 6094 #ifndef MACOS_CLASSIC /* TODO: get either mch_writable or mch_access */ 6095 if ( 6096 # ifdef WIN3264 6097 mch_writable(fname) && 6098 # else 6099 # if defined(UNIX) || defined(VMS) 6100 (perm & 0222) && 6101 # endif 6102 # endif 6103 mch_access((char *)fname, W_OK) == 0 6104 ) 6105 #endif 6106 { 6107 ++retval; 6108 if (mch_isdir(fname)) 6109 ++retval; 6110 } 6111 return retval; 6112 } 6113 #endif 6114 6115 /* 6116 * Print an error message with one or two "%s" and one or two string arguments. 6117 * This is not in message.c to avoid a warning for prototypes. 6118 */ 6119 int 6120 emsg3(s, a1, a2) 6121 char_u *s, *a1, *a2; 6122 { 6123 if (emsg_not_now()) 6124 return TRUE; /* no error messages at the moment */ 6125 #ifdef HAVE_STDARG_H 6126 vim_snprintf((char *)IObuff, IOSIZE, (char *)s, a1, a2); 6127 #else 6128 vim_snprintf((char *)IObuff, IOSIZE, (char *)s, (long_u)a1, (long_u)a2); 6129 #endif 6130 return emsg(IObuff); 6131 } 6132 6133 /* 6134 * Print an error message with one "%ld" and one long int argument. 6135 * This is not in message.c to avoid a warning for prototypes. 6136 */ 6137 int 6138 emsgn(s, n) 6139 char_u *s; 6140 long n; 6141 { 6142 if (emsg_not_now()) 6143 return TRUE; /* no error messages at the moment */ 6144 vim_snprintf((char *)IObuff, IOSIZE, (char *)s, n); 6145 return emsg(IObuff); 6146 } 6147 6148 #if defined(FEAT_SPELL) || defined(FEAT_PERSISTENT_UNDO) || defined(PROTO) 6149 /* 6150 * Read 2 bytes from "fd" and turn them into an int, MSB first. 6151 */ 6152 int 6153 get2c(fd) 6154 FILE *fd; 6155 { 6156 int n; 6157 6158 n = getc(fd); 6159 n = (n << 8) + getc(fd); 6160 return n; 6161 } 6162 6163 /* 6164 * Read 3 bytes from "fd" and turn them into an int, MSB first. 6165 */ 6166 int 6167 get3c(fd) 6168 FILE *fd; 6169 { 6170 int n; 6171 6172 n = getc(fd); 6173 n = (n << 8) + getc(fd); 6174 n = (n << 8) + getc(fd); 6175 return n; 6176 } 6177 6178 /* 6179 * Read 4 bytes from "fd" and turn them into an int, MSB first. 6180 */ 6181 int 6182 get4c(fd) 6183 FILE *fd; 6184 { 6185 /* Use unsigned rather than int otherwise result is undefined 6186 * when left-shift sets the MSB. */ 6187 unsigned n; 6188 6189 n = (unsigned)getc(fd); 6190 n = (n << 8) + (unsigned)getc(fd); 6191 n = (n << 8) + (unsigned)getc(fd); 6192 n = (n << 8) + (unsigned)getc(fd); 6193 return (int)n; 6194 } 6195 6196 /* 6197 * Read 8 bytes from "fd" and turn them into a time_t, MSB first. 6198 */ 6199 time_t 6200 get8ctime(fd) 6201 FILE *fd; 6202 { 6203 time_t n = 0; 6204 int i; 6205 6206 for (i = 0; i < 8; ++i) 6207 n = (n << 8) + getc(fd); 6208 return n; 6209 } 6210 6211 /* 6212 * Read a string of length "cnt" from "fd" into allocated memory. 6213 * Returns NULL when out of memory or unable to read that many bytes. 6214 */ 6215 char_u * 6216 read_string(fd, cnt) 6217 FILE *fd; 6218 int cnt; 6219 { 6220 char_u *str; 6221 int i; 6222 int c; 6223 6224 /* allocate memory */ 6225 str = alloc((unsigned)cnt + 1); 6226 if (str != NULL) 6227 { 6228 /* Read the string. Quit when running into the EOF. */ 6229 for (i = 0; i < cnt; ++i) 6230 { 6231 c = getc(fd); 6232 if (c == EOF) 6233 { 6234 vim_free(str); 6235 return NULL; 6236 } 6237 str[i] = c; 6238 } 6239 str[i] = NUL; 6240 } 6241 return str; 6242 } 6243 6244 /* 6245 * Write a number to file "fd", MSB first, in "len" bytes. 6246 */ 6247 int 6248 put_bytes(fd, nr, len) 6249 FILE *fd; 6250 long_u nr; 6251 int len; 6252 { 6253 int i; 6254 6255 for (i = len - 1; i >= 0; --i) 6256 if (putc((int)(nr >> (i * 8)), fd) == EOF) 6257 return FAIL; 6258 return OK; 6259 } 6260 6261 #ifdef _MSC_VER 6262 # if (_MSC_VER <= 1200) 6263 /* This line is required for VC6 without the service pack. Also see the 6264 * matching #pragma below. */ 6265 # pragma optimize("", off) 6266 # endif 6267 #endif 6268 6269 /* 6270 * Write time_t to file "fd" in 8 bytes. 6271 */ 6272 void 6273 put_time(fd, the_time) 6274 FILE *fd; 6275 time_t the_time; 6276 { 6277 char_u buf[8]; 6278 6279 time_to_bytes(the_time, buf); 6280 fwrite(buf, (size_t)8, (size_t)1, fd); 6281 } 6282 6283 /* 6284 * Write time_t to "buf[8]". 6285 */ 6286 void 6287 time_to_bytes(the_time, buf) 6288 time_t the_time; 6289 char_u *buf; 6290 { 6291 int c; 6292 int i; 6293 int bi = 0; 6294 time_t wtime = the_time; 6295 6296 /* time_t can be up to 8 bytes in size, more than long_u, thus we 6297 * can't use put_bytes() here. 6298 * Another problem is that ">>" may do an arithmetic shift that keeps the 6299 * sign. This happens for large values of wtime. A cast to long_u may 6300 * truncate if time_t is 8 bytes. So only use a cast when it is 4 bytes, 6301 * it's safe to assume that long_u is 4 bytes or more and when using 8 6302 * bytes the top bit won't be set. */ 6303 for (i = 7; i >= 0; --i) 6304 { 6305 if (i + 1 > (int)sizeof(time_t)) 6306 /* ">>" doesn't work well when shifting more bits than avail */ 6307 buf[bi++] = 0; 6308 else 6309 { 6310 #if defined(SIZEOF_TIME_T) && SIZEOF_TIME_T > 4 6311 c = (int)(wtime >> (i * 8)); 6312 #else 6313 c = (int)((long_u)wtime >> (i * 8)); 6314 #endif 6315 buf[bi++] = c; 6316 } 6317 } 6318 } 6319 6320 #ifdef _MSC_VER 6321 # if (_MSC_VER <= 1200) 6322 # pragma optimize("", on) 6323 # endif 6324 #endif 6325 6326 #endif 6327 6328 #if (defined(FEAT_MBYTE) && defined(FEAT_QUICKFIX)) \ 6329 || defined(FEAT_SPELL) || defined(PROTO) 6330 /* 6331 * Return TRUE if string "s" contains a non-ASCII character (128 or higher). 6332 * When "s" is NULL FALSE is returned. 6333 */ 6334 int 6335 has_non_ascii(s) 6336 char_u *s; 6337 { 6338 char_u *p; 6339 6340 if (s != NULL) 6341 for (p = s; *p != NUL; ++p) 6342 if (*p >= 128) 6343 return TRUE; 6344 return FALSE; 6345 } 6346 #endif 6347