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 * misc1.c: functions that didn't seem to fit elsewhere 12 */ 13 14 #include "vim.h" 15 #include "version.h" 16 17 #ifdef HAVE_FCNTL_H 18 # include <fcntl.h> /* for chdir() */ 19 #endif 20 21 static char_u *vim_version_dir __ARGS((char_u *vimdir)); 22 static char_u *remove_tail __ARGS((char_u *p, char_u *pend, char_u *name)); 23 #if defined(USE_EXE_NAME) && defined(MACOS_X) 24 static char_u *remove_tail_with_ext __ARGS((char_u *p, char_u *pend, char_u *ext)); 25 #endif 26 static int get_indent_str __ARGS((char_u *ptr, int ts)); 27 static int copy_indent __ARGS((int size, char_u *src)); 28 29 /* 30 * Count the size (in window cells) of the indent in the current line. 31 */ 32 int 33 get_indent() 34 { 35 return get_indent_str(ml_get_curline(), (int)curbuf->b_p_ts); 36 } 37 38 /* 39 * Count the size (in window cells) of the indent in line "lnum". 40 */ 41 int 42 get_indent_lnum(lnum) 43 linenr_T lnum; 44 { 45 return get_indent_str(ml_get(lnum), (int)curbuf->b_p_ts); 46 } 47 48 #if defined(FEAT_FOLDING) || defined(PROTO) 49 /* 50 * Count the size (in window cells) of the indent in line "lnum" of buffer 51 * "buf". 52 */ 53 int 54 get_indent_buf(buf, lnum) 55 buf_T *buf; 56 linenr_T lnum; 57 { 58 return get_indent_str(ml_get_buf(buf, lnum, FALSE), (int)buf->b_p_ts); 59 } 60 #endif 61 62 /* 63 * count the size (in window cells) of the indent in line "ptr", with 64 * 'tabstop' at "ts" 65 */ 66 static int 67 get_indent_str(ptr, ts) 68 char_u *ptr; 69 int ts; 70 { 71 int count = 0; 72 73 for ( ; *ptr; ++ptr) 74 { 75 if (*ptr == TAB) /* count a tab for what it is worth */ 76 count += ts - (count % ts); 77 else if (*ptr == ' ') 78 ++count; /* count a space for one */ 79 else 80 break; 81 } 82 return (count); 83 } 84 85 /* 86 * Set the indent of the current line. 87 * Leaves the cursor on the first non-blank in the line. 88 * Caller must take care of undo. 89 * "flags": 90 * SIN_CHANGED: call changed_bytes() if the line was changed. 91 * SIN_INSERT: insert the indent in front of the line. 92 * SIN_UNDO: save line for undo before changing it. 93 * Returns TRUE if the line was changed. 94 */ 95 int 96 set_indent(size, flags) 97 int size; 98 int flags; 99 { 100 char_u *p; 101 char_u *newline; 102 char_u *oldline; 103 char_u *s; 104 int todo; 105 int ind_len; 106 int line_len; 107 int doit = FALSE; 108 int ind_done; 109 int tab_pad; 110 111 /* 112 * First check if there is anything to do and compute the number of 113 * characters needed for the indent. 114 */ 115 todo = size; 116 ind_len = 0; 117 p = oldline = ml_get_curline(); 118 119 /* Calculate the buffer size for the new indent, and check to see if it 120 * isn't already set */ 121 122 /* if 'expandtab' isn't set: use TABs */ 123 if (!curbuf->b_p_et) 124 { 125 /* If 'preserveindent' is set then reuse as much as possible of 126 * the existing indent structure for the new indent */ 127 if (!(flags & SIN_INSERT) && curbuf->b_p_pi) 128 { 129 ind_done = 0; 130 131 /* count as many characters as we can use */ 132 while (todo > 0 && vim_iswhite(*p)) 133 { 134 if (*p == TAB) 135 { 136 tab_pad = (int)curbuf->b_p_ts 137 - (ind_done % (int)curbuf->b_p_ts); 138 /* stop if this tab will overshoot the target */ 139 if (todo < tab_pad) 140 break; 141 todo -= tab_pad; 142 ++ind_len; 143 ind_done += tab_pad; 144 } 145 else 146 { 147 --todo; 148 ++ind_len; 149 ++ind_done; 150 } 151 ++p; 152 } 153 154 /* Fill to next tabstop with a tab, if possible */ 155 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); 156 if (todo >= tab_pad) 157 { 158 doit = TRUE; 159 todo -= tab_pad; 160 ++ind_len; 161 /* ind_done += tab_pad; */ 162 } 163 } 164 165 /* count tabs required for indent */ 166 while (todo >= (int)curbuf->b_p_ts) 167 { 168 if (*p != TAB) 169 doit = TRUE; 170 else 171 ++p; 172 todo -= (int)curbuf->b_p_ts; 173 ++ind_len; 174 /* ind_done += (int)curbuf->b_p_ts; */ 175 } 176 } 177 /* count spaces required for indent */ 178 while (todo > 0) 179 { 180 if (*p != ' ') 181 doit = TRUE; 182 else 183 ++p; 184 --todo; 185 ++ind_len; 186 /* ++ind_done; */ 187 } 188 189 /* Return if the indent is OK already. */ 190 if (!doit && !vim_iswhite(*p) && !(flags & SIN_INSERT)) 191 return FALSE; 192 193 /* Allocate memory for the new line. */ 194 if (flags & SIN_INSERT) 195 p = oldline; 196 else 197 p = skipwhite(p); 198 line_len = (int)STRLEN(p) + 1; 199 newline = alloc(ind_len + line_len); 200 if (newline == NULL) 201 return FALSE; 202 203 /* Put the characters in the new line. */ 204 s = newline; 205 todo = size; 206 /* if 'expandtab' isn't set: use TABs */ 207 if (!curbuf->b_p_et) 208 { 209 /* If 'preserveindent' is set then reuse as much as possible of 210 * the existing indent structure for the new indent */ 211 if (!(flags & SIN_INSERT) && curbuf->b_p_pi) 212 { 213 p = oldline; 214 ind_done = 0; 215 216 while (todo > 0 && vim_iswhite(*p)) 217 { 218 if (*p == TAB) 219 { 220 tab_pad = (int)curbuf->b_p_ts 221 - (ind_done % (int)curbuf->b_p_ts); 222 /* stop if this tab will overshoot the target */ 223 if (todo < tab_pad) 224 break; 225 todo -= tab_pad; 226 ind_done += tab_pad; 227 } 228 else 229 { 230 --todo; 231 ++ind_done; 232 } 233 *s++ = *p++; 234 } 235 236 /* Fill to next tabstop with a tab, if possible */ 237 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); 238 if (todo >= tab_pad) 239 { 240 *s++ = TAB; 241 todo -= tab_pad; 242 } 243 244 p = skipwhite(p); 245 } 246 247 while (todo >= (int)curbuf->b_p_ts) 248 { 249 *s++ = TAB; 250 todo -= (int)curbuf->b_p_ts; 251 } 252 } 253 while (todo > 0) 254 { 255 *s++ = ' '; 256 --todo; 257 } 258 mch_memmove(s, p, (size_t)line_len); 259 260 /* Replace the line (unless undo fails). */ 261 if (!(flags & SIN_UNDO) || u_savesub(curwin->w_cursor.lnum) == OK) 262 { 263 ml_replace(curwin->w_cursor.lnum, newline, FALSE); 264 if (flags & SIN_CHANGED) 265 changed_bytes(curwin->w_cursor.lnum, 0); 266 /* Correct saved cursor position if it's after the indent. */ 267 if (saved_cursor.lnum == curwin->w_cursor.lnum 268 && saved_cursor.col >= (colnr_T)(p - oldline)) 269 saved_cursor.col += ind_len - (p - oldline); 270 } 271 else 272 vim_free(newline); 273 274 curwin->w_cursor.col = ind_len; 275 return TRUE; 276 } 277 278 /* 279 * Copy the indent from ptr to the current line (and fill to size) 280 * Leaves the cursor on the first non-blank in the line. 281 * Returns TRUE if the line was changed. 282 */ 283 static int 284 copy_indent(size, src) 285 int size; 286 char_u *src; 287 { 288 char_u *p = NULL; 289 char_u *line = NULL; 290 char_u *s; 291 int todo; 292 int ind_len; 293 int line_len = 0; 294 int tab_pad; 295 int ind_done; 296 int round; 297 298 /* Round 1: compute the number of characters needed for the indent 299 * Round 2: copy the characters. */ 300 for (round = 1; round <= 2; ++round) 301 { 302 todo = size; 303 ind_len = 0; 304 ind_done = 0; 305 s = src; 306 307 /* Count/copy the usable portion of the source line */ 308 while (todo > 0 && vim_iswhite(*s)) 309 { 310 if (*s == TAB) 311 { 312 tab_pad = (int)curbuf->b_p_ts 313 - (ind_done % (int)curbuf->b_p_ts); 314 /* Stop if this tab will overshoot the target */ 315 if (todo < tab_pad) 316 break; 317 todo -= tab_pad; 318 ind_done += tab_pad; 319 } 320 else 321 { 322 --todo; 323 ++ind_done; 324 } 325 ++ind_len; 326 if (round == 2) 327 *p++ = *s; 328 ++s; 329 } 330 331 /* Fill to next tabstop with a tab, if possible */ 332 tab_pad = (int)curbuf->b_p_ts - (ind_done % (int)curbuf->b_p_ts); 333 if (todo >= tab_pad) 334 { 335 todo -= tab_pad; 336 ++ind_len; 337 if (round == 2) 338 *p++ = TAB; 339 } 340 341 /* Add tabs required for indent */ 342 while (todo >= (int)curbuf->b_p_ts) 343 { 344 todo -= (int)curbuf->b_p_ts; 345 ++ind_len; 346 if (round == 2) 347 *p++ = TAB; 348 } 349 350 /* Count/add spaces required for indent */ 351 while (todo > 0) 352 { 353 --todo; 354 ++ind_len; 355 if (round == 2) 356 *p++ = ' '; 357 } 358 359 if (round == 1) 360 { 361 /* Allocate memory for the result: the copied indent, new indent 362 * and the rest of the line. */ 363 line_len = (int)STRLEN(ml_get_curline()) + 1; 364 line = alloc(ind_len + line_len); 365 if (line == NULL) 366 return FALSE; 367 p = line; 368 } 369 } 370 371 /* Append the original line */ 372 mch_memmove(p, ml_get_curline(), (size_t)line_len); 373 374 /* Replace the line */ 375 ml_replace(curwin->w_cursor.lnum, line, FALSE); 376 377 /* Put the cursor after the indent. */ 378 curwin->w_cursor.col = ind_len; 379 return TRUE; 380 } 381 382 /* 383 * Return the indent of the current line after a number. Return -1 if no 384 * number was found. Used for 'n' in 'formatoptions': numbered list. 385 */ 386 int 387 get_number_indent(lnum) 388 linenr_T lnum; 389 { 390 char_u *line; 391 char_u *p; 392 colnr_T col; 393 pos_T pos; 394 395 if (lnum > curbuf->b_ml.ml_line_count) 396 return -1; 397 line = ml_get(lnum); 398 p = skipwhite(line); 399 if (!VIM_ISDIGIT(*p)) 400 return -1; 401 p = skipdigits(p); 402 if (vim_strchr((char_u *)":.)]}\t ", *p) == NULL) 403 return -1; 404 p = skipwhite(p + 1); 405 if (*p == NUL) 406 return -1; 407 pos.lnum = lnum; 408 pos.col = (colnr_T)(p - line); 409 getvcol(curwin, &pos, &col, NULL, NULL); 410 return (int)col; 411 } 412 413 #if defined(FEAT_CINDENT) || defined(FEAT_SMARTINDENT) 414 415 static int cin_is_cinword __ARGS((char_u *line)); 416 417 /* 418 * Return TRUE if the string "line" starts with a word from 'cinwords'. 419 */ 420 static int 421 cin_is_cinword(line) 422 char_u *line; 423 { 424 char_u *cinw; 425 char_u *cinw_buf; 426 int cinw_len; 427 int retval = FALSE; 428 int len; 429 430 cinw_len = (int)STRLEN(curbuf->b_p_cinw) + 1; 431 cinw_buf = alloc((unsigned)cinw_len); 432 if (cinw_buf != NULL) 433 { 434 line = skipwhite(line); 435 for (cinw = curbuf->b_p_cinw; *cinw; ) 436 { 437 len = copy_option_part(&cinw, cinw_buf, cinw_len, ","); 438 if (STRNCMP(line, cinw_buf, len) == 0 439 && (!vim_iswordc(line[len]) || !vim_iswordc(line[len - 1]))) 440 { 441 retval = TRUE; 442 break; 443 } 444 } 445 vim_free(cinw_buf); 446 } 447 return retval; 448 } 449 #endif 450 451 /* 452 * open_line: Add a new line below or above the current line. 453 * 454 * For VREPLACE mode, we only add a new line when we get to the end of the 455 * file, otherwise we just start replacing the next line. 456 * 457 * Caller must take care of undo. Since VREPLACE may affect any number of 458 * lines however, it may call u_save_cursor() again when starting to change a 459 * new line. 460 * "flags": OPENLINE_DELSPACES delete spaces after cursor 461 * OPENLINE_DO_COM format comments 462 * OPENLINE_KEEPTRAIL keep trailing spaces 463 * OPENLINE_MARKFIX adjust mark positions after the line break 464 * 465 * Return TRUE for success, FALSE for failure 466 */ 467 int 468 open_line(dir, flags, old_indent) 469 int dir; /* FORWARD or BACKWARD */ 470 int flags; 471 int old_indent; /* indent for after ^^D in Insert mode */ 472 { 473 char_u *saved_line; /* copy of the original line */ 474 char_u *next_line = NULL; /* copy of the next line */ 475 char_u *p_extra = NULL; /* what goes to next line */ 476 int less_cols = 0; /* less columns for mark in new line */ 477 int less_cols_off = 0; /* columns to skip for mark adjust */ 478 pos_T old_cursor; /* old cursor position */ 479 int newcol = 0; /* new cursor column */ 480 int newindent = 0; /* auto-indent of the new line */ 481 int n; 482 int trunc_line = FALSE; /* truncate current line afterwards */ 483 int retval = FALSE; /* return value, default is FAIL */ 484 #ifdef FEAT_COMMENTS 485 int extra_len = 0; /* length of p_extra string */ 486 int lead_len; /* length of comment leader */ 487 char_u *lead_flags; /* position in 'comments' for comment leader */ 488 char_u *leader = NULL; /* copy of comment leader */ 489 #endif 490 char_u *allocated = NULL; /* allocated memory */ 491 #if defined(FEAT_SMARTINDENT) || defined(FEAT_VREPLACE) || defined(FEAT_LISP) \ 492 || defined(FEAT_CINDENT) || defined(FEAT_COMMENTS) 493 char_u *p; 494 #endif 495 int saved_char = NUL; /* init for GCC */ 496 #if defined(FEAT_SMARTINDENT) || defined(FEAT_COMMENTS) 497 pos_T *pos; 498 #endif 499 #ifdef FEAT_SMARTINDENT 500 int do_si = (!p_paste && curbuf->b_p_si 501 # ifdef FEAT_CINDENT 502 && !curbuf->b_p_cin 503 # endif 504 ); 505 int no_si = FALSE; /* reset did_si afterwards */ 506 int first_char = NUL; /* init for GCC */ 507 #endif 508 #if defined(FEAT_VREPLACE) && (defined(FEAT_LISP) || defined(FEAT_CINDENT)) 509 int vreplace_mode; 510 #endif 511 int did_append; /* appended a new line */ 512 int saved_pi = curbuf->b_p_pi; /* copy of preserveindent setting */ 513 514 /* 515 * make a copy of the current line so we can mess with it 516 */ 517 saved_line = vim_strsave(ml_get_curline()); 518 if (saved_line == NULL) /* out of memory! */ 519 return FALSE; 520 521 #ifdef FEAT_VREPLACE 522 if (State & VREPLACE_FLAG) 523 { 524 /* 525 * With VREPLACE we make a copy of the next line, which we will be 526 * starting to replace. First make the new line empty and let vim play 527 * with the indenting and comment leader to its heart's content. Then 528 * we grab what it ended up putting on the new line, put back the 529 * original line, and call ins_char() to put each new character onto 530 * the line, replacing what was there before and pushing the right 531 * stuff onto the replace stack. -- webb. 532 */ 533 if (curwin->w_cursor.lnum < orig_line_count) 534 next_line = vim_strsave(ml_get(curwin->w_cursor.lnum + 1)); 535 else 536 next_line = vim_strsave((char_u *)""); 537 if (next_line == NULL) /* out of memory! */ 538 goto theend; 539 540 /* 541 * In VREPLACE mode, a NL replaces the rest of the line, and starts 542 * replacing the next line, so push all of the characters left on the 543 * line onto the replace stack. We'll push any other characters that 544 * might be replaced at the start of the next line (due to autoindent 545 * etc) a bit later. 546 */ 547 replace_push(NUL); /* Call twice because BS over NL expects it */ 548 replace_push(NUL); 549 p = saved_line + curwin->w_cursor.col; 550 while (*p != NUL) 551 replace_push(*p++); 552 saved_line[curwin->w_cursor.col] = NUL; 553 } 554 #endif 555 556 if ((State & INSERT) 557 #ifdef FEAT_VREPLACE 558 && !(State & VREPLACE_FLAG) 559 #endif 560 ) 561 { 562 p_extra = saved_line + curwin->w_cursor.col; 563 #ifdef FEAT_SMARTINDENT 564 if (do_si) /* need first char after new line break */ 565 { 566 p = skipwhite(p_extra); 567 first_char = *p; 568 } 569 #endif 570 #ifdef FEAT_COMMENTS 571 extra_len = (int)STRLEN(p_extra); 572 #endif 573 saved_char = *p_extra; 574 *p_extra = NUL; 575 } 576 577 u_clearline(); /* cannot do "U" command when adding lines */ 578 #ifdef FEAT_SMARTINDENT 579 did_si = FALSE; 580 #endif 581 ai_col = 0; 582 583 /* 584 * If we just did an auto-indent, then we didn't type anything on 585 * the prior line, and it should be truncated. Do this even if 'ai' is not 586 * set because automatically inserting a comment leader also sets did_ai. 587 */ 588 if (dir == FORWARD && did_ai) 589 trunc_line = TRUE; 590 591 /* 592 * If 'autoindent' and/or 'smartindent' is set, try to figure out what 593 * indent to use for the new line. 594 */ 595 if (curbuf->b_p_ai 596 #ifdef FEAT_SMARTINDENT 597 || do_si 598 #endif 599 ) 600 { 601 /* 602 * count white space on current line 603 */ 604 newindent = get_indent_str(saved_line, (int)curbuf->b_p_ts); 605 if (newindent == 0) 606 newindent = old_indent; /* for ^^D command in insert mode */ 607 608 #ifdef FEAT_SMARTINDENT 609 /* 610 * Do smart indenting. 611 * In insert/replace mode (only when dir == FORWARD) 612 * we may move some text to the next line. If it starts with '{' 613 * don't add an indent. Fixes inserting a NL before '{' in line 614 * "if (condition) {" 615 */ 616 if (!trunc_line && do_si && *saved_line != NUL 617 && (p_extra == NULL || first_char != '{')) 618 { 619 char_u *ptr; 620 char_u last_char; 621 622 old_cursor = curwin->w_cursor; 623 ptr = saved_line; 624 # ifdef FEAT_COMMENTS 625 if (flags & OPENLINE_DO_COM) 626 lead_len = get_leader_len(ptr, NULL, FALSE); 627 else 628 lead_len = 0; 629 # endif 630 if (dir == FORWARD) 631 { 632 /* 633 * Skip preprocessor directives, unless they are 634 * recognised as comments. 635 */ 636 if ( 637 # ifdef FEAT_COMMENTS 638 lead_len == 0 && 639 # endif 640 ptr[0] == '#') 641 { 642 while (ptr[0] == '#' && curwin->w_cursor.lnum > 1) 643 ptr = ml_get(--curwin->w_cursor.lnum); 644 newindent = get_indent(); 645 } 646 # ifdef FEAT_COMMENTS 647 if (flags & OPENLINE_DO_COM) 648 lead_len = get_leader_len(ptr, NULL, FALSE); 649 else 650 lead_len = 0; 651 if (lead_len > 0) 652 { 653 /* 654 * This case gets the following right: 655 * \* 656 * * A comment (read '\' as '/'). 657 * *\ 658 * #define IN_THE_WAY 659 * This should line up here; 660 */ 661 p = skipwhite(ptr); 662 if (p[0] == '/' && p[1] == '*') 663 p++; 664 if (p[0] == '*') 665 { 666 for (p++; *p; p++) 667 { 668 if (p[0] == '/' && p[-1] == '*') 669 { 670 /* 671 * End of C comment, indent should line up 672 * with the line containing the start of 673 * the comment 674 */ 675 curwin->w_cursor.col = (colnr_T)(p - ptr); 676 if ((pos = findmatch(NULL, NUL)) != NULL) 677 { 678 curwin->w_cursor.lnum = pos->lnum; 679 newindent = get_indent(); 680 } 681 } 682 } 683 } 684 } 685 else /* Not a comment line */ 686 # endif 687 { 688 /* Find last non-blank in line */ 689 p = ptr + STRLEN(ptr) - 1; 690 while (p > ptr && vim_iswhite(*p)) 691 --p; 692 last_char = *p; 693 694 /* 695 * find the character just before the '{' or ';' 696 */ 697 if (last_char == '{' || last_char == ';') 698 { 699 if (p > ptr) 700 --p; 701 while (p > ptr && vim_iswhite(*p)) 702 --p; 703 } 704 /* 705 * Try to catch lines that are split over multiple 706 * lines. eg: 707 * if (condition && 708 * condition) { 709 * Should line up here! 710 * } 711 */ 712 if (*p == ')') 713 { 714 curwin->w_cursor.col = (colnr_T)(p - ptr); 715 if ((pos = findmatch(NULL, '(')) != NULL) 716 { 717 curwin->w_cursor.lnum = pos->lnum; 718 newindent = get_indent(); 719 ptr = ml_get_curline(); 720 } 721 } 722 /* 723 * If last character is '{' do indent, without 724 * checking for "if" and the like. 725 */ 726 if (last_char == '{') 727 { 728 did_si = TRUE; /* do indent */ 729 no_si = TRUE; /* don't delete it when '{' typed */ 730 } 731 /* 732 * Look for "if" and the like, use 'cinwords'. 733 * Don't do this if the previous line ended in ';' or 734 * '}'. 735 */ 736 else if (last_char != ';' && last_char != '}' 737 && cin_is_cinword(ptr)) 738 did_si = TRUE; 739 } 740 } 741 else /* dir == BACKWARD */ 742 { 743 /* 744 * Skip preprocessor directives, unless they are 745 * recognised as comments. 746 */ 747 if ( 748 # ifdef FEAT_COMMENTS 749 lead_len == 0 && 750 # endif 751 ptr[0] == '#') 752 { 753 int was_backslashed = FALSE; 754 755 while ((ptr[0] == '#' || was_backslashed) && 756 curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) 757 { 758 if (*ptr && ptr[STRLEN(ptr) - 1] == '\\') 759 was_backslashed = TRUE; 760 else 761 was_backslashed = FALSE; 762 ptr = ml_get(++curwin->w_cursor.lnum); 763 } 764 if (was_backslashed) 765 newindent = 0; /* Got to end of file */ 766 else 767 newindent = get_indent(); 768 } 769 p = skipwhite(ptr); 770 if (*p == '}') /* if line starts with '}': do indent */ 771 did_si = TRUE; 772 else /* can delete indent when '{' typed */ 773 can_si_back = TRUE; 774 } 775 curwin->w_cursor = old_cursor; 776 } 777 if (do_si) 778 can_si = TRUE; 779 #endif /* FEAT_SMARTINDENT */ 780 781 did_ai = TRUE; 782 } 783 784 #ifdef FEAT_COMMENTS 785 /* 786 * Find out if the current line starts with a comment leader. 787 * This may then be inserted in front of the new line. 788 */ 789 end_comment_pending = NUL; 790 if (flags & OPENLINE_DO_COM) 791 lead_len = get_leader_len(saved_line, &lead_flags, dir == BACKWARD); 792 else 793 lead_len = 0; 794 if (lead_len > 0) 795 { 796 char_u *lead_repl = NULL; /* replaces comment leader */ 797 int lead_repl_len = 0; /* length of *lead_repl */ 798 char_u lead_middle[COM_MAX_LEN]; /* middle-comment string */ 799 char_u lead_end[COM_MAX_LEN]; /* end-comment string */ 800 char_u *comment_end = NULL; /* where lead_end has been found */ 801 int extra_space = FALSE; /* append extra space */ 802 int current_flag; 803 int require_blank = FALSE; /* requires blank after middle */ 804 char_u *p2; 805 806 /* 807 * If the comment leader has the start, middle or end flag, it may not 808 * be used or may be replaced with the middle leader. 809 */ 810 for (p = lead_flags; *p && *p != ':'; ++p) 811 { 812 if (*p == COM_BLANK) 813 { 814 require_blank = TRUE; 815 continue; 816 } 817 if (*p == COM_START || *p == COM_MIDDLE) 818 { 819 current_flag = *p; 820 if (*p == COM_START) 821 { 822 /* 823 * Doing "O" on a start of comment does not insert leader. 824 */ 825 if (dir == BACKWARD) 826 { 827 lead_len = 0; 828 break; 829 } 830 831 /* find start of middle part */ 832 (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ","); 833 require_blank = FALSE; 834 } 835 836 /* 837 * Isolate the strings of the middle and end leader. 838 */ 839 while (*p && p[-1] != ':') /* find end of middle flags */ 840 { 841 if (*p == COM_BLANK) 842 require_blank = TRUE; 843 ++p; 844 } 845 (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ","); 846 847 while (*p && p[-1] != ':') /* find end of end flags */ 848 { 849 /* Check whether we allow automatic ending of comments */ 850 if (*p == COM_AUTO_END) 851 end_comment_pending = -1; /* means we want to set it */ 852 ++p; 853 } 854 n = copy_option_part(&p, lead_end, COM_MAX_LEN, ","); 855 856 if (end_comment_pending == -1) /* we can set it now */ 857 end_comment_pending = lead_end[n - 1]; 858 859 /* 860 * If the end of the comment is in the same line, don't use 861 * the comment leader. 862 */ 863 if (dir == FORWARD) 864 { 865 for (p = saved_line + lead_len; *p; ++p) 866 if (STRNCMP(p, lead_end, n) == 0) 867 { 868 comment_end = p; 869 lead_len = 0; 870 break; 871 } 872 } 873 874 /* 875 * Doing "o" on a start of comment inserts the middle leader. 876 */ 877 if (lead_len > 0) 878 { 879 if (current_flag == COM_START) 880 { 881 lead_repl = lead_middle; 882 lead_repl_len = (int)STRLEN(lead_middle); 883 } 884 885 /* 886 * If we have hit RETURN immediately after the start 887 * comment leader, then put a space after the middle 888 * comment leader on the next line. 889 */ 890 if (!vim_iswhite(saved_line[lead_len - 1]) 891 && ((p_extra != NULL 892 && (int)curwin->w_cursor.col == lead_len) 893 || (p_extra == NULL 894 && saved_line[lead_len] == NUL) 895 || require_blank)) 896 extra_space = TRUE; 897 } 898 break; 899 } 900 if (*p == COM_END) 901 { 902 /* 903 * Doing "o" on the end of a comment does not insert leader. 904 * Remember where the end is, might want to use it to find the 905 * start (for C-comments). 906 */ 907 if (dir == FORWARD) 908 { 909 comment_end = skipwhite(saved_line); 910 lead_len = 0; 911 break; 912 } 913 914 /* 915 * Doing "O" on the end of a comment inserts the middle leader. 916 * Find the string for the middle leader, searching backwards. 917 */ 918 while (p > curbuf->b_p_com && *p != ',') 919 --p; 920 for (lead_repl = p; lead_repl > curbuf->b_p_com 921 && lead_repl[-1] != ':'; --lead_repl) 922 ; 923 lead_repl_len = (int)(p - lead_repl); 924 925 /* We can probably always add an extra space when doing "O" on 926 * the comment-end */ 927 extra_space = TRUE; 928 929 /* Check whether we allow automatic ending of comments */ 930 for (p2 = p; *p2 && *p2 != ':'; p2++) 931 { 932 if (*p2 == COM_AUTO_END) 933 end_comment_pending = -1; /* means we want to set it */ 934 } 935 if (end_comment_pending == -1) 936 { 937 /* Find last character in end-comment string */ 938 while (*p2 && *p2 != ',') 939 p2++; 940 end_comment_pending = p2[-1]; 941 } 942 break; 943 } 944 if (*p == COM_FIRST) 945 { 946 /* 947 * Comment leader for first line only: Don't repeat leader 948 * when using "O", blank out leader when using "o". 949 */ 950 if (dir == BACKWARD) 951 lead_len = 0; 952 else 953 { 954 lead_repl = (char_u *)""; 955 lead_repl_len = 0; 956 } 957 break; 958 } 959 } 960 if (lead_len) 961 { 962 /* allocate buffer (may concatenate p_exta later) */ 963 leader = alloc(lead_len + lead_repl_len + extra_space + 964 extra_len + 1); 965 allocated = leader; /* remember to free it later */ 966 967 if (leader == NULL) 968 lead_len = 0; 969 else 970 { 971 STRNCPY(leader, saved_line, lead_len); 972 leader[lead_len] = NUL; 973 974 /* 975 * Replace leader with lead_repl, right or left adjusted 976 */ 977 if (lead_repl != NULL) 978 { 979 int c = 0; 980 int off = 0; 981 982 for (p = lead_flags; *p && *p != ':'; ++p) 983 { 984 if (*p == COM_RIGHT || *p == COM_LEFT) 985 c = *p; 986 else if (VIM_ISDIGIT(*p) || *p == '-') 987 off = getdigits(&p); 988 } 989 if (c == COM_RIGHT) /* right adjusted leader */ 990 { 991 /* find last non-white in the leader to line up with */ 992 for (p = leader + lead_len - 1; p > leader 993 && vim_iswhite(*p); --p) 994 ; 995 ++p; 996 997 #ifdef FEAT_MBYTE 998 /* Compute the length of the replaced characters in 999 * screen characters, not bytes. */ 1000 { 1001 int repl_size = vim_strnsize(lead_repl, 1002 lead_repl_len); 1003 int old_size = 0; 1004 char_u *endp = p; 1005 int l; 1006 1007 while (old_size < repl_size && p > leader) 1008 { 1009 --p; 1010 p -= mb_head_off(leader, p); 1011 old_size += ptr2cells(p); 1012 } 1013 l = lead_repl_len - (endp - p); 1014 if (l != 0) 1015 mch_memmove(endp + l, endp, 1016 (size_t)((leader + lead_len) - endp)); 1017 lead_len += l; 1018 } 1019 #else 1020 if (p < leader + lead_repl_len) 1021 p = leader; 1022 else 1023 p -= lead_repl_len; 1024 #endif 1025 mch_memmove(p, lead_repl, (size_t)lead_repl_len); 1026 if (p + lead_repl_len > leader + lead_len) 1027 p[lead_repl_len] = NUL; 1028 1029 /* blank-out any other chars from the old leader. */ 1030 while (--p >= leader) 1031 { 1032 #ifdef FEAT_MBYTE 1033 int l = mb_head_off(leader, p); 1034 1035 if (l > 1) 1036 { 1037 p -= l; 1038 if (ptr2cells(p) > 1) 1039 { 1040 p[1] = ' '; 1041 --l; 1042 } 1043 mch_memmove(p + 1, p + l + 1, 1044 (size_t)((leader + lead_len) - (p + l + 1))); 1045 lead_len -= l; 1046 *p = ' '; 1047 } 1048 else 1049 #endif 1050 if (!vim_iswhite(*p)) 1051 *p = ' '; 1052 } 1053 } 1054 else /* left adjusted leader */ 1055 { 1056 p = skipwhite(leader); 1057 #ifdef FEAT_MBYTE 1058 /* Compute the length of the replaced characters in 1059 * screen characters, not bytes. Move the part that is 1060 * not to be overwritten. */ 1061 { 1062 int repl_size = vim_strnsize(lead_repl, 1063 lead_repl_len); 1064 int i; 1065 int l; 1066 1067 for (i = 0; p[i] != NUL && i < lead_len; i += l) 1068 { 1069 l = mb_ptr2len_check(p + i); 1070 if (vim_strnsize(p, i + l) > repl_size) 1071 break; 1072 } 1073 if (i != lead_repl_len) 1074 { 1075 mch_memmove(p + lead_repl_len, p + i, 1076 (size_t)(lead_len - i - (leader - p))); 1077 lead_len += lead_repl_len - i; 1078 } 1079 } 1080 #endif 1081 mch_memmove(p, lead_repl, (size_t)lead_repl_len); 1082 1083 /* Replace any remaining non-white chars in the old 1084 * leader by spaces. Keep Tabs, the indent must 1085 * remain the same. */ 1086 for (p += lead_repl_len; p < leader + lead_len; ++p) 1087 if (!vim_iswhite(*p)) 1088 { 1089 /* Don't put a space before a TAB. */ 1090 if (p + 1 < leader + lead_len && p[1] == TAB) 1091 { 1092 --lead_len; 1093 mch_memmove(p, p + 1, 1094 (leader + lead_len) - p); 1095 } 1096 else 1097 { 1098 #ifdef FEAT_MBYTE 1099 int l = mb_ptr2len_check(p); 1100 1101 if (l > 1) 1102 { 1103 if (ptr2cells(p) > 1) 1104 { 1105 /* Replace a double-wide char with 1106 * two spaces */ 1107 --l; 1108 *p++ = ' '; 1109 } 1110 mch_memmove(p + 1, p + l, 1111 (leader + lead_len) - p); 1112 lead_len -= l - 1; 1113 } 1114 #endif 1115 *p = ' '; 1116 } 1117 } 1118 *p = NUL; 1119 } 1120 1121 /* Recompute the indent, it may have changed. */ 1122 if (curbuf->b_p_ai 1123 #ifdef FEAT_SMARTINDENT 1124 || do_si 1125 #endif 1126 ) 1127 newindent = get_indent_str(leader, (int)curbuf->b_p_ts); 1128 1129 /* Add the indent offset */ 1130 if (newindent + off < 0) 1131 { 1132 off = -newindent; 1133 newindent = 0; 1134 } 1135 else 1136 newindent += off; 1137 1138 /* Correct trailing spaces for the shift, so that 1139 * alignment remains equal. */ 1140 while (off > 0 && lead_len > 0 1141 && leader[lead_len - 1] == ' ') 1142 { 1143 /* Don't do it when there is a tab before the space */ 1144 if (vim_strchr(skipwhite(leader), '\t') != NULL) 1145 break; 1146 --lead_len; 1147 --off; 1148 } 1149 1150 /* If the leader ends in white space, don't add an 1151 * extra space */ 1152 if (lead_len > 0 && vim_iswhite(leader[lead_len - 1])) 1153 extra_space = FALSE; 1154 leader[lead_len] = NUL; 1155 } 1156 1157 if (extra_space) 1158 { 1159 leader[lead_len++] = ' '; 1160 leader[lead_len] = NUL; 1161 } 1162 1163 newcol = lead_len; 1164 1165 /* 1166 * if a new indent will be set below, remove the indent that 1167 * is in the comment leader 1168 */ 1169 if (newindent 1170 #ifdef FEAT_SMARTINDENT 1171 || did_si 1172 #endif 1173 ) 1174 { 1175 while (lead_len && vim_iswhite(*leader)) 1176 { 1177 --lead_len; 1178 --newcol; 1179 ++leader; 1180 } 1181 } 1182 1183 } 1184 #ifdef FEAT_SMARTINDENT 1185 did_si = can_si = FALSE; 1186 #endif 1187 } 1188 else if (comment_end != NULL) 1189 { 1190 /* 1191 * We have finished a comment, so we don't use the leader. 1192 * If this was a C-comment and 'ai' or 'si' is set do a normal 1193 * indent to align with the line containing the start of the 1194 * comment. 1195 */ 1196 if (comment_end[0] == '*' && comment_end[1] == '/' && 1197 (curbuf->b_p_ai 1198 #ifdef FEAT_SMARTINDENT 1199 || do_si 1200 #endif 1201 )) 1202 { 1203 old_cursor = curwin->w_cursor; 1204 curwin->w_cursor.col = (colnr_T)(comment_end - saved_line); 1205 if ((pos = findmatch(NULL, NUL)) != NULL) 1206 { 1207 curwin->w_cursor.lnum = pos->lnum; 1208 newindent = get_indent(); 1209 } 1210 curwin->w_cursor = old_cursor; 1211 } 1212 } 1213 } 1214 #endif 1215 1216 /* (State == INSERT || State == REPLACE), only when dir == FORWARD */ 1217 if (p_extra != NULL) 1218 { 1219 *p_extra = saved_char; /* restore char that NUL replaced */ 1220 1221 /* 1222 * When 'ai' set or "flags" has OPENLINE_DELSPACES, skip to the first 1223 * non-blank. 1224 * 1225 * When in REPLACE mode, put the deleted blanks on the replace stack, 1226 * preceded by a NUL, so they can be put back when a BS is entered. 1227 */ 1228 if (REPLACE_NORMAL(State)) 1229 replace_push(NUL); /* end of extra blanks */ 1230 if (curbuf->b_p_ai || (flags & OPENLINE_DELSPACES)) 1231 { 1232 while ((*p_extra == ' ' || *p_extra == '\t') 1233 #ifdef FEAT_MBYTE 1234 && (!enc_utf8 1235 || !utf_iscomposing(utf_ptr2char(p_extra + 1))) 1236 #endif 1237 ) 1238 { 1239 if (REPLACE_NORMAL(State)) 1240 replace_push(*p_extra); 1241 ++p_extra; 1242 ++less_cols_off; 1243 } 1244 } 1245 if (*p_extra != NUL) 1246 did_ai = FALSE; /* append some text, don't truncate now */ 1247 1248 /* columns for marks adjusted for removed columns */ 1249 less_cols = (int)(p_extra - saved_line); 1250 } 1251 1252 if (p_extra == NULL) 1253 p_extra = (char_u *)""; /* append empty line */ 1254 1255 #ifdef FEAT_COMMENTS 1256 /* concatenate leader and p_extra, if there is a leader */ 1257 if (lead_len) 1258 { 1259 STRCAT(leader, p_extra); 1260 p_extra = leader; 1261 did_ai = TRUE; /* So truncating blanks works with comments */ 1262 less_cols -= lead_len; 1263 } 1264 else 1265 end_comment_pending = NUL; /* turns out there was no leader */ 1266 #endif 1267 1268 old_cursor = curwin->w_cursor; 1269 if (dir == BACKWARD) 1270 --curwin->w_cursor.lnum; 1271 #ifdef FEAT_VREPLACE 1272 if (!(State & VREPLACE_FLAG) || old_cursor.lnum >= orig_line_count) 1273 #endif 1274 { 1275 if (ml_append(curwin->w_cursor.lnum, p_extra, (colnr_T)0, FALSE) 1276 == FAIL) 1277 goto theend; 1278 /* Postpone calling changed_lines(), because it would mess up folding 1279 * with markers. */ 1280 mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L); 1281 did_append = TRUE; 1282 } 1283 #ifdef FEAT_VREPLACE 1284 else 1285 { 1286 /* 1287 * In VREPLACE mode we are starting to replace the next line. 1288 */ 1289 curwin->w_cursor.lnum++; 1290 if (curwin->w_cursor.lnum >= Insstart.lnum + vr_lines_changed) 1291 { 1292 /* In case we NL to a new line, BS to the previous one, and NL 1293 * again, we don't want to save the new line for undo twice. 1294 */ 1295 (void)u_save_cursor(); /* errors are ignored! */ 1296 vr_lines_changed++; 1297 } 1298 ml_replace(curwin->w_cursor.lnum, p_extra, TRUE); 1299 changed_bytes(curwin->w_cursor.lnum, 0); 1300 curwin->w_cursor.lnum--; 1301 did_append = FALSE; 1302 } 1303 #endif 1304 1305 if (newindent 1306 #ifdef FEAT_SMARTINDENT 1307 || did_si 1308 #endif 1309 ) 1310 { 1311 ++curwin->w_cursor.lnum; 1312 #ifdef FEAT_SMARTINDENT 1313 if (did_si) 1314 { 1315 if (p_sr) 1316 newindent -= newindent % (int)curbuf->b_p_sw; 1317 newindent += (int)curbuf->b_p_sw; 1318 } 1319 #endif 1320 /* Copy the indent only if expand tab is disabled */ 1321 if (curbuf->b_p_ci && !curbuf->b_p_et) 1322 { 1323 (void)copy_indent(newindent, saved_line); 1324 1325 /* 1326 * Set the 'preserveindent' option so that any further screwing 1327 * with the line doesn't entirely destroy our efforts to preserve 1328 * it. It gets restored at the function end. 1329 */ 1330 curbuf->b_p_pi = TRUE; 1331 } 1332 else 1333 (void)set_indent(newindent, SIN_INSERT); 1334 less_cols -= curwin->w_cursor.col; 1335 1336 ai_col = curwin->w_cursor.col; 1337 1338 /* 1339 * In REPLACE mode, for each character in the new indent, there must 1340 * be a NUL on the replace stack, for when it is deleted with BS 1341 */ 1342 if (REPLACE_NORMAL(State)) 1343 for (n = 0; n < (int)curwin->w_cursor.col; ++n) 1344 replace_push(NUL); 1345 newcol += curwin->w_cursor.col; 1346 #ifdef FEAT_SMARTINDENT 1347 if (no_si) 1348 did_si = FALSE; 1349 #endif 1350 } 1351 1352 #ifdef FEAT_COMMENTS 1353 /* 1354 * In REPLACE mode, for each character in the extra leader, there must be 1355 * a NUL on the replace stack, for when it is deleted with BS. 1356 */ 1357 if (REPLACE_NORMAL(State)) 1358 while (lead_len-- > 0) 1359 replace_push(NUL); 1360 #endif 1361 1362 curwin->w_cursor = old_cursor; 1363 1364 if (dir == FORWARD) 1365 { 1366 if (trunc_line || (State & INSERT)) 1367 { 1368 /* truncate current line at cursor */ 1369 saved_line[curwin->w_cursor.col] = NUL; 1370 /* Remove trailing white space, unless OPENLINE_KEEPTRAIL used. */ 1371 if (trunc_line && !(flags & OPENLINE_KEEPTRAIL)) 1372 truncate_spaces(saved_line); 1373 ml_replace(curwin->w_cursor.lnum, saved_line, FALSE); 1374 saved_line = NULL; 1375 if (did_append) 1376 { 1377 changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col, 1378 curwin->w_cursor.lnum + 1, 1L); 1379 did_append = FALSE; 1380 1381 /* Move marks after the line break to the new line. */ 1382 if (flags & OPENLINE_MARKFIX) 1383 mark_col_adjust(curwin->w_cursor.lnum, 1384 curwin->w_cursor.col + less_cols_off, 1385 1L, (long)-less_cols); 1386 } 1387 else 1388 changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); 1389 } 1390 1391 /* 1392 * Put the cursor on the new line. Careful: the scrollup() above may 1393 * have moved w_cursor, we must use old_cursor. 1394 */ 1395 curwin->w_cursor.lnum = old_cursor.lnum + 1; 1396 } 1397 if (did_append) 1398 changed_lines(curwin->w_cursor.lnum, 0, curwin->w_cursor.lnum, 1L); 1399 1400 curwin->w_cursor.col = newcol; 1401 #ifdef FEAT_VIRTUALEDIT 1402 curwin->w_cursor.coladd = 0; 1403 #endif 1404 1405 #if defined(FEAT_VREPLACE) && (defined(FEAT_LISP) || defined(FEAT_CINDENT)) 1406 /* 1407 * In VREPLACE mode, we are handling the replace stack ourselves, so stop 1408 * fixthisline() from doing it (via change_indent()) by telling it we're in 1409 * normal INSERT mode. 1410 */ 1411 if (State & VREPLACE_FLAG) 1412 { 1413 vreplace_mode = State; /* So we know to put things right later */ 1414 State = INSERT; 1415 } 1416 else 1417 vreplace_mode = 0; 1418 #endif 1419 #ifdef FEAT_LISP 1420 /* 1421 * May do lisp indenting. 1422 */ 1423 if (!p_paste 1424 # ifdef FEAT_COMMENTS 1425 && leader == NULL 1426 # endif 1427 && curbuf->b_p_lisp 1428 && curbuf->b_p_ai) 1429 { 1430 fixthisline(get_lisp_indent); 1431 p = ml_get_curline(); 1432 ai_col = (colnr_T)(skipwhite(p) - p); 1433 } 1434 #endif 1435 #ifdef FEAT_CINDENT 1436 /* 1437 * May do indenting after opening a new line. 1438 */ 1439 if (!p_paste 1440 && (curbuf->b_p_cin 1441 # ifdef FEAT_EVAL 1442 || *curbuf->b_p_inde != NUL 1443 # endif 1444 ) 1445 && in_cinkeys(dir == FORWARD 1446 ? KEY_OPEN_FORW 1447 : KEY_OPEN_BACK, ' ', linewhite(curwin->w_cursor.lnum))) 1448 { 1449 do_c_expr_indent(); 1450 p = ml_get_curline(); 1451 ai_col = (colnr_T)(skipwhite(p) - p); 1452 } 1453 #endif 1454 #if defined(FEAT_VREPLACE) && (defined(FEAT_LISP) || defined(FEAT_CINDENT)) 1455 if (vreplace_mode != 0) 1456 State = vreplace_mode; 1457 #endif 1458 1459 #ifdef FEAT_VREPLACE 1460 /* 1461 * Finally, VREPLACE gets the stuff on the new line, then puts back the 1462 * original line, and inserts the new stuff char by char, pushing old stuff 1463 * onto the replace stack (via ins_char()). 1464 */ 1465 if (State & VREPLACE_FLAG) 1466 { 1467 /* Put new line in p_extra */ 1468 p_extra = vim_strsave(ml_get_curline()); 1469 if (p_extra == NULL) 1470 goto theend; 1471 1472 /* Put back original line */ 1473 ml_replace(curwin->w_cursor.lnum, next_line, FALSE); 1474 1475 /* Insert new stuff into line again */ 1476 curwin->w_cursor.col = 0; 1477 #ifdef FEAT_VIRTUALEDIT 1478 curwin->w_cursor.coladd = 0; 1479 #endif 1480 ins_bytes(p_extra); /* will call changed_bytes() */ 1481 vim_free(p_extra); 1482 next_line = NULL; 1483 } 1484 #endif 1485 1486 retval = TRUE; /* success! */ 1487 theend: 1488 curbuf->b_p_pi = saved_pi; 1489 vim_free(saved_line); 1490 vim_free(next_line); 1491 vim_free(allocated); 1492 return retval; 1493 } 1494 1495 #if defined(FEAT_COMMENTS) || defined(PROTO) 1496 /* 1497 * get_leader_len() returns the length of the prefix of the given string 1498 * which introduces a comment. If this string is not a comment then 0 is 1499 * returned. 1500 * When "flags" is not NULL, it is set to point to the flags of the recognized 1501 * comment leader. 1502 * "backward" must be true for the "O" command. 1503 */ 1504 int 1505 get_leader_len(line, flags, backward) 1506 char_u *line; 1507 char_u **flags; 1508 int backward; 1509 { 1510 int i, j; 1511 int got_com = FALSE; 1512 int found_one; 1513 char_u part_buf[COM_MAX_LEN]; /* buffer for one option part */ 1514 char_u *string; /* pointer to comment string */ 1515 char_u *list; 1516 1517 i = 0; 1518 while (vim_iswhite(line[i])) /* leading white space is ignored */ 1519 ++i; 1520 1521 /* 1522 * Repeat to match several nested comment strings. 1523 */ 1524 while (line[i]) 1525 { 1526 /* 1527 * scan through the 'comments' option for a match 1528 */ 1529 found_one = FALSE; 1530 for (list = curbuf->b_p_com; *list; ) 1531 { 1532 /* 1533 * Get one option part into part_buf[]. Advance list to next one. 1534 * put string at start of string. 1535 */ 1536 if (!got_com && flags != NULL) /* remember where flags started */ 1537 *flags = list; 1538 (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ","); 1539 string = vim_strchr(part_buf, ':'); 1540 if (string == NULL) /* missing ':', ignore this part */ 1541 continue; 1542 *string++ = NUL; /* isolate flags from string */ 1543 1544 /* 1545 * When already found a nested comment, only accept further 1546 * nested comments. 1547 */ 1548 if (got_com && vim_strchr(part_buf, COM_NEST) == NULL) 1549 continue; 1550 1551 /* When 'O' flag used don't use for "O" command */ 1552 if (backward && vim_strchr(part_buf, COM_NOBACK) != NULL) 1553 continue; 1554 1555 /* 1556 * Line contents and string must match. 1557 * When string starts with white space, must have some white space 1558 * (but the amount does not need to match, there might be a mix of 1559 * TABs and spaces). 1560 */ 1561 if (vim_iswhite(string[0])) 1562 { 1563 if (i == 0 || !vim_iswhite(line[i - 1])) 1564 continue; 1565 while (vim_iswhite(string[0])) 1566 ++string; 1567 } 1568 for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j) 1569 ; 1570 if (string[j] != NUL) 1571 continue; 1572 1573 /* 1574 * When 'b' flag used, there must be white space or an 1575 * end-of-line after the string in the line. 1576 */ 1577 if (vim_strchr(part_buf, COM_BLANK) != NULL 1578 && !vim_iswhite(line[i + j]) && line[i + j] != NUL) 1579 continue; 1580 1581 /* 1582 * We have found a match, stop searching. 1583 */ 1584 i += j; 1585 got_com = TRUE; 1586 found_one = TRUE; 1587 break; 1588 } 1589 1590 /* 1591 * No match found, stop scanning. 1592 */ 1593 if (!found_one) 1594 break; 1595 1596 /* 1597 * Include any trailing white space. 1598 */ 1599 while (vim_iswhite(line[i])) 1600 ++i; 1601 1602 /* 1603 * If this comment doesn't nest, stop here. 1604 */ 1605 if (vim_strchr(part_buf, COM_NEST) == NULL) 1606 break; 1607 } 1608 return (got_com ? i : 0); 1609 } 1610 #endif 1611 1612 /* 1613 * Return the number of window lines occupied by buffer line "lnum". 1614 */ 1615 int 1616 plines(lnum) 1617 linenr_T lnum; 1618 { 1619 return plines_win(curwin, lnum, TRUE); 1620 } 1621 1622 int 1623 plines_win(wp, lnum, winheight) 1624 win_T *wp; 1625 linenr_T lnum; 1626 int winheight; /* when TRUE limit to window height */ 1627 { 1628 #if defined(FEAT_DIFF) || defined(PROTO) 1629 /* Check for filler lines above this buffer line. When folded the result 1630 * is one line anyway. */ 1631 return plines_win_nofill(wp, lnum, winheight) + diff_check_fill(wp, lnum); 1632 } 1633 1634 int 1635 plines_nofill(lnum) 1636 linenr_T lnum; 1637 { 1638 return plines_win_nofill(curwin, lnum, TRUE); 1639 } 1640 1641 int 1642 plines_win_nofill(wp, lnum, winheight) 1643 win_T *wp; 1644 linenr_T lnum; 1645 int winheight; /* when TRUE limit to window height */ 1646 { 1647 #endif 1648 int lines; 1649 1650 if (!wp->w_p_wrap) 1651 return 1; 1652 1653 #ifdef FEAT_VERTSPLIT 1654 if (wp->w_width == 0) 1655 return 1; 1656 #endif 1657 1658 #ifdef FEAT_FOLDING 1659 /* A folded lines is handled just like an empty line. */ 1660 /* NOTE: Caller must handle lines that are MAYBE folded. */ 1661 if (lineFolded(wp, lnum) == TRUE) 1662 return 1; 1663 #endif 1664 1665 lines = plines_win_nofold(wp, lnum); 1666 if (winheight > 0 && lines > wp->w_height) 1667 return (int)wp->w_height; 1668 return lines; 1669 } 1670 1671 /* 1672 * Return number of window lines physical line "lnum" will occupy in window 1673 * "wp". Does not care about folding, 'wrap' or 'diff'. 1674 */ 1675 int 1676 plines_win_nofold(wp, lnum) 1677 win_T *wp; 1678 linenr_T lnum; 1679 { 1680 char_u *s; 1681 long col; 1682 int width; 1683 1684 s = ml_get_buf(wp->w_buffer, lnum, FALSE); 1685 if (*s == NUL) /* empty line */ 1686 return 1; 1687 col = win_linetabsize(wp, s, (colnr_T)MAXCOL); 1688 1689 /* 1690 * If list mode is on, then the '$' at the end of the line may take up one 1691 * extra column. 1692 */ 1693 if (wp->w_p_list && lcs_eol != NUL) 1694 col += 1; 1695 1696 /* 1697 * Add column offset for 'number' and 'foldcolumn'. 1698 */ 1699 width = W_WIDTH(wp) - win_col_off(wp); 1700 if (width <= 0) 1701 return 32000; 1702 if (col <= width) 1703 return 1; 1704 col -= width; 1705 width += win_col_off2(wp); 1706 return (col + (width - 1)) / width + 1; 1707 } 1708 1709 /* 1710 * Like plines_win(), but only reports the number of physical screen lines 1711 * used from the start of the line to the given column number. 1712 */ 1713 int 1714 plines_win_col(wp, lnum, column) 1715 win_T *wp; 1716 linenr_T lnum; 1717 long column; 1718 { 1719 long col; 1720 char_u *s; 1721 int lines = 0; 1722 int width; 1723 1724 #ifdef FEAT_DIFF 1725 /* Check for filler lines above this buffer line. When folded the result 1726 * is one line anyway. */ 1727 lines = diff_check_fill(wp, lnum); 1728 #endif 1729 1730 if (!wp->w_p_wrap) 1731 return lines + 1; 1732 1733 #ifdef FEAT_VERTSPLIT 1734 if (wp->w_width == 0) 1735 return lines + 1; 1736 #endif 1737 1738 s = ml_get_buf(wp->w_buffer, lnum, FALSE); 1739 1740 col = 0; 1741 while (*s != NUL && --column >= 0) 1742 { 1743 col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL); 1744 #ifdef FEAT_MBYTE 1745 if (has_mbyte) 1746 s += (*mb_ptr2len_check)(s); 1747 else 1748 #endif 1749 ++s; 1750 } 1751 1752 /* 1753 * If *s is a TAB, and the TAB is not displayed as ^I, and we're not in 1754 * INSERT mode, then col must be adjusted so that it represents the last 1755 * screen position of the TAB. This only fixes an error when the TAB wraps 1756 * from one screen line to the next (when 'columns' is not a multiple of 1757 * 'ts') -- webb. 1758 */ 1759 if (*s == TAB && (State & NORMAL) && (!wp->w_p_list || lcs_tab1)) 1760 col += win_lbr_chartabsize(wp, s, (colnr_T)col, NULL) - 1; 1761 1762 /* 1763 * Add column offset for 'number', 'foldcolumn', etc. 1764 */ 1765 width = W_WIDTH(wp) - win_col_off(wp); 1766 if (width > 0) 1767 { 1768 lines += 1; 1769 if (col >= width) 1770 lines += (col - width) / (width + win_col_off2(wp)); 1771 if (lines <= wp->w_height) 1772 return lines; 1773 } 1774 return (int)(wp->w_height); /* maximum length */ 1775 } 1776 1777 int 1778 plines_m_win(wp, first, last) 1779 win_T *wp; 1780 linenr_T first, last; 1781 { 1782 int count = 0; 1783 1784 while (first <= last) 1785 { 1786 #ifdef FEAT_FOLDING 1787 int x; 1788 1789 /* Check if there are any really folded lines, but also included lines 1790 * that are maybe folded. */ 1791 x = foldedCount(wp, first, NULL); 1792 if (x > 0) 1793 { 1794 ++count; /* count 1 for "+-- folded" line */ 1795 first += x; 1796 } 1797 else 1798 #endif 1799 { 1800 #ifdef FEAT_DIFF 1801 if (first == wp->w_topline) 1802 count += plines_win_nofill(wp, first, TRUE) + wp->w_topfill; 1803 else 1804 #endif 1805 count += plines_win(wp, first, TRUE); 1806 ++first; 1807 } 1808 } 1809 return (count); 1810 } 1811 1812 #if defined(FEAT_VREPLACE) || defined(FEAT_INS_EXPAND) || defined(PROTO) 1813 /* 1814 * Insert string "p" at the cursor position. Stops at a NUL byte. 1815 * Handles Replace mode and multi-byte characters. 1816 */ 1817 void 1818 ins_bytes(p) 1819 char_u *p; 1820 { 1821 ins_bytes_len(p, (int)STRLEN(p)); 1822 } 1823 #endif 1824 1825 #if defined(FEAT_VREPLACE) || defined(FEAT_INS_EXPAND) \ 1826 || defined(FEAT_COMMENTS) || defined(FEAT_MBYTE) || defined(PROTO) 1827 /* 1828 * Insert string "p" with length "len" at the cursor position. 1829 * Handles Replace mode and multi-byte characters. 1830 */ 1831 void 1832 ins_bytes_len(p, len) 1833 char_u *p; 1834 int len; 1835 { 1836 int i; 1837 # ifdef FEAT_MBYTE 1838 int n; 1839 1840 for (i = 0; i < len; i += n) 1841 { 1842 n = (*mb_ptr2len_check)(p + i); 1843 ins_char_bytes(p + i, n); 1844 } 1845 # else 1846 for (i = 0; i < len; ++i) 1847 ins_char(p[i]); 1848 # endif 1849 } 1850 #endif 1851 1852 /* 1853 * Insert or replace a single character at the cursor position. 1854 * When in REPLACE or VREPLACE mode, replace any existing character. 1855 * Caller must have prepared for undo. 1856 * For multi-byte characters we get the whole character, the caller must 1857 * convert bytes to a character. 1858 */ 1859 void 1860 ins_char(c) 1861 int c; 1862 { 1863 #if defined(FEAT_MBYTE) || defined(PROTO) 1864 char_u buf[MB_MAXBYTES]; 1865 int n; 1866 1867 n = (*mb_char2bytes)(c, buf); 1868 1869 /* When "c" is 0x100, 0x200, etc. we don't want to insert a NUL byte. 1870 * Happens for CTRL-Vu9900. */ 1871 if (buf[0] == 0) 1872 buf[0] = '\n'; 1873 1874 ins_char_bytes(buf, n); 1875 } 1876 1877 void 1878 ins_char_bytes(buf, charlen) 1879 char_u *buf; 1880 int charlen; 1881 { 1882 int c = buf[0]; 1883 int l, j; 1884 #endif 1885 int newlen; /* nr of bytes inserted */ 1886 int oldlen; /* nr of bytes deleted (0 when not replacing) */ 1887 char_u *p; 1888 char_u *newp; 1889 char_u *oldp; 1890 int linelen; /* length of old line including NUL */ 1891 colnr_T col; 1892 linenr_T lnum = curwin->w_cursor.lnum; 1893 int i; 1894 1895 #ifdef FEAT_VIRTUALEDIT 1896 /* Break tabs if needed. */ 1897 if (virtual_active() && curwin->w_cursor.coladd > 0) 1898 coladvance_force(getviscol()); 1899 #endif 1900 1901 col = curwin->w_cursor.col; 1902 oldp = ml_get(lnum); 1903 linelen = (int)STRLEN(oldp) + 1; 1904 1905 /* The lengths default to the values for when not replacing. */ 1906 oldlen = 0; 1907 #ifdef FEAT_MBYTE 1908 newlen = charlen; 1909 #else 1910 newlen = 1; 1911 #endif 1912 1913 if (State & REPLACE_FLAG) 1914 { 1915 #ifdef FEAT_VREPLACE 1916 if (State & VREPLACE_FLAG) 1917 { 1918 colnr_T new_vcol = 0; /* init for GCC */ 1919 colnr_T vcol; 1920 int old_list; 1921 #ifndef FEAT_MBYTE 1922 char_u buf[2]; 1923 #endif 1924 1925 /* 1926 * Disable 'list' temporarily, unless 'cpo' contains the 'L' flag. 1927 * Returns the old value of list, so when finished, 1928 * curwin->w_p_list should be set back to this. 1929 */ 1930 old_list = curwin->w_p_list; 1931 if (old_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL) 1932 curwin->w_p_list = FALSE; 1933 1934 /* 1935 * In virtual replace mode each character may replace one or more 1936 * characters (zero if it's a TAB). Count the number of bytes to 1937 * be deleted to make room for the new character, counting screen 1938 * cells. May result in adding spaces to fill a gap. 1939 */ 1940 getvcol(curwin, &curwin->w_cursor, NULL, &vcol, NULL); 1941 #ifndef FEAT_MBYTE 1942 buf[0] = c; 1943 buf[1] = NUL; 1944 #endif 1945 new_vcol = vcol + chartabsize(buf, vcol); 1946 while (oldp[col + oldlen] != NUL && vcol < new_vcol) 1947 { 1948 vcol += chartabsize(oldp + col + oldlen, vcol); 1949 /* Don't need to remove a TAB that takes us to the right 1950 * position. */ 1951 if (vcol > new_vcol && oldp[col + oldlen] == TAB) 1952 break; 1953 #ifdef FEAT_MBYTE 1954 oldlen += (*mb_ptr2len_check)(oldp + col + oldlen); 1955 #else 1956 ++oldlen; 1957 #endif 1958 /* Deleted a bit too much, insert spaces. */ 1959 if (vcol > new_vcol) 1960 newlen += vcol - new_vcol; 1961 } 1962 curwin->w_p_list = old_list; 1963 } 1964 else 1965 #endif 1966 if (oldp[col] != NUL) 1967 { 1968 /* normal replace */ 1969 #ifdef FEAT_MBYTE 1970 oldlen = (*mb_ptr2len_check)(oldp + col); 1971 #else 1972 oldlen = 1; 1973 #endif 1974 } 1975 1976 1977 /* Push the replaced bytes onto the replace stack, so that they can be 1978 * put back when BS is used. The bytes of a multi-byte character are 1979 * done the other way around, so that the first byte is popped off 1980 * first (it tells the byte length of the character). */ 1981 replace_push(NUL); 1982 for (i = 0; i < oldlen; ++i) 1983 { 1984 #ifdef FEAT_MBYTE 1985 l = (*mb_ptr2len_check)(oldp + col + i) - 1; 1986 for (j = l; j >= 0; --j) 1987 replace_push(oldp[col + i + j]); 1988 i += l; 1989 #else 1990 replace_push(oldp[col + i]); 1991 #endif 1992 } 1993 } 1994 1995 newp = alloc_check((unsigned)(linelen + newlen - oldlen)); 1996 if (newp == NULL) 1997 return; 1998 1999 /* Copy bytes before the cursor. */ 2000 if (col > 0) 2001 mch_memmove(newp, oldp, (size_t)col); 2002 2003 /* Copy bytes after the changed character(s). */ 2004 p = newp + col; 2005 mch_memmove(p + newlen, oldp + col + oldlen, 2006 (size_t)(linelen - col - oldlen)); 2007 2008 /* Insert or overwrite the new character. */ 2009 #ifdef FEAT_MBYTE 2010 mch_memmove(p, buf, charlen); 2011 i = charlen; 2012 #else 2013 *p = c; 2014 i = 1; 2015 #endif 2016 2017 /* Fill with spaces when necessary. */ 2018 while (i < newlen) 2019 p[i++] = ' '; 2020 2021 /* Replace the line in the buffer. */ 2022 ml_replace(lnum, newp, FALSE); 2023 2024 /* mark the buffer as changed and prepare for displaying */ 2025 changed_bytes(lnum, col); 2026 2027 /* 2028 * If we're in Insert or Replace mode and 'showmatch' is set, then briefly 2029 * show the match for right parens and braces. 2030 */ 2031 if (p_sm && (State & INSERT) 2032 && msg_silent == 0 2033 #ifdef FEAT_MBYTE 2034 && charlen == 1 2035 #endif 2036 ) 2037 showmatch(c); 2038 2039 #ifdef FEAT_RIGHTLEFT 2040 if (!p_ri || (State & REPLACE_FLAG)) 2041 #endif 2042 { 2043 /* Normal insert: move cursor right */ 2044 #ifdef FEAT_MBYTE 2045 curwin->w_cursor.col += charlen; 2046 #else 2047 ++curwin->w_cursor.col; 2048 #endif 2049 } 2050 /* 2051 * TODO: should try to update w_row here, to avoid recomputing it later. 2052 */ 2053 } 2054 2055 /* 2056 * Insert a string at the cursor position. 2057 * Note: Does NOT handle Replace mode. 2058 * Caller must have prepared for undo. 2059 */ 2060 void 2061 ins_str(s) 2062 char_u *s; 2063 { 2064 char_u *oldp, *newp; 2065 int newlen = (int)STRLEN(s); 2066 int oldlen; 2067 colnr_T col; 2068 linenr_T lnum = curwin->w_cursor.lnum; 2069 2070 #ifdef FEAT_VIRTUALEDIT 2071 if (virtual_active() && curwin->w_cursor.coladd > 0) 2072 coladvance_force(getviscol()); 2073 #endif 2074 2075 col = curwin->w_cursor.col; 2076 oldp = ml_get(lnum); 2077 oldlen = (int)STRLEN(oldp); 2078 2079 newp = alloc_check((unsigned)(oldlen + newlen + 1)); 2080 if (newp == NULL) 2081 return; 2082 if (col > 0) 2083 mch_memmove(newp, oldp, (size_t)col); 2084 mch_memmove(newp + col, s, (size_t)newlen); 2085 mch_memmove(newp + col + newlen, oldp + col, (size_t)(oldlen - col + 1)); 2086 ml_replace(lnum, newp, FALSE); 2087 changed_bytes(lnum, col); 2088 curwin->w_cursor.col += newlen; 2089 } 2090 2091 /* 2092 * Delete one character under the cursor. 2093 * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line. 2094 * Caller must have prepared for undo. 2095 * 2096 * return FAIL for failure, OK otherwise 2097 */ 2098 int 2099 del_char(fixpos) 2100 int fixpos; 2101 { 2102 #ifdef FEAT_MBYTE 2103 if (has_mbyte) 2104 { 2105 /* Make sure the cursor is at the start of a character. */ 2106 mb_adjust_cursor(); 2107 if (*ml_get_cursor() == NUL) 2108 return FAIL; 2109 return del_chars(1L, fixpos); 2110 } 2111 #endif 2112 return del_bytes(1L, fixpos); 2113 } 2114 2115 #if defined(FEAT_MBYTE) || defined(PROTO) 2116 /* 2117 * Like del_bytes(), but delete characters instead of bytes. 2118 */ 2119 int 2120 del_chars(count, fixpos) 2121 long count; 2122 int fixpos; 2123 { 2124 long bytes = 0; 2125 long i; 2126 char_u *p; 2127 int l; 2128 2129 p = ml_get_cursor(); 2130 for (i = 0; i < count && *p != NUL; ++i) 2131 { 2132 l = (*mb_ptr2len_check)(p); 2133 bytes += l; 2134 p += l; 2135 } 2136 return del_bytes(bytes, fixpos); 2137 } 2138 #endif 2139 2140 /* 2141 * Delete "count" bytes under the cursor. 2142 * If "fixpos" is TRUE, don't leave the cursor on the NUL after the line. 2143 * Caller must have prepared for undo. 2144 * 2145 * return FAIL for failure, OK otherwise 2146 */ 2147 int 2148 del_bytes(count, fixpos) 2149 long count; 2150 int fixpos; 2151 { 2152 char_u *oldp, *newp; 2153 colnr_T oldlen; 2154 linenr_T lnum = curwin->w_cursor.lnum; 2155 colnr_T col = curwin->w_cursor.col; 2156 int was_alloced; 2157 long movelen; 2158 2159 oldp = ml_get(lnum); 2160 oldlen = (int)STRLEN(oldp); 2161 2162 /* 2163 * Can't do anything when the cursor is on the NUL after the line. 2164 */ 2165 if (col >= oldlen) 2166 return FAIL; 2167 2168 #ifdef FEAT_MBYTE 2169 /* If 'delcombine' is set and deleting (less than) one character, only 2170 * delete the last combining character. */ 2171 if (p_deco && enc_utf8 && (*mb_ptr2len_check)(oldp + col) <= count) 2172 { 2173 int c1, c2; 2174 int n; 2175 2176 (void)utfc_ptr2char(oldp + col, &c1, &c2); 2177 if (c1 != NUL) 2178 { 2179 /* Find the last composing char, there can be several. */ 2180 n = col; 2181 do 2182 { 2183 col = n; 2184 count = utf_ptr2len_check(oldp + n); 2185 n += count; 2186 } while (UTF_COMPOSINGLIKE(oldp + col, oldp + n)); 2187 fixpos = 0; 2188 } 2189 } 2190 #endif 2191 2192 /* 2193 * When count is too big, reduce it. 2194 */ 2195 movelen = (long)oldlen - (long)col - count + 1; /* includes trailing NUL */ 2196 if (movelen <= 1) 2197 { 2198 /* 2199 * If we just took off the last character of a non-blank line, and 2200 * fixpos is TRUE, we don't want to end up positioned at the NUL. 2201 */ 2202 if (col > 0 && fixpos) 2203 { 2204 --curwin->w_cursor.col; 2205 #ifdef FEAT_VIRTUALEDIT 2206 curwin->w_cursor.coladd = 0; 2207 #endif 2208 #ifdef FEAT_MBYTE 2209 if (has_mbyte) 2210 curwin->w_cursor.col -= 2211 (*mb_head_off)(oldp, oldp + curwin->w_cursor.col); 2212 #endif 2213 } 2214 count = oldlen - col; 2215 movelen = 1; 2216 } 2217 2218 /* 2219 * If the old line has been allocated the deletion can be done in the 2220 * existing line. Otherwise a new line has to be allocated 2221 */ 2222 was_alloced = ml_line_alloced(); /* check if oldp was allocated */ 2223 #ifdef FEAT_NETBEANS_INTG 2224 if (was_alloced && usingNetbeans) 2225 netbeans_removed(curbuf, lnum, col, count); 2226 /* else is handled by ml_replace() */ 2227 #endif 2228 if (was_alloced) 2229 newp = oldp; /* use same allocated memory */ 2230 else 2231 { /* need to allocate a new line */ 2232 newp = alloc((unsigned)(oldlen + 1 - count)); 2233 if (newp == NULL) 2234 return FAIL; 2235 mch_memmove(newp, oldp, (size_t)col); 2236 } 2237 mch_memmove(newp + col, oldp + col + count, (size_t)movelen); 2238 if (!was_alloced) 2239 ml_replace(lnum, newp, FALSE); 2240 2241 /* mark the buffer as changed and prepare for displaying */ 2242 changed_bytes(lnum, curwin->w_cursor.col); 2243 2244 return OK; 2245 } 2246 2247 /* 2248 * Delete from cursor to end of line. 2249 * Caller must have prepared for undo. 2250 * 2251 * return FAIL for failure, OK otherwise 2252 */ 2253 int 2254 truncate_line(fixpos) 2255 int fixpos; /* if TRUE fix the cursor position when done */ 2256 { 2257 char_u *newp; 2258 linenr_T lnum = curwin->w_cursor.lnum; 2259 colnr_T col = curwin->w_cursor.col; 2260 2261 if (col == 0) 2262 newp = vim_strsave((char_u *)""); 2263 else 2264 newp = vim_strnsave(ml_get(lnum), col); 2265 2266 if (newp == NULL) 2267 return FAIL; 2268 2269 ml_replace(lnum, newp, FALSE); 2270 2271 /* mark the buffer as changed and prepare for displaying */ 2272 changed_bytes(lnum, curwin->w_cursor.col); 2273 2274 /* 2275 * If "fixpos" is TRUE we don't want to end up positioned at the NUL. 2276 */ 2277 if (fixpos && curwin->w_cursor.col > 0) 2278 --curwin->w_cursor.col; 2279 2280 return OK; 2281 } 2282 2283 /* 2284 * Delete "nlines" lines at the cursor. 2285 * Saves the lines for undo first if "undo" is TRUE. 2286 */ 2287 void 2288 del_lines(nlines, undo) 2289 long nlines; /* number of lines to delete */ 2290 int undo; /* if TRUE, prepare for undo */ 2291 { 2292 long n; 2293 2294 if (nlines <= 0) 2295 return; 2296 2297 /* save the deleted lines for undo */ 2298 if (undo && u_savedel(curwin->w_cursor.lnum, nlines) == FAIL) 2299 return; 2300 2301 for (n = 0; n < nlines; ) 2302 { 2303 if (curbuf->b_ml.ml_flags & ML_EMPTY) /* nothing to delete */ 2304 break; 2305 2306 ml_delete(curwin->w_cursor.lnum, TRUE); 2307 ++n; 2308 2309 /* If we delete the last line in the file, stop */ 2310 if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) 2311 break; 2312 } 2313 /* adjust marks, mark the buffer as changed and prepare for displaying */ 2314 deleted_lines_mark(curwin->w_cursor.lnum, n); 2315 2316 curwin->w_cursor.col = 0; 2317 check_cursor_lnum(); 2318 } 2319 2320 int 2321 gchar_pos(pos) 2322 pos_T *pos; 2323 { 2324 char_u *ptr = ml_get_pos(pos); 2325 2326 #ifdef FEAT_MBYTE 2327 if (has_mbyte) 2328 return (*mb_ptr2char)(ptr); 2329 #endif 2330 return (int)*ptr; 2331 } 2332 2333 int 2334 gchar_cursor() 2335 { 2336 #ifdef FEAT_MBYTE 2337 if (has_mbyte) 2338 return (*mb_ptr2char)(ml_get_cursor()); 2339 #endif 2340 return (int)*ml_get_cursor(); 2341 } 2342 2343 /* 2344 * Write a character at the current cursor position. 2345 * It is directly written into the block. 2346 */ 2347 void 2348 pchar_cursor(c) 2349 int c; 2350 { 2351 *(ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE) 2352 + curwin->w_cursor.col) = c; 2353 } 2354 2355 #if 0 /* not used */ 2356 /* 2357 * Put *pos at end of current buffer 2358 */ 2359 void 2360 goto_endofbuf(pos) 2361 pos_T *pos; 2362 { 2363 char_u *p; 2364 2365 pos->lnum = curbuf->b_ml.ml_line_count; 2366 pos->col = 0; 2367 p = ml_get(pos->lnum); 2368 while (*p++) 2369 ++pos->col; 2370 } 2371 #endif 2372 2373 /* 2374 * When extra == 0: Return TRUE if the cursor is before or on the first 2375 * non-blank in the line. 2376 * When extra == 1: Return TRUE if the cursor is before the first non-blank in 2377 * the line. 2378 */ 2379 int 2380 inindent(extra) 2381 int extra; 2382 { 2383 char_u *ptr; 2384 colnr_T col; 2385 2386 for (col = 0, ptr = ml_get_curline(); vim_iswhite(*ptr); ++col) 2387 ++ptr; 2388 if (col >= curwin->w_cursor.col + extra) 2389 return TRUE; 2390 else 2391 return FALSE; 2392 } 2393 2394 /* 2395 * Skip to next part of an option argument: Skip space and comma. 2396 */ 2397 char_u * 2398 skip_to_option_part(p) 2399 char_u *p; 2400 { 2401 if (*p == ',') 2402 ++p; 2403 while (*p == ' ') 2404 ++p; 2405 return p; 2406 } 2407 2408 /* 2409 * changed() is called when something in the current buffer is changed. 2410 * 2411 * Most often called through changed_bytes() and changed_lines(), which also 2412 * mark the area of the display to be redrawn. 2413 */ 2414 void 2415 changed() 2416 { 2417 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK) 2418 /* The text of the preediting area is inserted, but this doesn't 2419 * mean a change of the buffer yet. That is delayed until the 2420 * text is committed. (this means preedit becomes empty) */ 2421 if (im_is_preediting() && !xim_changed_while_preediting) 2422 return; 2423 xim_changed_while_preediting = FALSE; 2424 #endif 2425 2426 if (!curbuf->b_changed) 2427 { 2428 int save_msg_scroll = msg_scroll; 2429 2430 change_warning(0); 2431 /* Create a swap file if that is wanted. 2432 * Don't do this for "nofile" and "nowrite" buffer types. */ 2433 if (curbuf->b_may_swap 2434 #ifdef FEAT_QUICKFIX 2435 && !bt_dontwrite(curbuf) 2436 #endif 2437 ) 2438 { 2439 ml_open_file(curbuf); 2440 2441 /* The ml_open_file() can cause an ATTENTION message. 2442 * Wait two seconds, to make sure the user reads this unexpected 2443 * message. Since we could be anywhere, call wait_return() now, 2444 * and don't let the emsg() set msg_scroll. */ 2445 if (need_wait_return && emsg_silent == 0) 2446 { 2447 out_flush(); 2448 ui_delay(2000L, TRUE); 2449 wait_return(TRUE); 2450 msg_scroll = save_msg_scroll; 2451 } 2452 } 2453 curbuf->b_changed = TRUE; 2454 ml_setdirty(curbuf, TRUE); 2455 #ifdef FEAT_WINDOWS 2456 check_status(curbuf); 2457 #endif 2458 #ifdef FEAT_TITLE 2459 need_maketitle = TRUE; /* set window title later */ 2460 #endif 2461 } 2462 ++curbuf->b_changedtick; 2463 ++global_changedtick; 2464 } 2465 2466 static void changedOneline __ARGS((linenr_T lnum)); 2467 static void changed_common __ARGS((linenr_T lnum, colnr_T col, linenr_T lnume, long xtra)); 2468 2469 /* 2470 * Changed bytes within a single line for the current buffer. 2471 * - marks the windows on this buffer to be redisplayed 2472 * - marks the buffer changed by calling changed() 2473 * - invalidates cached values 2474 */ 2475 void 2476 changed_bytes(lnum, col) 2477 linenr_T lnum; 2478 colnr_T col; 2479 { 2480 changedOneline(lnum); 2481 changed_common(lnum, col, lnum + 1, 0L); 2482 } 2483 2484 static void 2485 changedOneline(lnum) 2486 linenr_T lnum; 2487 { 2488 if (curbuf->b_mod_set) 2489 { 2490 /* find the maximum area that must be redisplayed */ 2491 if (lnum < curbuf->b_mod_top) 2492 curbuf->b_mod_top = lnum; 2493 else if (lnum >= curbuf->b_mod_bot) 2494 curbuf->b_mod_bot = lnum + 1; 2495 } 2496 else 2497 { 2498 /* set the area that must be redisplayed to one line */ 2499 curbuf->b_mod_set = TRUE; 2500 curbuf->b_mod_top = lnum; 2501 curbuf->b_mod_bot = lnum + 1; 2502 curbuf->b_mod_xlines = 0; 2503 } 2504 } 2505 2506 /* 2507 * Appended "count" lines below line "lnum" in the current buffer. 2508 * Must be called AFTER the change and after mark_adjust(). 2509 * Takes care of marking the buffer to be redrawn and sets the changed flag. 2510 */ 2511 void 2512 appended_lines(lnum, count) 2513 linenr_T lnum; 2514 long count; 2515 { 2516 changed_lines(lnum + 1, 0, lnum + 1, count); 2517 } 2518 2519 /* 2520 * Like appended_lines(), but adjust marks first. 2521 */ 2522 void 2523 appended_lines_mark(lnum, count) 2524 linenr_T lnum; 2525 long count; 2526 { 2527 mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L); 2528 changed_lines(lnum + 1, 0, lnum + 1, count); 2529 } 2530 2531 /* 2532 * Deleted "count" lines at line "lnum" in the current buffer. 2533 * Must be called AFTER the change and after mark_adjust(). 2534 * Takes care of marking the buffer to be redrawn and sets the changed flag. 2535 */ 2536 void 2537 deleted_lines(lnum, count) 2538 linenr_T lnum; 2539 long count; 2540 { 2541 changed_lines(lnum, 0, lnum + count, -count); 2542 } 2543 2544 /* 2545 * Like deleted_lines(), but adjust marks first. 2546 */ 2547 void 2548 deleted_lines_mark(lnum, count) 2549 linenr_T lnum; 2550 long count; 2551 { 2552 mark_adjust(lnum, (linenr_T)(lnum + count - 1), (long)MAXLNUM, -count); 2553 changed_lines(lnum, 0, lnum + count, -count); 2554 } 2555 2556 /* 2557 * Changed lines for the current buffer. 2558 * Must be called AFTER the change and after mark_adjust(). 2559 * - mark the buffer changed by calling changed() 2560 * - mark the windows on this buffer to be redisplayed 2561 * - invalidate cached values 2562 * "lnum" is the first line that needs displaying, "lnume" the first line 2563 * below the changed lines (BEFORE the change). 2564 * When only inserting lines, "lnum" and "lnume" are equal. 2565 * Takes care of calling changed() and updating b_mod_*. 2566 */ 2567 void 2568 changed_lines(lnum, col, lnume, xtra) 2569 linenr_T lnum; /* first line with change */ 2570 colnr_T col; /* column in first line with change */ 2571 linenr_T lnume; /* line below last changed line */ 2572 long xtra; /* number of extra lines (negative when deleting) */ 2573 { 2574 if (curbuf->b_mod_set) 2575 { 2576 /* find the maximum area that must be redisplayed */ 2577 if (lnum < curbuf->b_mod_top) 2578 curbuf->b_mod_top = lnum; 2579 if (lnum < curbuf->b_mod_bot) 2580 { 2581 /* adjust old bot position for xtra lines */ 2582 curbuf->b_mod_bot += xtra; 2583 if (curbuf->b_mod_bot < lnum) 2584 curbuf->b_mod_bot = lnum; 2585 } 2586 if (lnume + xtra > curbuf->b_mod_bot) 2587 curbuf->b_mod_bot = lnume + xtra; 2588 curbuf->b_mod_xlines += xtra; 2589 } 2590 else 2591 { 2592 /* set the area that must be redisplayed */ 2593 curbuf->b_mod_set = TRUE; 2594 curbuf->b_mod_top = lnum; 2595 curbuf->b_mod_bot = lnume + xtra; 2596 curbuf->b_mod_xlines = xtra; 2597 } 2598 2599 changed_common(lnum, col, lnume, xtra); 2600 } 2601 2602 static void 2603 changed_common(lnum, col, lnume, xtra) 2604 linenr_T lnum; 2605 colnr_T col; 2606 linenr_T lnume; 2607 long xtra; 2608 { 2609 win_T *wp; 2610 int i; 2611 #ifdef FEAT_JUMPLIST 2612 int cols; 2613 pos_T *p; 2614 int add; 2615 #endif 2616 2617 /* mark the buffer as modified */ 2618 changed(); 2619 2620 /* set the '. mark */ 2621 if (!cmdmod.keepjumps) 2622 { 2623 curbuf->b_last_change.lnum = lnum; 2624 curbuf->b_last_change.col = col; 2625 2626 #ifdef FEAT_JUMPLIST 2627 /* Create a new entry if a new undo-able change was started or we 2628 * don't have an entry yet. */ 2629 if (curbuf->b_new_change || curbuf->b_changelistlen == 0) 2630 { 2631 if (curbuf->b_changelistlen == 0) 2632 add = TRUE; 2633 else 2634 { 2635 /* Don't create a new entry when the line number is the same 2636 * as the last one and the column is not too far away. Avoids 2637 * creating many entries for typing "xxxxx". */ 2638 p = &curbuf->b_changelist[curbuf->b_changelistlen - 1]; 2639 if (p->lnum != lnum) 2640 add = TRUE; 2641 else 2642 { 2643 cols = comp_textwidth(FALSE); 2644 if (cols == 0) 2645 cols = 79; 2646 add = (p->col + cols < col || col + cols < p->col); 2647 } 2648 } 2649 if (add) 2650 { 2651 /* This is the first of a new sequence of undo-able changes 2652 * and it's at some distance of the last change. Use a new 2653 * position in the changelist. */ 2654 curbuf->b_new_change = FALSE; 2655 2656 if (curbuf->b_changelistlen == JUMPLISTSIZE) 2657 { 2658 /* changelist is full: remove oldest entry */ 2659 curbuf->b_changelistlen = JUMPLISTSIZE - 1; 2660 mch_memmove(curbuf->b_changelist, curbuf->b_changelist + 1, 2661 sizeof(pos_T) * (JUMPLISTSIZE - 1)); 2662 FOR_ALL_WINDOWS(wp) 2663 { 2664 /* Correct position in changelist for other windows on 2665 * this buffer. */ 2666 if (wp->w_buffer == curbuf && wp->w_changelistidx > 0) 2667 --wp->w_changelistidx; 2668 } 2669 } 2670 FOR_ALL_WINDOWS(wp) 2671 { 2672 /* For other windows, if the position in the changelist is 2673 * at the end it stays at the end. */ 2674 if (wp->w_buffer == curbuf 2675 && wp->w_changelistidx == curbuf->b_changelistlen) 2676 ++wp->w_changelistidx; 2677 } 2678 ++curbuf->b_changelistlen; 2679 } 2680 } 2681 curbuf->b_changelist[curbuf->b_changelistlen - 1] = 2682 curbuf->b_last_change; 2683 /* The current window is always after the last change, so that "g," 2684 * takes you back to it. */ 2685 curwin->w_changelistidx = curbuf->b_changelistlen; 2686 #endif 2687 } 2688 2689 FOR_ALL_WINDOWS(wp) 2690 { 2691 if (wp->w_buffer == curbuf) 2692 { 2693 /* Mark this window to be redrawn later. */ 2694 if (wp->w_redr_type < VALID) 2695 wp->w_redr_type = VALID; 2696 2697 /* Check if a change in the buffer has invalidated the cached 2698 * values for the cursor. */ 2699 #ifdef FEAT_FOLDING 2700 /* 2701 * Update the folds for this window. Can't postpone this, because 2702 * a following operator might work on the whole fold: ">>dd". 2703 */ 2704 foldUpdate(wp, lnum, lnume + xtra - 1); 2705 2706 /* The change may cause lines above or below the change to become 2707 * included in a fold. Set lnum/lnume to the first/last line that 2708 * might be displayed differently. 2709 * Set w_cline_folded here as an efficient way to update it when 2710 * inserting lines just above a closed fold. */ 2711 i = hasFoldingWin(wp, lnum, &lnum, NULL, FALSE, NULL); 2712 if (wp->w_cursor.lnum == lnum) 2713 wp->w_cline_folded = i; 2714 i = hasFoldingWin(wp, lnume, NULL, &lnume, FALSE, NULL); 2715 if (wp->w_cursor.lnum == lnume) 2716 wp->w_cline_folded = i; 2717 2718 /* If the changed line is in a range of previously folded lines, 2719 * compare with the first line in that range. */ 2720 if (wp->w_cursor.lnum <= lnum) 2721 { 2722 i = find_wl_entry(wp, lnum); 2723 if (i >= 0 && wp->w_cursor.lnum > wp->w_lines[i].wl_lnum) 2724 changed_line_abv_curs_win(wp); 2725 } 2726 #endif 2727 2728 if (wp->w_cursor.lnum > lnum) 2729 changed_line_abv_curs_win(wp); 2730 else if (wp->w_cursor.lnum == lnum && wp->w_cursor.col >= col) 2731 changed_cline_bef_curs_win(wp); 2732 if (wp->w_botline >= lnum) 2733 { 2734 /* Assume that botline doesn't change (inserted lines make 2735 * other lines scroll down below botline). */ 2736 approximate_botline_win(wp); 2737 } 2738 2739 /* Check if any w_lines[] entries have become invalid. 2740 * For entries below the change: Correct the lnums for 2741 * inserted/deleted lines. Makes it possible to stop displaying 2742 * after the change. */ 2743 for (i = 0; i < wp->w_lines_valid; ++i) 2744 if (wp->w_lines[i].wl_valid) 2745 { 2746 if (wp->w_lines[i].wl_lnum >= lnum) 2747 { 2748 if (wp->w_lines[i].wl_lnum < lnume) 2749 { 2750 /* line included in change */ 2751 wp->w_lines[i].wl_valid = FALSE; 2752 } 2753 else if (xtra != 0) 2754 { 2755 /* line below change */ 2756 wp->w_lines[i].wl_lnum += xtra; 2757 #ifdef FEAT_FOLDING 2758 wp->w_lines[i].wl_lastlnum += xtra; 2759 #endif 2760 } 2761 } 2762 #ifdef FEAT_FOLDING 2763 else if (wp->w_lines[i].wl_lastlnum >= lnum) 2764 { 2765 /* change somewhere inside this range of folded lines, 2766 * may need to be redrawn */ 2767 wp->w_lines[i].wl_valid = FALSE; 2768 } 2769 #endif 2770 } 2771 } 2772 } 2773 2774 /* Call update_screen() later, which checks out what needs to be redrawn, 2775 * since it notices b_mod_set and then uses b_mod_*. */ 2776 if (must_redraw < VALID) 2777 must_redraw = VALID; 2778 } 2779 2780 /* 2781 * unchanged() is called when the changed flag must be reset for buffer 'buf' 2782 */ 2783 void 2784 unchanged(buf, ff) 2785 buf_T *buf; 2786 int ff; /* also reset 'fileformat' */ 2787 { 2788 if (buf->b_changed || (ff && file_ff_differs(buf))) 2789 { 2790 buf->b_changed = 0; 2791 ml_setdirty(buf, FALSE); 2792 if (ff) 2793 save_file_ff(buf); 2794 #ifdef FEAT_WINDOWS 2795 check_status(buf); 2796 #endif 2797 #ifdef FEAT_TITLE 2798 need_maketitle = TRUE; /* set window title later */ 2799 #endif 2800 } 2801 ++buf->b_changedtick; 2802 ++global_changedtick; 2803 #ifdef FEAT_NETBEANS_INTG 2804 netbeans_unmodified(buf); 2805 #endif 2806 } 2807 2808 #if defined(FEAT_WINDOWS) || defined(PROTO) 2809 /* 2810 * check_status: called when the status bars for the buffer 'buf' 2811 * need to be updated 2812 */ 2813 void 2814 check_status(buf) 2815 buf_T *buf; 2816 { 2817 win_T *wp; 2818 2819 for (wp = firstwin; wp != NULL; wp = wp->w_next) 2820 if (wp->w_buffer == buf && wp->w_status_height) 2821 { 2822 wp->w_redr_status = TRUE; 2823 if (must_redraw < VALID) 2824 must_redraw = VALID; 2825 } 2826 } 2827 #endif 2828 2829 /* 2830 * If the file is readonly, give a warning message with the first change. 2831 * Don't do this for autocommands. 2832 * Don't use emsg(), because it flushes the macro buffer. 2833 * If we have undone all changes b_changed will be FALSE, but b_did_warn 2834 * will be TRUE. 2835 */ 2836 void 2837 change_warning(col) 2838 int col; /* column for message; non-zero when in insert 2839 mode and 'showmode' is on */ 2840 { 2841 if (curbuf->b_did_warn == FALSE 2842 && curbufIsChanged() == 0 2843 #ifdef FEAT_AUTOCMD 2844 && !autocmd_busy 2845 #endif 2846 && curbuf->b_p_ro) 2847 { 2848 #ifdef FEAT_AUTOCMD 2849 apply_autocmds(EVENT_FILECHANGEDRO, NULL, NULL, FALSE, curbuf); 2850 if (!curbuf->b_p_ro) 2851 return; 2852 #endif 2853 /* 2854 * Do what msg() does, but with a column offset if the warning should 2855 * be after the mode message. 2856 */ 2857 msg_start(); 2858 if (msg_row == Rows - 1) 2859 msg_col = col; 2860 msg_source(hl_attr(HLF_W)); 2861 MSG_PUTS_ATTR(_("W10: Warning: Changing a readonly file"), 2862 hl_attr(HLF_W) | MSG_HIST); 2863 msg_clr_eos(); 2864 (void)msg_end(); 2865 if (msg_silent == 0 && !silent_mode) 2866 { 2867 out_flush(); 2868 ui_delay(1000L, TRUE); /* give the user time to think about it */ 2869 } 2870 curbuf->b_did_warn = TRUE; 2871 redraw_cmdline = FALSE; /* don't redraw and erase the message */ 2872 if (msg_row < Rows - 1) 2873 showmode(); 2874 } 2875 } 2876 2877 /* 2878 * Ask for a reply from the user, a 'y' or a 'n'. 2879 * No other characters are accepted, the message is repeated until a valid 2880 * reply is entered or CTRL-C is hit. 2881 * If direct is TRUE, don't use vgetc() but ui_inchar(), don't get characters 2882 * from any buffers but directly from the user. 2883 * 2884 * return the 'y' or 'n' 2885 */ 2886 int 2887 ask_yesno(str, direct) 2888 char_u *str; 2889 int direct; 2890 { 2891 int r = ' '; 2892 int save_State = State; 2893 2894 if (exiting) /* put terminal in raw mode for this question */ 2895 settmode(TMODE_RAW); 2896 ++no_wait_return; 2897 #ifdef USE_ON_FLY_SCROLL 2898 dont_scroll = TRUE; /* disallow scrolling here */ 2899 #endif 2900 State = CONFIRM; /* mouse behaves like with :confirm */ 2901 #ifdef FEAT_MOUSE 2902 setmouse(); /* disables mouse for xterm */ 2903 #endif 2904 ++no_mapping; 2905 ++allow_keys; /* no mapping here, but recognize keys */ 2906 2907 while (r != 'y' && r != 'n') 2908 { 2909 /* same highlighting as for wait_return */ 2910 smsg_attr(hl_attr(HLF_R), (char_u *)"%s (y/n)?", str); 2911 if (direct) 2912 r = get_keystroke(); 2913 else 2914 r = safe_vgetc(); 2915 if (r == Ctrl_C || r == ESC) 2916 r = 'n'; 2917 msg_putchar(r); /* show what you typed */ 2918 out_flush(); 2919 } 2920 --no_wait_return; 2921 State = save_State; 2922 #ifdef FEAT_MOUSE 2923 setmouse(); 2924 #endif 2925 --no_mapping; 2926 --allow_keys; 2927 2928 return r; 2929 } 2930 2931 /* 2932 * Get a key stroke directly from the user. 2933 * Ignores mouse clicks and scrollbar events, except a click for the left 2934 * button (used at the more prompt). 2935 * Doesn't use vgetc(), because it syncs undo and eats mapped characters. 2936 * Disadvantage: typeahead is ignored. 2937 * Translates the interrupt character for unix to ESC. 2938 */ 2939 int 2940 get_keystroke() 2941 { 2942 #define CBUFLEN 151 2943 char_u buf[CBUFLEN]; 2944 int len = 0; 2945 int n; 2946 int save_mapped_ctrl_c = mapped_ctrl_c; 2947 2948 mapped_ctrl_c = FALSE; /* mappings are not used here */ 2949 for (;;) 2950 { 2951 cursor_on(); 2952 out_flush(); 2953 2954 /* First time: blocking wait. Second time: wait up to 100ms for a 2955 * terminal code to complete. Leave some room for check_termcode() to 2956 * insert a key code into (max 5 chars plus NUL). And 2957 * fix_input_buffer() can triple the number of bytes. */ 2958 n = ui_inchar(buf + len, (CBUFLEN - 6 - len) / 3, 2959 len == 0 ? -1L : 100L, 0); 2960 if (n > 0) 2961 { 2962 /* Replace zero and CSI by a special key code. */ 2963 n = fix_input_buffer(buf + len, n, FALSE); 2964 len += n; 2965 } 2966 2967 /* incomplete termcode: get more characters */ 2968 if ((n = check_termcode(1, buf, len)) < 0) 2969 continue; 2970 /* found a termcode: adjust length */ 2971 if (n > 0) 2972 len = n; 2973 if (len == 0) /* nothing typed yet */ 2974 continue; 2975 2976 /* Handle modifier and/or special key code. */ 2977 n = buf[0]; 2978 if (n == K_SPECIAL) 2979 { 2980 n = TO_SPECIAL(buf[1], buf[2]); 2981 if (buf[1] == KS_MODIFIER 2982 || n == K_IGNORE 2983 #ifdef FEAT_MOUSE 2984 || n == K_LEFTMOUSE_NM 2985 || n == K_LEFTDRAG 2986 || n == K_LEFTRELEASE 2987 || n == K_LEFTRELEASE_NM 2988 || n == K_MIDDLEMOUSE 2989 || n == K_MIDDLEDRAG 2990 || n == K_MIDDLERELEASE 2991 || n == K_RIGHTMOUSE 2992 || n == K_RIGHTDRAG 2993 || n == K_RIGHTRELEASE 2994 || n == K_MOUSEDOWN 2995 || n == K_MOUSEUP 2996 || n == K_X1MOUSE 2997 || n == K_X1DRAG 2998 || n == K_X1RELEASE 2999 || n == K_X2MOUSE 3000 || n == K_X2DRAG 3001 || n == K_X2RELEASE 3002 # ifdef FEAT_GUI 3003 || n == K_VER_SCROLLBAR 3004 || n == K_HOR_SCROLLBAR 3005 # endif 3006 #endif 3007 ) 3008 { 3009 if (buf[1] == KS_MODIFIER) 3010 mod_mask = buf[2]; 3011 len -= 3; 3012 if (len > 0) 3013 mch_memmove(buf, buf + 3, (size_t)len); 3014 continue; 3015 } 3016 } 3017 #ifdef FEAT_MBYTE 3018 if (has_mbyte) 3019 { 3020 if (MB_BYTE2LEN(n) > len) 3021 continue; /* more bytes to get */ 3022 buf[len >= CBUFLEN ? CBUFLEN - 1 : len] = NUL; 3023 n = (*mb_ptr2char)(buf); 3024 } 3025 #endif 3026 #ifdef UNIX 3027 if (n == intr_char) 3028 n = ESC; 3029 #endif 3030 break; 3031 } 3032 3033 mapped_ctrl_c = save_mapped_ctrl_c; 3034 return n; 3035 } 3036 3037 /* 3038 * get a number from the user 3039 */ 3040 int 3041 get_number(colon) 3042 int colon; /* allow colon to abort */ 3043 { 3044 int n = 0; 3045 int c; 3046 3047 /* When not printing messages, the user won't know what to type, return a 3048 * zero (as if CR was hit). */ 3049 if (msg_silent != 0) 3050 return 0; 3051 3052 #ifdef USE_ON_FLY_SCROLL 3053 dont_scroll = TRUE; /* disallow scrolling here */ 3054 #endif 3055 ++no_mapping; 3056 ++allow_keys; /* no mapping here, but recognize keys */ 3057 for (;;) 3058 { 3059 windgoto(msg_row, msg_col); 3060 c = safe_vgetc(); 3061 if (VIM_ISDIGIT(c)) 3062 { 3063 n = n * 10 + c - '0'; 3064 msg_putchar(c); 3065 } 3066 else if (c == K_DEL || c == K_KDEL || c == K_BS || c == Ctrl_H) 3067 { 3068 n /= 10; 3069 MSG_PUTS("\b \b"); 3070 } 3071 else if (n == 0 && c == ':' && colon) 3072 { 3073 stuffcharReadbuff(':'); 3074 if (!exmode_active) 3075 cmdline_row = msg_row; 3076 skip_redraw = TRUE; /* skip redraw once */ 3077 do_redraw = FALSE; 3078 break; 3079 } 3080 else if (c == CAR || c == NL || c == Ctrl_C || c == ESC) 3081 break; 3082 } 3083 --no_mapping; 3084 --allow_keys; 3085 return n; 3086 } 3087 3088 void 3089 msgmore(n) 3090 long n; 3091 { 3092 long pn; 3093 3094 if (global_busy /* no messages now, wait until global is finished */ 3095 || keep_msg != NULL /* there is a message already, skip this one */ 3096 || !messaging()) /* 'lazyredraw' set, don't do messages now */ 3097 return; 3098 3099 if (n > 0) 3100 pn = n; 3101 else 3102 pn = -n; 3103 3104 if (pn > p_report) 3105 { 3106 if (pn == 1) 3107 { 3108 if (n > 0) 3109 STRCPY(msg_buf, _("1 more line")); 3110 else 3111 STRCPY(msg_buf, _("1 line less")); 3112 } 3113 else 3114 { 3115 if (n > 0) 3116 sprintf((char *)msg_buf, _("%ld more lines"), pn); 3117 else 3118 sprintf((char *)msg_buf, _("%ld fewer lines"), pn); 3119 } 3120 if (got_int) 3121 STRCAT(msg_buf, _(" (Interrupted)")); 3122 if (msg(msg_buf)) 3123 { 3124 set_keep_msg(msg_buf); 3125 keep_msg_attr = 0; 3126 } 3127 } 3128 } 3129 3130 /* 3131 * flush map and typeahead buffers and give a warning for an error 3132 */ 3133 void 3134 beep_flush() 3135 { 3136 if (emsg_silent == 0) 3137 { 3138 flush_buffers(FALSE); 3139 vim_beep(); 3140 } 3141 } 3142 3143 /* 3144 * give a warning for an error 3145 */ 3146 void 3147 vim_beep() 3148 { 3149 if (emsg_silent == 0) 3150 { 3151 if (p_vb 3152 #ifdef FEAT_GUI 3153 /* While the GUI is starting up the termcap is set for the GUI 3154 * but the output still goes to a terminal. */ 3155 && !(gui.in_use && gui.starting) 3156 #endif 3157 ) 3158 { 3159 out_str(T_VB); 3160 } 3161 else 3162 { 3163 #ifdef MSDOS 3164 /* 3165 * The number of beeps outputted is reduced to avoid having to wait 3166 * for all the beeps to finish. This is only a problem on systems 3167 * where the beeps don't overlap. 3168 */ 3169 if (beep_count == 0 || beep_count == 10) 3170 { 3171 out_char(BELL); 3172 beep_count = 1; 3173 } 3174 else 3175 ++beep_count; 3176 #else 3177 out_char(BELL); 3178 #endif 3179 } 3180 } 3181 } 3182 3183 /* 3184 * To get the "real" home directory: 3185 * - get value of $HOME 3186 * For Unix: 3187 * - go to that directory 3188 * - do mch_dirname() to get the real name of that directory. 3189 * This also works with mounts and links. 3190 * Don't do this for MS-DOS, it will change the "current dir" for a drive. 3191 */ 3192 static char_u *homedir = NULL; 3193 3194 void 3195 init_homedir() 3196 { 3197 char_u *var; 3198 3199 #ifdef VMS 3200 var = mch_getenv((char_u *)"SYS$LOGIN"); 3201 #else 3202 var = mch_getenv((char_u *)"HOME"); 3203 #endif 3204 3205 if (var != NULL && *var == NUL) /* empty is same as not set */ 3206 var = NULL; 3207 3208 #ifdef WIN3264 3209 /* 3210 * Weird but true: $HOME may contain an indirect reference to another 3211 * variable, esp. "%USERPROFILE%". Happens when $USERPROFILE isn't set 3212 * when $HOME is being set. 3213 */ 3214 if (var != NULL && *var == '%') 3215 { 3216 char_u *p; 3217 char_u *exp; 3218 3219 p = vim_strchr(var + 1, '%'); 3220 if (p != NULL) 3221 { 3222 STRNCPY(NameBuff, var + 1, p - (var + 1)); 3223 NameBuff[p - (var + 1)] = NUL; 3224 exp = mch_getenv(NameBuff); 3225 if (exp != NULL && *exp != NUL 3226 && STRLEN(exp) + STRLEN(p) < MAXPATHL) 3227 { 3228 sprintf((char *)NameBuff, "%s%s", exp, p + 1); 3229 var = NameBuff; 3230 /* Also set $HOME, it's needed for _viminfo. */ 3231 vim_setenv((char_u *)"HOME", NameBuff); 3232 } 3233 } 3234 } 3235 3236 /* 3237 * Typically, $HOME is not defined on Windows, unless the user has 3238 * specifically defined it for Vim's sake. However, on Windows NT 3239 * platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for 3240 * each user. Try constructing $HOME from these. 3241 */ 3242 if (var == NULL) 3243 { 3244 char_u *homedrive, *homepath; 3245 3246 homedrive = mch_getenv((char_u *)"HOMEDRIVE"); 3247 homepath = mch_getenv((char_u *)"HOMEPATH"); 3248 if (homedrive != NULL && homepath != NULL 3249 && STRLEN(homedrive) + STRLEN(homepath) < MAXPATHL) 3250 { 3251 sprintf((char *)NameBuff, "%s%s", homedrive, homepath); 3252 if (NameBuff[0] != NUL) 3253 { 3254 var = NameBuff; 3255 /* Also set $HOME, it's needed for _viminfo. */ 3256 vim_setenv((char_u *)"HOME", NameBuff); 3257 } 3258 } 3259 } 3260 #endif 3261 3262 #if defined(OS2) || defined(MSDOS) || defined(MSWIN) 3263 /* 3264 * Default home dir is C:/ 3265 * Best assumption we can make in such a situation. 3266 */ 3267 if (var == NULL) 3268 var = "C:/"; 3269 #endif 3270 if (var != NULL) 3271 { 3272 #ifdef UNIX 3273 /* 3274 * Change to the directory and get the actual path. This resolves 3275 * links. Don't do it when we can't return. 3276 */ 3277 if (mch_dirname(NameBuff, MAXPATHL) == OK 3278 && mch_chdir((char *)NameBuff) == 0) 3279 { 3280 if (!mch_chdir((char *)var) && mch_dirname(IObuff, IOSIZE) == OK) 3281 var = IObuff; 3282 if (mch_chdir((char *)NameBuff) != 0) 3283 EMSG(_(e_prev_dir)); 3284 } 3285 #endif 3286 homedir = vim_strsave(var); 3287 } 3288 } 3289 3290 /* 3291 * Expand environment variable with path name. 3292 * "~/" is also expanded, using $HOME. For Unix "~user/" is expanded. 3293 * Skips over "\ ", "\~" and "\$". 3294 * If anything fails no expansion is done and dst equals src. 3295 */ 3296 void 3297 expand_env(src, dst, dstlen) 3298 char_u *src; /* input string e.g. "$HOME/vim.hlp" */ 3299 char_u *dst; /* where to put the result */ 3300 int dstlen; /* maximum length of the result */ 3301 { 3302 expand_env_esc(src, dst, dstlen, FALSE); 3303 } 3304 3305 void 3306 expand_env_esc(src, dst, dstlen, esc) 3307 char_u *src; /* input string e.g. "$HOME/vim.hlp" */ 3308 char_u *dst; /* where to put the result */ 3309 int dstlen; /* maximum length of the result */ 3310 int esc; /* escape spaces in expanded variables */ 3311 { 3312 char_u *tail; 3313 int c; 3314 char_u *var; 3315 int copy_char; 3316 int mustfree; /* var was allocated, need to free it later */ 3317 int at_start = TRUE; /* at start of a name */ 3318 3319 src = skipwhite(src); 3320 --dstlen; /* leave one char space for "\," */ 3321 while (*src && dstlen > 0) 3322 { 3323 copy_char = TRUE; 3324 if (*src == '$' 3325 #if defined(MSDOS) || defined(MSWIN) || defined(OS2) 3326 || *src == '%' 3327 #endif 3328 || (*src == '~' && at_start)) 3329 { 3330 mustfree = FALSE; 3331 3332 /* 3333 * The variable name is copied into dst temporarily, because it may 3334 * be a string in read-only memory and a NUL needs to be appended. 3335 */ 3336 if (*src != '~') /* environment var */ 3337 { 3338 tail = src + 1; 3339 var = dst; 3340 c = dstlen - 1; 3341 3342 #ifdef UNIX 3343 /* Unix has ${var-name} type environment vars */ 3344 if (*tail == '{' && !vim_isIDc('{')) 3345 { 3346 tail++; /* ignore '{' */ 3347 while (c-- > 0 && *tail && *tail != '}') 3348 *var++ = *tail++; 3349 } 3350 else 3351 #endif 3352 { 3353 while (c-- > 0 && *tail != NUL && ((vim_isIDc(*tail)) 3354 #if defined(MSDOS) || defined(MSWIN) || defined(OS2) 3355 || (*src == '%' && *tail != '%') 3356 #endif 3357 )) 3358 { 3359 #ifdef OS2 /* env vars only in uppercase */ 3360 *var++ = TOUPPER_LOC(*tail); 3361 tail++; /* toupper() may be a macro! */ 3362 #else 3363 *var++ = *tail++; 3364 #endif 3365 } 3366 } 3367 3368 #if defined(MSDOS) || defined(MSWIN) || defined(OS2) || defined(UNIX) 3369 # ifdef UNIX 3370 if (src[1] == '{' && *tail != '}') 3371 # else 3372 if (*src == '%' && *tail != '%') 3373 # endif 3374 var = NULL; 3375 else 3376 { 3377 # ifdef UNIX 3378 if (src[1] == '{') 3379 # else 3380 if (*src == '%') 3381 #endif 3382 ++tail; 3383 #endif 3384 *var = NUL; 3385 var = vim_getenv(dst, &mustfree); 3386 #if defined(MSDOS) || defined(MSWIN) || defined(OS2) || defined(UNIX) 3387 } 3388 #endif 3389 } 3390 /* home directory */ 3391 else if ( src[1] == NUL 3392 || vim_ispathsep(src[1]) 3393 || vim_strchr((char_u *)" ,\t\n", src[1]) != NULL) 3394 { 3395 var = homedir; 3396 tail = src + 1; 3397 } 3398 else /* user directory */ 3399 { 3400 #if defined(UNIX) || (defined(VMS) && defined(USER_HOME)) 3401 /* 3402 * Copy ~user to dst[], so we can put a NUL after it. 3403 */ 3404 tail = src; 3405 var = dst; 3406 c = dstlen - 1; 3407 while ( c-- > 0 3408 && *tail 3409 && vim_isfilec(*tail) 3410 && !vim_ispathsep(*tail)) 3411 *var++ = *tail++; 3412 *var = NUL; 3413 # ifdef UNIX 3414 /* 3415 * If the system supports getpwnam(), use it. 3416 * Otherwise, or if getpwnam() fails, the shell is used to 3417 * expand ~user. This is slower and may fail if the shell 3418 * does not support ~user (old versions of /bin/sh). 3419 */ 3420 # if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H) 3421 { 3422 struct passwd *pw; 3423 3424 pw = getpwnam((char *)dst + 1); 3425 if (pw != NULL) 3426 var = (char_u *)pw->pw_dir; 3427 else 3428 var = NULL; 3429 } 3430 if (var == NULL) 3431 # endif 3432 { 3433 expand_T xpc; 3434 3435 ExpandInit(&xpc); 3436 xpc.xp_context = EXPAND_FILES; 3437 var = ExpandOne(&xpc, dst, NULL, 3438 WILD_ADD_SLASH|WILD_SILENT, WILD_EXPAND_FREE); 3439 ExpandCleanup(&xpc); 3440 mustfree = TRUE; 3441 } 3442 3443 # else /* !UNIX, thus VMS */ 3444 /* 3445 * USER_HOME is a comma-separated list of 3446 * directories to search for the user account in. 3447 */ 3448 { 3449 char_u test[MAXPATHL], paths[MAXPATHL]; 3450 char_u *path, *next_path, *ptr; 3451 struct stat st; 3452 3453 STRCPY(paths, USER_HOME); 3454 next_path = paths; 3455 while (*next_path) 3456 { 3457 for (path = next_path; *next_path && *next_path != ','; 3458 next_path++); 3459 if (*next_path) 3460 *next_path++ = NUL; 3461 STRCPY(test, path); 3462 STRCAT(test, "/"); 3463 STRCAT(test, dst + 1); 3464 if (mch_stat(test, &st) == 0) 3465 { 3466 var = alloc(STRLEN(test) + 1); 3467 STRCPY(var, test); 3468 mustfree = TRUE; 3469 break; 3470 } 3471 } 3472 } 3473 # endif /* UNIX */ 3474 #else 3475 /* cannot expand user's home directory, so don't try */ 3476 var = NULL; 3477 tail = (char_u *)""; /* for gcc */ 3478 #endif /* UNIX || VMS */ 3479 } 3480 3481 #ifdef BACKSLASH_IN_FILENAME 3482 /* If 'shellslash' is set change backslashes to forward slashes. 3483 * Can't use slash_adjust(), p_ssl may be set temporarily. */ 3484 if (p_ssl && var != NULL && vim_strchr(var, '\\') != NULL) 3485 { 3486 char_u *p = vim_strsave(var); 3487 3488 if (p != NULL) 3489 { 3490 if (mustfree) 3491 vim_free(var); 3492 var = p; 3493 mustfree = TRUE; 3494 forward_slash(var); 3495 } 3496 } 3497 #endif 3498 3499 /* If "var" contains white space, escape it with a backslash. 3500 * Required for ":e ~/tt" when $HOME includes a space. */ 3501 if (esc && var != NULL && vim_strpbrk(var, (char_u *)" \t") != NULL) 3502 { 3503 char_u *p = vim_strsave_escaped(var, (char_u *)" \t"); 3504 3505 if (p != NULL) 3506 { 3507 if (mustfree) 3508 vim_free(var); 3509 var = p; 3510 mustfree = TRUE; 3511 } 3512 } 3513 3514 if (var != NULL && *var != NUL 3515 && (STRLEN(var) + STRLEN(tail) + 1 < (unsigned)dstlen)) 3516 { 3517 STRCPY(dst, var); 3518 dstlen -= (int)STRLEN(var); 3519 dst += STRLEN(var); 3520 /* if var[] ends in a path separator and tail[] starts 3521 * with it, skip a character */ 3522 if (*var != NUL && vim_ispathsep(dst[-1]) 3523 #if defined(BACKSLASH_IN_FILENAME) || defined(AMIGA) 3524 && dst[-1] != ':' 3525 #endif 3526 && vim_ispathsep(*tail)) 3527 ++tail; 3528 src = tail; 3529 copy_char = FALSE; 3530 } 3531 if (mustfree) 3532 vim_free(var); 3533 } 3534 3535 if (copy_char) /* copy at least one char */ 3536 { 3537 /* 3538 * Recogize the start of a new name, for '~'. 3539 */ 3540 at_start = FALSE; 3541 if (src[0] == '\\' && src[1] != NUL) 3542 { 3543 *dst++ = *src++; 3544 --dstlen; 3545 } 3546 else if (src[0] == ' ' || src[0] == ',') 3547 at_start = TRUE; 3548 *dst++ = *src++; 3549 --dstlen; 3550 } 3551 } 3552 *dst = NUL; 3553 } 3554 3555 /* 3556 * Vim's version of getenv(). 3557 * Special handling of $HOME, $VIM and $VIMRUNTIME. 3558 */ 3559 char_u * 3560 vim_getenv(name, mustfree) 3561 char_u *name; 3562 int *mustfree; /* set to TRUE when returned is allocated */ 3563 { 3564 char_u *p; 3565 char_u *pend; 3566 int vimruntime; 3567 3568 #if defined(OS2) || defined(MSDOS) || defined(MSWIN) 3569 /* use "C:/" when $HOME is not set */ 3570 if (STRCMP(name, "HOME") == 0) 3571 return homedir; 3572 #endif 3573 3574 p = mch_getenv(name); 3575 if (p != NULL && *p == NUL) /* empty is the same as not set */ 3576 p = NULL; 3577 3578 if (p != NULL) 3579 return p; 3580 3581 vimruntime = (STRCMP(name, "VIMRUNTIME") == 0); 3582 if (!vimruntime && STRCMP(name, "VIM") != 0) 3583 return NULL; 3584 3585 /* 3586 * When expanding $VIMRUNTIME fails, try using $VIM/vim<version> or $VIM. 3587 * Don't do this when default_vimruntime_dir is non-empty. 3588 */ 3589 if (vimruntime 3590 #ifdef HAVE_PATHDEF 3591 && *default_vimruntime_dir == NUL 3592 #endif 3593 ) 3594 { 3595 p = mch_getenv((char_u *)"VIM"); 3596 if (p != NULL && *p == NUL) /* empty is the same as not set */ 3597 p = NULL; 3598 if (p != NULL) 3599 { 3600 p = vim_version_dir(p); 3601 if (p != NULL) 3602 *mustfree = TRUE; 3603 else 3604 p = mch_getenv((char_u *)"VIM"); 3605 } 3606 } 3607 3608 /* 3609 * When expanding $VIM or $VIMRUNTIME fails, try using: 3610 * - the directory name from 'helpfile' (unless it contains '$') 3611 * - the executable name from argv[0] 3612 */ 3613 if (p == NULL) 3614 { 3615 if (p_hf != NULL && vim_strchr(p_hf, '$') == NULL) 3616 p = p_hf; 3617 #ifdef USE_EXE_NAME 3618 /* 3619 * Use the name of the executable, obtained from argv[0]. 3620 */ 3621 else 3622 p = exe_name; 3623 #endif 3624 if (p != NULL) 3625 { 3626 /* remove the file name */ 3627 pend = gettail(p); 3628 3629 /* remove "doc/" from 'helpfile', if present */ 3630 if (p == p_hf) 3631 pend = remove_tail(p, pend, (char_u *)"doc"); 3632 3633 #ifdef USE_EXE_NAME 3634 # ifdef MACOS_X 3635 /* remove "build/..." from exe_name, if present */ 3636 if (p == exe_name) 3637 { 3638 char_u *pend1; 3639 char_u *pend2; 3640 3641 pend1 = remove_tail(p, pend, (char_u *)"Contents/MacOS"); 3642 pend2 = remove_tail_with_ext(p, pend1, (char_u *)".app"); 3643 pend = remove_tail(p, pend2, (char_u *)"build"); 3644 /* When runnig from project builder get rid of the 3645 * build/???.app, otherwise keep the ???.app */ 3646 if (pend2 == pend) 3647 pend = pend1; 3648 } 3649 # endif 3650 /* remove "src/" from exe_name, if present */ 3651 if (p == exe_name) 3652 pend = remove_tail(p, pend, (char_u *)"src"); 3653 #endif 3654 3655 /* for $VIM, remove "runtime/" or "vim54/", if present */ 3656 if (!vimruntime) 3657 { 3658 pend = remove_tail(p, pend, (char_u *)RUNTIME_DIRNAME); 3659 pend = remove_tail(p, pend, (char_u *)VIM_VERSION_NODOT); 3660 } 3661 3662 /* remove trailing path separator */ 3663 #ifndef MACOS_CLASSIC 3664 /* With MacOS path (with colons) the final colon is required */ 3665 /* to avoid confusion between absoulute and relative path */ 3666 if (pend > p && vim_ispathsep(*(pend - 1))) 3667 --pend; 3668 #endif 3669 3670 /* check that the result is a directory name */ 3671 p = vim_strnsave(p, (int)(pend - p)); 3672 3673 if (p != NULL && !mch_isdir(p)) 3674 { 3675 vim_free(p); 3676 p = NULL; 3677 } 3678 else 3679 { 3680 #ifdef USE_EXE_NAME 3681 /* may add "/vim54" or "/runtime" if it exists */ 3682 if (vimruntime && (pend = vim_version_dir(p)) != NULL) 3683 { 3684 vim_free(p); 3685 p = pend; 3686 } 3687 #endif 3688 *mustfree = TRUE; 3689 } 3690 } 3691 } 3692 3693 #ifdef HAVE_PATHDEF 3694 /* When there is a pathdef.c file we can use default_vim_dir and 3695 * default_vimruntime_dir */ 3696 if (p == NULL) 3697 { 3698 /* Only use default_vimruntime_dir when it is not empty */ 3699 if (vimruntime && *default_vimruntime_dir != NUL) 3700 { 3701 p = default_vimruntime_dir; 3702 *mustfree = FALSE; 3703 } 3704 else if (*default_vim_dir != NUL) 3705 { 3706 if (vimruntime && (p = vim_version_dir(default_vim_dir)) != NULL) 3707 *mustfree = TRUE; 3708 else 3709 { 3710 p = default_vim_dir; 3711 *mustfree = FALSE; 3712 } 3713 } 3714 } 3715 #endif 3716 3717 /* 3718 * Set the environment variable, so that the new value can be found fast 3719 * next time, and others can also use it (e.g. Perl). 3720 */ 3721 if (p != NULL) 3722 { 3723 if (vimruntime) 3724 { 3725 vim_setenv((char_u *)"VIMRUNTIME", p); 3726 didset_vimruntime = TRUE; 3727 #ifdef FEAT_GETTEXT 3728 { 3729 char_u *buf = alloc((unsigned int)STRLEN(p) + 6); 3730 3731 if (buf != NULL) 3732 { 3733 STRCPY(buf, p); 3734 STRCAT(buf, "/lang"); 3735 bindtextdomain(VIMPACKAGE, (char *)buf); 3736 vim_free(buf); 3737 } 3738 } 3739 #endif 3740 } 3741 else 3742 { 3743 vim_setenv((char_u *)"VIM", p); 3744 didset_vim = TRUE; 3745 } 3746 } 3747 return p; 3748 } 3749 3750 /* 3751 * Check if the directory "vimdir/<version>" or "vimdir/runtime" exists. 3752 * Return NULL if not, return its name in allocated memory otherwise. 3753 */ 3754 static char_u * 3755 vim_version_dir(vimdir) 3756 char_u *vimdir; 3757 { 3758 char_u *p; 3759 3760 if (vimdir == NULL || *vimdir == NUL) 3761 return NULL; 3762 p = concat_fnames(vimdir, (char_u *)VIM_VERSION_NODOT, TRUE); 3763 if (p != NULL && mch_isdir(p)) 3764 return p; 3765 vim_free(p); 3766 p = concat_fnames(vimdir, (char_u *)RUNTIME_DIRNAME, TRUE); 3767 if (p != NULL && mch_isdir(p)) 3768 return p; 3769 vim_free(p); 3770 return NULL; 3771 } 3772 3773 /* 3774 * If the string between "p" and "pend" ends in "name/", return "pend" minus 3775 * the length of "name/". Otherwise return "pend". 3776 */ 3777 static char_u * 3778 remove_tail(p, pend, name) 3779 char_u *p; 3780 char_u *pend; 3781 char_u *name; 3782 { 3783 int len = (int)STRLEN(name) + 1; 3784 char_u *newend = pend - len; 3785 3786 if (newend >= p 3787 && fnamencmp(newend, name, len - 1) == 0 3788 && (newend == p || vim_ispathsep(*(newend - 1)))) 3789 return newend; 3790 return pend; 3791 } 3792 3793 #if defined(USE_EXE_NAME) && defined(MACOS_X) 3794 /* 3795 * If the string between "p" and "pend" ends in "???.ext/", return "pend" 3796 * minus the length of "???.ext/". Otherwise return "pend". 3797 */ 3798 static char_u * 3799 remove_tail_with_ext(p, pend, ext) 3800 char_u *p; 3801 char_u *pend; 3802 char_u *ext; 3803 { 3804 int len = (int)STRLEN(ext) + 1; 3805 char_u *newend = pend - len; 3806 3807 if (newend >= p && fnamencmp(newend, ext, len - 1) == 0) 3808 while (newend != p && !vim_ispathsep(*(newend - 1))) 3809 --newend; 3810 if (newend == p || vim_ispathsep(*(newend - 1))) 3811 return newend; 3812 return pend; 3813 } 3814 #endif 3815 3816 /* 3817 * Call expand_env() and store the result in an allocated string. 3818 * This is not very memory efficient, this expects the result to be freed 3819 * again soon. 3820 */ 3821 char_u * 3822 expand_env_save(src) 3823 char_u *src; 3824 { 3825 char_u *p; 3826 3827 p = alloc(MAXPATHL); 3828 if (p != NULL) 3829 expand_env(src, p, MAXPATHL); 3830 return p; 3831 } 3832 3833 /* 3834 * Our portable version of setenv. 3835 */ 3836 void 3837 vim_setenv(name, val) 3838 char_u *name; 3839 char_u *val; 3840 { 3841 #ifdef HAVE_SETENV 3842 mch_setenv((char *)name, (char *)val, 1); 3843 #else 3844 char_u *envbuf; 3845 3846 /* 3847 * Putenv does not copy the string, it has to remain 3848 * valid. The allocated memory will never be freed. 3849 */ 3850 envbuf = alloc((unsigned)(STRLEN(name) + STRLEN(val) + 2)); 3851 if (envbuf != NULL) 3852 { 3853 sprintf((char *)envbuf, "%s=%s", name, val); 3854 putenv((char *)envbuf); 3855 } 3856 #endif 3857 } 3858 3859 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 3860 /* 3861 * Function given to ExpandGeneric() to obtain an environment variable name. 3862 */ 3863 /*ARGSUSED*/ 3864 char_u * 3865 get_env_name(xp, idx) 3866 expand_T *xp; 3867 int idx; 3868 { 3869 # if defined(AMIGA) || defined(__MRC__) || defined(__SC__) 3870 /* 3871 * No environ[] on the Amiga and on the Mac (using MPW). 3872 */ 3873 return NULL; 3874 # else 3875 # ifndef __WIN32__ 3876 /* Borland C++ 5.2 has this in a header file. */ 3877 extern char **environ; 3878 # endif 3879 # define ENVNAMELEN 100 3880 static char_u name[ENVNAMELEN]; 3881 char_u *str; 3882 int n; 3883 3884 str = (char_u *)environ[idx]; 3885 if (str == NULL) 3886 return NULL; 3887 3888 for (n = 0; n < ENVNAMELEN - 1; ++n) 3889 { 3890 if (str[n] == '=' || str[n] == NUL) 3891 break; 3892 name[n] = str[n]; 3893 } 3894 name[n] = NUL; 3895 return name; 3896 # endif 3897 } 3898 #endif 3899 3900 /* 3901 * Replace home directory by "~" in each space or comma separated file name in 3902 * 'src'. 3903 * If anything fails (except when out of space) dst equals src. 3904 */ 3905 void 3906 home_replace(buf, src, dst, dstlen, one) 3907 buf_T *buf; /* when not NULL, check for help files */ 3908 char_u *src; /* input file name */ 3909 char_u *dst; /* where to put the result */ 3910 int dstlen; /* maximum length of the result */ 3911 int one; /* if TRUE, only replace one file name, include 3912 spaces and commas in the file name. */ 3913 { 3914 size_t dirlen = 0, envlen = 0; 3915 size_t len; 3916 char_u *homedir_env; 3917 char_u *p; 3918 3919 if (src == NULL) 3920 { 3921 *dst = NUL; 3922 return; 3923 } 3924 3925 /* 3926 * If the file is a help file, remove the path completely. 3927 */ 3928 if (buf != NULL && buf->b_help) 3929 { 3930 STRCPY(dst, gettail(src)); 3931 return; 3932 } 3933 3934 /* 3935 * We check both the value of the $HOME environment variable and the 3936 * "real" home directory. 3937 */ 3938 if (homedir != NULL) 3939 dirlen = STRLEN(homedir); 3940 3941 #ifdef VMS 3942 homedir_env = mch_getenv((char_u *)"SYS$LOGIN"); 3943 #else 3944 homedir_env = mch_getenv((char_u *)"HOME"); 3945 #endif 3946 3947 if (homedir_env != NULL && *homedir_env == NUL) 3948 homedir_env = NULL; 3949 if (homedir_env != NULL) 3950 envlen = STRLEN(homedir_env); 3951 3952 if (!one) 3953 src = skipwhite(src); 3954 while (*src && dstlen > 0) 3955 { 3956 /* 3957 * Here we are at the beginning of a file name. 3958 * First, check to see if the beginning of the file name matches 3959 * $HOME or the "real" home directory. Check that there is a '/' 3960 * after the match (so that if e.g. the file is "/home/pieter/bla", 3961 * and the home directory is "/home/piet", the file does not end up 3962 * as "~er/bla" (which would seem to indicate the file "bla" in user 3963 * er's home directory)). 3964 */ 3965 p = homedir; 3966 len = dirlen; 3967 for (;;) 3968 { 3969 if ( len 3970 && fnamencmp(src, p, len) == 0 3971 && (vim_ispathsep(src[len]) 3972 || (!one && (src[len] == ',' || src[len] == ' ')) 3973 || src[len] == NUL)) 3974 { 3975 src += len; 3976 if (--dstlen > 0) 3977 *dst++ = '~'; 3978 3979 /* 3980 * If it's just the home directory, add "/". 3981 */ 3982 if (!vim_ispathsep(src[0]) && --dstlen > 0) 3983 *dst++ = '/'; 3984 break; 3985 } 3986 if (p == homedir_env) 3987 break; 3988 p = homedir_env; 3989 len = envlen; 3990 } 3991 3992 /* if (!one) skip to separator: space or comma */ 3993 while (*src && (one || (*src != ',' && *src != ' ')) && --dstlen > 0) 3994 *dst++ = *src++; 3995 /* skip separator */ 3996 while ((*src == ' ' || *src == ',') && --dstlen > 0) 3997 *dst++ = *src++; 3998 } 3999 /* if (dstlen == 0) out of space, what to do??? */ 4000 4001 *dst = NUL; 4002 } 4003 4004 /* 4005 * Like home_replace, store the replaced string in allocated memory. 4006 * When something fails, NULL is returned. 4007 */ 4008 char_u * 4009 home_replace_save(buf, src) 4010 buf_T *buf; /* when not NULL, check for help files */ 4011 char_u *src; /* input file name */ 4012 { 4013 char_u *dst; 4014 unsigned len; 4015 4016 len = 3; /* space for "~/" and trailing NUL */ 4017 if (src != NULL) /* just in case */ 4018 len += (unsigned)STRLEN(src); 4019 dst = alloc(len); 4020 if (dst != NULL) 4021 home_replace(buf, src, dst, len, TRUE); 4022 return dst; 4023 } 4024 4025 /* 4026 * Compare two file names and return: 4027 * FPC_SAME if they both exist and are the same file. 4028 * FPC_SAMEX if they both don't exist and have the same file name. 4029 * FPC_DIFF if they both exist and are different files. 4030 * FPC_NOTX if they both don't exist. 4031 * FPC_DIFFX if one of them doesn't exist. 4032 * For the first name environment variables are expanded 4033 */ 4034 int 4035 fullpathcmp(s1, s2, checkname) 4036 char_u *s1, *s2; 4037 int checkname; /* when both don't exist, check file names */ 4038 { 4039 #ifdef UNIX 4040 char_u exp1[MAXPATHL]; 4041 char_u full1[MAXPATHL]; 4042 char_u full2[MAXPATHL]; 4043 struct stat st1, st2; 4044 int r1, r2; 4045 4046 expand_env(s1, exp1, MAXPATHL); 4047 r1 = mch_stat((char *)exp1, &st1); 4048 r2 = mch_stat((char *)s2, &st2); 4049 if (r1 != 0 && r2 != 0) 4050 { 4051 /* if mch_stat() doesn't work, may compare the names */ 4052 if (checkname) 4053 { 4054 if (fnamecmp(exp1, s2) == 0) 4055 return FPC_SAMEX; 4056 r1 = vim_FullName(exp1, full1, MAXPATHL, FALSE); 4057 r2 = vim_FullName(s2, full2, MAXPATHL, FALSE); 4058 if (r1 == OK && r2 == OK && fnamecmp(full1, full2) == 0) 4059 return FPC_SAMEX; 4060 } 4061 return FPC_NOTX; 4062 } 4063 if (r1 != 0 || r2 != 0) 4064 return FPC_DIFFX; 4065 if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) 4066 return FPC_SAME; 4067 return FPC_DIFF; 4068 #else 4069 char_u *exp1; /* expanded s1 */ 4070 char_u *full1; /* full path of s1 */ 4071 char_u *full2; /* full path of s2 */ 4072 int retval = FPC_DIFF; 4073 int r1, r2; 4074 4075 /* allocate one buffer to store three paths (alloc()/free() is slow!) */ 4076 if ((exp1 = alloc(MAXPATHL * 3)) != NULL) 4077 { 4078 full1 = exp1 + MAXPATHL; 4079 full2 = full1 + MAXPATHL; 4080 4081 expand_env(s1, exp1, MAXPATHL); 4082 r1 = vim_FullName(exp1, full1, MAXPATHL, FALSE); 4083 r2 = vim_FullName(s2, full2, MAXPATHL, FALSE); 4084 4085 /* If vim_FullName() fails, the file probably doesn't exist. */ 4086 if (r1 != OK && r2 != OK) 4087 { 4088 if (checkname && fnamecmp(exp1, s2) == 0) 4089 retval = FPC_SAMEX; 4090 else 4091 retval = FPC_NOTX; 4092 } 4093 else if (r1 != OK || r2 != OK) 4094 retval = FPC_DIFFX; 4095 else if (fnamecmp(full1, full2)) 4096 retval = FPC_DIFF; 4097 else 4098 retval = FPC_SAME; 4099 vim_free(exp1); 4100 } 4101 return retval; 4102 #endif 4103 } 4104 4105 /* 4106 * Get the tail of a path: the file name. 4107 * Fail safe: never returns NULL. 4108 */ 4109 char_u * 4110 gettail(fname) 4111 char_u *fname; 4112 { 4113 char_u *p1, *p2; 4114 4115 if (fname == NULL) 4116 return (char_u *)""; 4117 for (p1 = p2 = fname; *p2; ) /* find last part of path */ 4118 { 4119 if (vim_ispathsep(*p2)) 4120 p1 = p2 + 1; 4121 #ifdef FEAT_MBYTE 4122 if (has_mbyte) 4123 p2 += (*mb_ptr2len_check)(p2); 4124 else 4125 #endif 4126 ++p2; 4127 } 4128 return p1; 4129 } 4130 4131 /* 4132 * get the next path component (just after the next path separator). 4133 */ 4134 char_u * 4135 getnextcomp(fname) 4136 char_u *fname; 4137 { 4138 while (*fname && !vim_ispathsep(*fname)) 4139 ++fname; 4140 if (*fname) 4141 ++fname; 4142 return fname; 4143 } 4144 4145 #if defined(FEAT_MODIFY_FNAME) || defined(FEAT_EVAL) \ 4146 || defined(FEAT_SESSION) || defined(MSWIN) \ 4147 || ((defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE)) \ 4148 && (defined(FEAT_WINDOWS) || defined(FEAT_DND))) \ 4149 || defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) \ 4150 || defined(PROTO) 4151 /* 4152 * Get a pointer to one character past the head of a path name. 4153 * Unix: after "/"; DOS: after "c:\"; Amiga: after "disk:/"; Mac: no head. 4154 * If there is no head, path is returned. 4155 */ 4156 char_u * 4157 get_past_head(path) 4158 char_u *path; 4159 { 4160 char_u *retval; 4161 4162 #if defined(MSDOS) || defined(MSWIN) || defined(OS2) 4163 /* may skip "c:" */ 4164 if (isalpha(path[0]) && path[1] == ':') 4165 retval = path + 2; 4166 else 4167 retval = path; 4168 #else 4169 # if defined(AMIGA) 4170 /* may skip "label:" */ 4171 retval = vim_strchr(path, ':'); 4172 if (retval == NULL) 4173 retval = path; 4174 # else /* Unix */ 4175 retval = path; 4176 # endif 4177 #endif 4178 4179 while (vim_ispathsep(*retval)) 4180 ++retval; 4181 4182 return retval; 4183 } 4184 #endif 4185 4186 /* 4187 * return TRUE if 'c' is a path separator. 4188 */ 4189 int 4190 vim_ispathsep(c) 4191 int c; 4192 { 4193 #ifdef RISCOS 4194 return (c == '.' || c == ':'); 4195 #else 4196 # ifdef UNIX 4197 return (c == '/'); /* UNIX has ':' inside file names */ 4198 # else 4199 # ifdef BACKSLASH_IN_FILENAME 4200 return (c == ':' || c == '/' || c == '\\'); 4201 # else 4202 # ifdef VMS 4203 /* server"user passwd"::device:[full.path.name]fname.extension;version" */ 4204 return (c == ':' || c == '[' || c == ']' || c == '/' 4205 || c == '<' || c == '>' || c == '"' ); 4206 # else 4207 # ifdef COLON_AS_PATHSEP 4208 return (c == ':'); 4209 # else /* Amiga */ 4210 return (c == ':' || c == '/'); 4211 # endif 4212 # endif /* VMS */ 4213 # endif 4214 # endif 4215 #endif /* RISC OS */ 4216 } 4217 4218 #if defined(FEAT_SEARCHPATH) || defined(PROTO) 4219 /* 4220 * return TRUE if 'c' is a path list separator. 4221 */ 4222 int 4223 vim_ispathlistsep(c) 4224 int c; 4225 { 4226 #ifdef UNIX 4227 return (c == ':'); 4228 #else 4229 return (c == ';'); /* might not be rigth for every system... */ 4230 #endif 4231 } 4232 #endif 4233 4234 #if (defined(CASE_INSENSITIVE_FILENAME) && defined(BACKSLASH_IN_FILENAME)) \ 4235 || defined(PROTO) 4236 /* 4237 * Versions of fnamecmp() and fnamencmp() that handle '/' and '\' equally. 4238 */ 4239 int 4240 vim_fnamecmp(x, y) 4241 char_u *x, *y; 4242 { 4243 return vim_fnamencmp(x, y, MAXPATHL); 4244 } 4245 4246 int 4247 vim_fnamencmp(x, y, len) 4248 char_u *x, *y; 4249 size_t len; 4250 { 4251 while (len > 0 && *x && *y) 4252 { 4253 if (TOLOWER_LOC(*x) != TOLOWER_LOC(*y) 4254 && !(*x == '/' && *y == '\\') 4255 && !(*x == '\\' && *y == '/')) 4256 break; 4257 ++x; 4258 ++y; 4259 --len; 4260 } 4261 if (len == 0) 4262 return 0; 4263 return (*x - *y); 4264 } 4265 #endif 4266 4267 /* 4268 * Concatenate file names fname1 and fname2 into allocated memory. 4269 * Only add a '/' or '\\' when 'sep' is TRUE and it is neccesary. 4270 */ 4271 char_u * 4272 concat_fnames(fname1, fname2, sep) 4273 char_u *fname1; 4274 char_u *fname2; 4275 int sep; 4276 { 4277 char_u *dest; 4278 4279 dest = alloc((unsigned)(STRLEN(fname1) + STRLEN(fname2) + 3)); 4280 if (dest != NULL) 4281 { 4282 STRCPY(dest, fname1); 4283 if (sep) 4284 add_pathsep(dest); 4285 STRCAT(dest, fname2); 4286 } 4287 return dest; 4288 } 4289 4290 /* 4291 * Add a path separator to a file name, unless it already ends in a path 4292 * separator. 4293 */ 4294 void 4295 add_pathsep(p) 4296 char_u *p; 4297 { 4298 if (*p != NUL && !vim_ispathsep(*(p + STRLEN(p) - 1))) 4299 STRCAT(p, PATHSEPSTR); 4300 } 4301 4302 /* 4303 * FullName_save - Make an allocated copy of a full file name. 4304 * Returns NULL when out of memory. 4305 */ 4306 char_u * 4307 FullName_save(fname, force) 4308 char_u *fname; 4309 int force; /* force expansion, even when it already looks 4310 like a full path name */ 4311 { 4312 char_u *buf; 4313 char_u *new_fname = NULL; 4314 4315 if (fname == NULL) 4316 return NULL; 4317 4318 buf = alloc((unsigned)MAXPATHL); 4319 if (buf != NULL) 4320 { 4321 if (vim_FullName(fname, buf, MAXPATHL, force) != FAIL) 4322 new_fname = vim_strsave(buf); 4323 else 4324 new_fname = vim_strsave(fname); 4325 vim_free(buf); 4326 } 4327 return new_fname; 4328 } 4329 4330 #if defined(FEAT_CINDENT) || defined(FEAT_SYN_HL) 4331 4332 static char_u *skip_string __ARGS((char_u *p)); 4333 4334 /* 4335 * Find the start of a comment, not knowing if we are in a comment right now. 4336 * Search starts at w_cursor.lnum and goes backwards. 4337 */ 4338 pos_T * 4339 find_start_comment(ind_maxcomment) /* XXX */ 4340 int ind_maxcomment; 4341 { 4342 pos_T *pos; 4343 char_u *line; 4344 char_u *p; 4345 4346 if ((pos = findmatchlimit(NULL, '*', FM_BACKWARD, ind_maxcomment)) == NULL) 4347 return NULL; 4348 4349 /* 4350 * Check if the comment start we found is inside a string. 4351 */ 4352 line = ml_get(pos->lnum); 4353 for (p = line; *p && (unsigned)(p - line) < pos->col; ++p) 4354 p = skip_string(p); 4355 if ((unsigned)(p - line) > pos->col) 4356 return NULL; 4357 return pos; 4358 } 4359 4360 /* 4361 * Skip to the end of a "string" and a 'c' character. 4362 * If there is no string or character, return argument unmodified. 4363 */ 4364 static char_u * 4365 skip_string(p) 4366 char_u *p; 4367 { 4368 int i; 4369 4370 /* 4371 * We loop, because strings may be concatenated: "date""time". 4372 */ 4373 for ( ; ; ++p) 4374 { 4375 if (p[0] == '\'') /* 'c' or '\n' or '\000' */ 4376 { 4377 if (!p[1]) /* ' at end of line */ 4378 break; 4379 i = 2; 4380 if (p[1] == '\\') /* '\n' or '\000' */ 4381 { 4382 ++i; 4383 while (vim_isdigit(p[i - 1])) /* '\000' */ 4384 ++i; 4385 } 4386 if (p[i] == '\'') /* check for trailing ' */ 4387 { 4388 p += i; 4389 continue; 4390 } 4391 } 4392 else if (p[0] == '"') /* start of string */ 4393 { 4394 for (++p; p[0]; ++p) 4395 { 4396 if (p[0] == '\\' && p[1] != NUL) 4397 ++p; 4398 else if (p[0] == '"') /* end of string */ 4399 break; 4400 } 4401 if (p[0] == '"') 4402 continue; 4403 } 4404 break; /* no string found */ 4405 } 4406 if (!*p) 4407 --p; /* backup from NUL */ 4408 return p; 4409 } 4410 #endif /* FEAT_CINDENT || FEAT_SYN_HL */ 4411 4412 #if defined(FEAT_CINDENT) || defined(PROTO) 4413 4414 /* 4415 * Do C or expression indenting on the current line. 4416 */ 4417 void 4418 do_c_expr_indent() 4419 { 4420 # ifdef FEAT_EVAL 4421 if (*curbuf->b_p_inde != NUL) 4422 fixthisline(get_expr_indent); 4423 else 4424 # endif 4425 fixthisline(get_c_indent); 4426 } 4427 4428 /* 4429 * Functions for C-indenting. 4430 * Most of this originally comes from Eric Fischer. 4431 */ 4432 /* 4433 * Below "XXX" means that this function may unlock the current line. 4434 */ 4435 4436 static char_u *cin_skipcomment __ARGS((char_u *)); 4437 static int cin_nocode __ARGS((char_u *)); 4438 static pos_T *find_line_comment __ARGS((void)); 4439 static int cin_islabel_skip __ARGS((char_u **)); 4440 static int cin_isdefault __ARGS((char_u *)); 4441 static char_u *after_label __ARGS((char_u *l)); 4442 static int get_indent_nolabel __ARGS((linenr_T lnum)); 4443 static int skip_label __ARGS((linenr_T, char_u **pp, int ind_maxcomment)); 4444 static int cin_first_id_amount __ARGS((void)); 4445 static int cin_get_equal_amount __ARGS((linenr_T lnum)); 4446 static int cin_ispreproc __ARGS((char_u *)); 4447 static int cin_ispreproc_cont __ARGS((char_u **pp, linenr_T *lnump)); 4448 static int cin_iscomment __ARGS((char_u *)); 4449 static int cin_islinecomment __ARGS((char_u *)); 4450 static int cin_isterminated __ARGS((char_u *, int, int)); 4451 static int cin_isinit __ARGS((void)); 4452 static int cin_isfuncdecl __ARGS((char_u **, linenr_T)); 4453 static int cin_isif __ARGS((char_u *)); 4454 static int cin_iselse __ARGS((char_u *)); 4455 static int cin_isdo __ARGS((char_u *)); 4456 static int cin_iswhileofdo __ARGS((char_u *, linenr_T, int)); 4457 static int cin_isbreak __ARGS((char_u *)); 4458 static int cin_is_cpp_baseclass __ARGS((char_u *line, colnr_T *col)); 4459 static int cin_ends_in __ARGS((char_u *, char_u *, char_u *)); 4460 static int cin_skip2pos __ARGS((pos_T *trypos)); 4461 static pos_T *find_start_brace __ARGS((int)); 4462 static pos_T *find_match_paren __ARGS((int, int)); 4463 static int corr_ind_maxparen __ARGS((int ind_maxparen, pos_T *startpos)); 4464 static int find_last_paren __ARGS((char_u *l, int start, int end)); 4465 static int find_match __ARGS((int lookfor, linenr_T ourscope, int ind_maxparen, int ind_maxcomment)); 4466 4467 /* 4468 * Skip over white space and C comments within the line. 4469 */ 4470 static char_u * 4471 cin_skipcomment(s) 4472 char_u *s; 4473 { 4474 while (*s) 4475 { 4476 s = skipwhite(s); 4477 if (*s != '/') 4478 break; 4479 ++s; 4480 if (*s == '/') /* slash-slash comment continues till eol */ 4481 { 4482 s += STRLEN(s); 4483 break; 4484 } 4485 if (*s != '*') 4486 break; 4487 for (++s; *s; ++s) /* skip slash-star comment */ 4488 if (s[0] == '*' && s[1] == '/') 4489 { 4490 s += 2; 4491 break; 4492 } 4493 } 4494 return s; 4495 } 4496 4497 /* 4498 * Return TRUE if there there is no code at *s. White space and comments are 4499 * not considered code. 4500 */ 4501 static int 4502 cin_nocode(s) 4503 char_u *s; 4504 { 4505 return *cin_skipcomment(s) == NUL; 4506 } 4507 4508 /* 4509 * Check previous lines for a "//" line comment, skipping over blank lines. 4510 */ 4511 static pos_T * 4512 find_line_comment() /* XXX */ 4513 { 4514 static pos_T pos; 4515 char_u *line; 4516 char_u *p; 4517 4518 pos = curwin->w_cursor; 4519 while (--pos.lnum > 0) 4520 { 4521 line = ml_get(pos.lnum); 4522 p = skipwhite(line); 4523 if (cin_islinecomment(p)) 4524 { 4525 pos.col = (int)(p - line); 4526 return &pos; 4527 } 4528 if (*p != NUL) 4529 break; 4530 } 4531 return NULL; 4532 } 4533 4534 /* 4535 * Check if string matches "label:"; move to character after ':' if true. 4536 */ 4537 static int 4538 cin_islabel_skip(s) 4539 char_u **s; 4540 { 4541 if (!vim_isIDc(**s)) /* need at least one ID character */ 4542 return FALSE; 4543 4544 while (vim_isIDc(**s)) 4545 (*s)++; 4546 4547 *s = cin_skipcomment(*s); 4548 4549 /* "::" is not a label, it's C++ */ 4550 return (**s == ':' && *++*s != ':'); 4551 } 4552 4553 /* 4554 * Recognize a label: "label:". 4555 * Note: curwin->w_cursor must be where we are looking for the label. 4556 */ 4557 int 4558 cin_islabel(ind_maxcomment) /* XXX */ 4559 int ind_maxcomment; 4560 { 4561 char_u *s; 4562 4563 s = cin_skipcomment(ml_get_curline()); 4564 4565 /* 4566 * Exclude "default" from labels, since it should be indented 4567 * like a switch label. Same for C++ scope declarations. 4568 */ 4569 if (cin_isdefault(s)) 4570 return FALSE; 4571 if (cin_isscopedecl(s)) 4572 return FALSE; 4573 4574 if (cin_islabel_skip(&s)) 4575 { 4576 /* 4577 * Only accept a label if the previous line is terminated or is a case 4578 * label. 4579 */ 4580 pos_T cursor_save; 4581 pos_T *trypos; 4582 char_u *line; 4583 4584 cursor_save = curwin->w_cursor; 4585 while (curwin->w_cursor.lnum > 1) 4586 { 4587 --curwin->w_cursor.lnum; 4588 4589 /* 4590 * If we're in a comment now, skip to the start of the comment. 4591 */ 4592 curwin->w_cursor.col = 0; 4593 if ((trypos = find_start_comment(ind_maxcomment)) != NULL) /* XXX */ 4594 curwin->w_cursor = *trypos; 4595 4596 line = ml_get_curline(); 4597 if (cin_ispreproc(line)) /* ignore #defines, #if, etc. */ 4598 continue; 4599 if (*(line = cin_skipcomment(line)) == NUL) 4600 continue; 4601 4602 curwin->w_cursor = cursor_save; 4603 if (cin_isterminated(line, TRUE, FALSE) 4604 || cin_isscopedecl(line) 4605 || cin_iscase(line) 4606 || (cin_islabel_skip(&line) && cin_nocode(line))) 4607 return TRUE; 4608 return FALSE; 4609 } 4610 curwin->w_cursor = cursor_save; 4611 return TRUE; /* label at start of file??? */ 4612 } 4613 return FALSE; 4614 } 4615 4616 /* 4617 * Recognize structure initialization and enumerations. 4618 * Q&D-Implementation: 4619 * check for "=" at end or "[typedef] enum" at beginning of line. 4620 */ 4621 static int 4622 cin_isinit(void) 4623 { 4624 char_u *s; 4625 4626 s = cin_skipcomment(ml_get_curline()); 4627 4628 if (STRNCMP(s, "typedef", 7) == 0 && !vim_isIDc(s[7])) 4629 s = cin_skipcomment(s + 7); 4630 4631 if (STRNCMP(s, "enum", 4) == 0 && !vim_isIDc(s[4])) 4632 return TRUE; 4633 4634 if (cin_ends_in(s, (char_u *)"=", (char_u *)"{")) 4635 return TRUE; 4636 4637 return FALSE; 4638 } 4639 4640 /* 4641 * Recognize a switch label: "case .*:" or "default:". 4642 */ 4643 int 4644 cin_iscase(s) 4645 char_u *s; 4646 { 4647 s = cin_skipcomment(s); 4648 if (STRNCMP(s, "case", 4) == 0 && !vim_isIDc(s[4])) 4649 { 4650 for (s += 4; *s; ++s) 4651 { 4652 s = cin_skipcomment(s); 4653 if (*s == ':') 4654 { 4655 if (s[1] == ':') /* skip over "::" for C++ */ 4656 ++s; 4657 else 4658 return TRUE; 4659 } 4660 if (*s == '\'' && s[1] && s[2] == '\'') 4661 s += 2; /* skip over '.' */ 4662 else if (*s == '/' && (s[1] == '*' || s[1] == '/')) 4663 return FALSE; /* stop at comment */ 4664 else if (*s == '"') 4665 return FALSE; /* stop at string */ 4666 } 4667 return FALSE; 4668 } 4669 4670 if (cin_isdefault(s)) 4671 return TRUE; 4672 return FALSE; 4673 } 4674 4675 /* 4676 * Recognize a "default" switch label. 4677 */ 4678 static int 4679 cin_isdefault(s) 4680 char_u *s; 4681 { 4682 return (STRNCMP(s, "default", 7) == 0 4683 && *(s = cin_skipcomment(s + 7)) == ':' 4684 && s[1] != ':'); 4685 } 4686 4687 /* 4688 * Recognize a "public/private/proctected" scope declaration label. 4689 */ 4690 int 4691 cin_isscopedecl(s) 4692 char_u *s; 4693 { 4694 int i; 4695 4696 s = cin_skipcomment(s); 4697 if (STRNCMP(s, "public", 6) == 0) 4698 i = 6; 4699 else if (STRNCMP(s, "protected", 9) == 0) 4700 i = 9; 4701 else if (STRNCMP(s, "private", 7) == 0) 4702 i = 7; 4703 else 4704 return FALSE; 4705 return (*(s = cin_skipcomment(s + i)) == ':' && s[1] != ':'); 4706 } 4707 4708 /* 4709 * Return a pointer to the first non-empty non-comment character after a ':'. 4710 * Return NULL if not found. 4711 * case 234: a = b; 4712 * ^ 4713 */ 4714 static char_u * 4715 after_label(l) 4716 char_u *l; 4717 { 4718 for ( ; *l; ++l) 4719 { 4720 if (*l == ':') 4721 { 4722 if (l[1] == ':') /* skip over "::" for C++ */ 4723 ++l; 4724 else if (!cin_iscase(l + 1)) 4725 break; 4726 } 4727 else if (*l == '\'' && l[1] && l[2] == '\'') 4728 l += 2; /* skip over 'x' */ 4729 } 4730 if (*l == NUL) 4731 return NULL; 4732 l = cin_skipcomment(l + 1); 4733 if (*l == NUL) 4734 return NULL; 4735 return l; 4736 } 4737 4738 /* 4739 * Get indent of line "lnum", skipping a label. 4740 * Return 0 if there is nothing after the label. 4741 */ 4742 static int 4743 get_indent_nolabel(lnum) /* XXX */ 4744 linenr_T lnum; 4745 { 4746 char_u *l; 4747 pos_T fp; 4748 colnr_T col; 4749 char_u *p; 4750 4751 l = ml_get(lnum); 4752 p = after_label(l); 4753 if (p == NULL) 4754 return 0; 4755 4756 fp.col = (colnr_T)(p - l); 4757 fp.lnum = lnum; 4758 getvcol(curwin, &fp, &col, NULL, NULL); 4759 return (int)col; 4760 } 4761 4762 /* 4763 * Find indent for line "lnum", ignoring any case or jump label. 4764 * Also return a pointer to the text (after the label). 4765 * label: if (asdf && asdfasdf) 4766 * ^ 4767 */ 4768 static int 4769 skip_label(lnum, pp, ind_maxcomment) 4770 linenr_T lnum; 4771 char_u **pp; 4772 int ind_maxcomment; 4773 { 4774 char_u *l; 4775 int amount; 4776 pos_T cursor_save; 4777 4778 cursor_save = curwin->w_cursor; 4779 curwin->w_cursor.lnum = lnum; 4780 l = ml_get_curline(); 4781 /* XXX */ 4782 if (cin_iscase(l) || cin_isscopedecl(l) || cin_islabel(ind_maxcomment)) 4783 { 4784 amount = get_indent_nolabel(lnum); 4785 l = after_label(ml_get_curline()); 4786 if (l == NULL) /* just in case */ 4787 l = ml_get_curline(); 4788 } 4789 else 4790 { 4791 amount = get_indent(); 4792 l = ml_get_curline(); 4793 } 4794 *pp = l; 4795 4796 curwin->w_cursor = cursor_save; 4797 return amount; 4798 } 4799 4800 /* 4801 * Return the indent of the first variable name after a type in a declaration. 4802 * int a, indent of "a" 4803 * static struct foo b, indent of "b" 4804 * enum bla c, indent of "c" 4805 * Returns zero when it doesn't look like a declaration. 4806 */ 4807 static int 4808 cin_first_id_amount() 4809 { 4810 char_u *line, *p, *s; 4811 int len; 4812 pos_T fp; 4813 colnr_T col; 4814 4815 line = ml_get_curline(); 4816 p = skipwhite(line); 4817 len = skiptowhite(p) - p; 4818 if (len == 6 && STRNCMP(p, "static", 6) == 0) 4819 { 4820 p = skipwhite(p + 6); 4821 len = skiptowhite(p) - p; 4822 } 4823 if (len == 6 && STRNCMP(p, "struct", 6) == 0) 4824 p = skipwhite(p + 6); 4825 else if (len == 4 && STRNCMP(p, "enum", 4) == 0) 4826 p = skipwhite(p + 4); 4827 else if ((len == 8 && STRNCMP(p, "unsigned", 8) == 0) 4828 || (len == 6 && STRNCMP(p, "signed", 6) == 0)) 4829 { 4830 s = skipwhite(p + len); 4831 if ((STRNCMP(s, "int", 3) == 0 && vim_iswhite(s[3])) 4832 || (STRNCMP(s, "long", 4) == 0 && vim_iswhite(s[4])) 4833 || (STRNCMP(s, "short", 5) == 0 && vim_iswhite(s[5])) 4834 || (STRNCMP(s, "char", 4) == 0 && vim_iswhite(s[4]))) 4835 p = s; 4836 } 4837 for (len = 0; vim_isIDc(p[len]); ++len) 4838 ; 4839 if (len == 0 || !vim_iswhite(p[len]) || cin_nocode(p)) 4840 return 0; 4841 4842 p = skipwhite(p + len); 4843 fp.lnum = curwin->w_cursor.lnum; 4844 fp.col = (colnr_T)(p - line); 4845 getvcol(curwin, &fp, &col, NULL, NULL); 4846 return (int)col; 4847 } 4848 4849 /* 4850 * Return the indent of the first non-blank after an equal sign. 4851 * char *foo = "here"; 4852 * Return zero if no (useful) equal sign found. 4853 * Return -1 if the line above "lnum" ends in a backslash. 4854 * foo = "asdf\ 4855 * asdf\ 4856 * here"; 4857 */ 4858 static int 4859 cin_get_equal_amount(lnum) 4860 linenr_T lnum; 4861 { 4862 char_u *line; 4863 char_u *s; 4864 colnr_T col; 4865 pos_T fp; 4866 4867 if (lnum > 1) 4868 { 4869 line = ml_get(lnum - 1); 4870 if (*line != NUL && line[STRLEN(line) - 1] == '\\') 4871 return -1; 4872 } 4873 4874 line = s = ml_get(lnum); 4875 while (*s != NUL && vim_strchr((char_u *)"=;{}\"'", *s) == NULL) 4876 { 4877 if (cin_iscomment(s)) /* ignore comments */ 4878 s = cin_skipcomment(s); 4879 else 4880 ++s; 4881 } 4882 if (*s != '=') 4883 return 0; 4884 4885 s = skipwhite(s + 1); 4886 if (cin_nocode(s)) 4887 return 0; 4888 4889 if (*s == '"') /* nice alignment for continued strings */ 4890 ++s; 4891 4892 fp.lnum = lnum; 4893 fp.col = (colnr_T)(s - line); 4894 getvcol(curwin, &fp, &col, NULL, NULL); 4895 return (int)col; 4896 } 4897 4898 /* 4899 * Recognize a preprocessor statement: Any line that starts with '#'. 4900 */ 4901 static int 4902 cin_ispreproc(s) 4903 char_u *s; 4904 { 4905 s = skipwhite(s); 4906 if (*s == '#') 4907 return TRUE; 4908 return FALSE; 4909 } 4910 4911 /* 4912 * Return TRUE if line "*pp" at "*lnump" is a preprocessor statement or a 4913 * continuation line of a preprocessor statement. Decrease "*lnump" to the 4914 * start and return the line in "*pp". 4915 */ 4916 static int 4917 cin_ispreproc_cont(pp, lnump) 4918 char_u **pp; 4919 linenr_T *lnump; 4920 { 4921 char_u *line = *pp; 4922 linenr_T lnum = *lnump; 4923 int retval = FALSE; 4924 4925 while (1) 4926 { 4927 if (cin_ispreproc(line)) 4928 { 4929 retval = TRUE; 4930 *lnump = lnum; 4931 break; 4932 } 4933 if (lnum == 1) 4934 break; 4935 line = ml_get(--lnum); 4936 if (*line == NUL || line[STRLEN(line) - 1] != '\\') 4937 break; 4938 } 4939 4940 if (lnum != *lnump) 4941 *pp = ml_get(*lnump); 4942 return retval; 4943 } 4944 4945 /* 4946 * Recognize the start of a C or C++ comment. 4947 */ 4948 static int 4949 cin_iscomment(p) 4950 char_u *p; 4951 { 4952 return (p[0] == '/' && (p[1] == '*' || p[1] == '/')); 4953 } 4954 4955 /* 4956 * Recognize the start of a "//" comment. 4957 */ 4958 static int 4959 cin_islinecomment(p) 4960 char_u *p; 4961 { 4962 return (p[0] == '/' && p[1] == '/'); 4963 } 4964 4965 /* 4966 * Recognize a line that starts with '{' or '}', or ends with ';', '{' or '}'. 4967 * Don't consider "} else" a terminated line. 4968 * Return the character terminating the line (ending char's have precedence if 4969 * both apply in order to determine initializations). 4970 */ 4971 static int 4972 cin_isterminated(s, incl_open, incl_comma) 4973 char_u *s; 4974 int incl_open; /* include '{' at the end as terminator */ 4975 int incl_comma; /* recognize a trailing comma */ 4976 { 4977 char_u found_start = 0; 4978 4979 s = cin_skipcomment(s); 4980 4981 if (*s == '{' || (*s == '}' && !cin_iselse(s))) 4982 found_start = *s; 4983 4984 while (*s) 4985 { 4986 /* skip over comments, "" strings and 'c'haracters */ 4987 s = skip_string(cin_skipcomment(s)); 4988 if ((*s == ';' || (incl_open && *s == '{') || *s == '}' 4989 || (incl_comma && *s == ',')) 4990 && cin_nocode(s + 1)) 4991 return *s; 4992 4993 if (*s) 4994 s++; 4995 } 4996 return found_start; 4997 } 4998 4999 /* 5000 * Recognize the basic picture of a function declaration -- it needs to 5001 * have an open paren somewhere and a close paren at the end of the line and 5002 * no semicolons anywhere. 5003 * When a line ends in a comma we continue looking in the next line. 5004 * "sp" points to a string with the line. When looking at other lines it must 5005 * be restored to the line. When it's NULL fetch lines here. 5006 * "lnum" is where we start looking. 5007 */ 5008 static int 5009 cin_isfuncdecl(sp, first_lnum) 5010 char_u **sp; 5011 linenr_T first_lnum; 5012 { 5013 char_u *s; 5014 linenr_T lnum = first_lnum; 5015 int retval = FALSE; 5016 5017 if (sp == NULL) 5018 s = ml_get(lnum); 5019 else 5020 s = *sp; 5021 5022 while (*s && *s != '(' && *s != ';' && *s != '\'' && *s != '"') 5023 { 5024 if (cin_iscomment(s)) /* ignore comments */ 5025 s = cin_skipcomment(s); 5026 else 5027 ++s; 5028 } 5029 if (*s != '(') 5030 return FALSE; /* ';', ' or " before any () or no '(' */ 5031 5032 while (*s && *s != ';' && *s != '\'' && *s != '"') 5033 { 5034 if (*s == ')' && cin_nocode(s + 1)) 5035 { 5036 /* ')' at the end: may have found a match 5037 * Check for he previous line not to end in a backslash: 5038 * #if defined(x) && \ 5039 * defined(y) 5040 */ 5041 lnum = first_lnum - 1; 5042 s = ml_get(lnum); 5043 if (*s == NUL || s[STRLEN(s) - 1] != '\\') 5044 retval = TRUE; 5045 goto done; 5046 } 5047 if (*s == ',' && cin_nocode(s + 1)) 5048 { 5049 /* ',' at the end: continue looking in the next line */ 5050 if (lnum >= curbuf->b_ml.ml_line_count) 5051 break; 5052 5053 s = ml_get(++lnum); 5054 } 5055 else if (cin_iscomment(s)) /* ignore comments */ 5056 s = cin_skipcomment(s); 5057 else 5058 ++s; 5059 } 5060 5061 done: 5062 if (lnum != first_lnum && sp != NULL) 5063 *sp = ml_get(first_lnum); 5064 5065 return retval; 5066 } 5067 5068 static int 5069 cin_isif(p) 5070 char_u *p; 5071 { 5072 return (STRNCMP(p, "if", 2) == 0 && !vim_isIDc(p[2])); 5073 } 5074 5075 static int 5076 cin_iselse(p) 5077 char_u *p; 5078 { 5079 if (*p == '}') /* accept "} else" */ 5080 p = cin_skipcomment(p + 1); 5081 return (STRNCMP(p, "else", 4) == 0 && !vim_isIDc(p[4])); 5082 } 5083 5084 static int 5085 cin_isdo(p) 5086 char_u *p; 5087 { 5088 return (STRNCMP(p, "do", 2) == 0 && !vim_isIDc(p[2])); 5089 } 5090 5091 /* 5092 * Check if this is a "while" that should have a matching "do". 5093 * We only accept a "while (condition) ;", with only white space between the 5094 * ')' and ';'. The condition may be spread over several lines. 5095 */ 5096 static int 5097 cin_iswhileofdo(p, lnum, ind_maxparen) /* XXX */ 5098 char_u *p; 5099 linenr_T lnum; 5100 int ind_maxparen; 5101 { 5102 pos_T cursor_save; 5103 pos_T *trypos; 5104 int retval = FALSE; 5105 5106 p = cin_skipcomment(p); 5107 if (*p == '}') /* accept "} while (cond);" */ 5108 p = cin_skipcomment(p + 1); 5109 if (STRNCMP(p, "while", 5) == 0 && !vim_isIDc(p[5])) 5110 { 5111 cursor_save = curwin->w_cursor; 5112 curwin->w_cursor.lnum = lnum; 5113 curwin->w_cursor.col = 0; 5114 p = ml_get_curline(); 5115 while (*p && *p != 'w') /* skip any '}', until the 'w' of the "while" */ 5116 { 5117 ++p; 5118 ++curwin->w_cursor.col; 5119 } 5120 if ((trypos = findmatchlimit(NULL, 0, 0, ind_maxparen)) != NULL 5121 && *cin_skipcomment(ml_get_pos(trypos) + 1) == ';') 5122 retval = TRUE; 5123 curwin->w_cursor = cursor_save; 5124 } 5125 return retval; 5126 } 5127 5128 static int 5129 cin_isbreak(p) 5130 char_u *p; 5131 { 5132 return (STRNCMP(p, "break", 5) == 0 && !vim_isIDc(p[5])); 5133 } 5134 5135 /* Find the position of a C++ base-class declaration or 5136 * constructor-initialization. eg: 5137 * 5138 * class MyClass : 5139 * baseClass <-- here 5140 * class MyClass : public baseClass, 5141 * anotherBaseClass <-- here (should probably lineup ??) 5142 * MyClass::MyClass(...) : 5143 * baseClass(...) <-- here (constructor-initialization) 5144 */ 5145 static int 5146 cin_is_cpp_baseclass(line, col) 5147 char_u *line; 5148 colnr_T *col; 5149 { 5150 char_u *s; 5151 int class_or_struct, lookfor_ctor_init, cpp_base_class; 5152 5153 *col = 0; 5154 5155 s = skipwhite(line); 5156 if (*s == '#') /* skip #define FOO x ? (x) : x */ 5157 return FALSE; 5158 s = cin_skipcomment(s); 5159 if (*s == NUL) 5160 return FALSE; 5161 5162 cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE; 5163 5164 while(*s != NUL) 5165 { 5166 if (s[0] == ':') 5167 { 5168 if (s[1] == ':') 5169 { 5170 /* skip double colon. It can't be a constructor 5171 * initialization any more */ 5172 lookfor_ctor_init = FALSE; 5173 s = cin_skipcomment(s + 2); 5174 } 5175 else if (lookfor_ctor_init || class_or_struct) 5176 { 5177 /* we have something found, that looks like the start of 5178 * cpp-base-class-declaration or contructor-initialization */ 5179 cpp_base_class = TRUE; 5180 lookfor_ctor_init = class_or_struct = FALSE; 5181 *col = 0; 5182 s = cin_skipcomment(s + 1); 5183 } 5184 else 5185 s = cin_skipcomment(s + 1); 5186 } 5187 else if ((STRNCMP(s, "class", 5) == 0 && !vim_isIDc(s[5])) 5188 || (STRNCMP(s, "struct", 6) == 0 && !vim_isIDc(s[6]))) 5189 { 5190 class_or_struct = TRUE; 5191 lookfor_ctor_init = FALSE; 5192 5193 if (*s == 'c') 5194 s = cin_skipcomment(s + 5); 5195 else 5196 s = cin_skipcomment(s + 6); 5197 } 5198 else 5199 { 5200 if (s[0] == '{' || s[0] == '}' || s[0] == ';') 5201 { 5202 cpp_base_class = lookfor_ctor_init = class_or_struct = FALSE; 5203 } 5204 else if (s[0] == ')') 5205 { 5206 /* Constructor-initialization is assumed if we come across 5207 * something like "):" */ 5208 class_or_struct = FALSE; 5209 lookfor_ctor_init = TRUE; 5210 } 5211 else if (!vim_isIDc(s[0])) 5212 { 5213 /* if it is not an identifier, we are wrong */ 5214 class_or_struct = FALSE; 5215 lookfor_ctor_init = FALSE; 5216 } 5217 else if (*col == 0) 5218 { 5219 /* it can't be a constructor-initialization any more */ 5220 lookfor_ctor_init = FALSE; 5221 5222 /* the first statement starts here: lineup with this one... */ 5223 if (cpp_base_class && *col == 0) 5224 *col = (colnr_T)(s - line); 5225 } 5226 5227 s = cin_skipcomment(s + 1); 5228 } 5229 } 5230 5231 return cpp_base_class; 5232 } 5233 5234 /* 5235 * Return TRUE if string "s" ends with the string "find", possibly followed by 5236 * white space and comments. Skip strings and comments. 5237 * Ignore "ignore" after "find" if it's not NULL. 5238 */ 5239 static int 5240 cin_ends_in(s, find, ignore) 5241 char_u *s; 5242 char_u *find; 5243 char_u *ignore; 5244 { 5245 char_u *p = s; 5246 char_u *r; 5247 int len = (int)STRLEN(find); 5248 5249 while (*p != NUL) 5250 { 5251 p = cin_skipcomment(p); 5252 if (STRNCMP(p, find, len) == 0) 5253 { 5254 r = skipwhite(p + len); 5255 if (ignore != NULL && STRNCMP(r, ignore, STRLEN(ignore)) == 0) 5256 r = skipwhite(r + STRLEN(ignore)); 5257 if (cin_nocode(r)) 5258 return TRUE; 5259 } 5260 if (*p != NUL) 5261 ++p; 5262 } 5263 return FALSE; 5264 } 5265 5266 /* 5267 * Skip strings, chars and comments until at or past "trypos". 5268 * Return the column found. 5269 */ 5270 static int 5271 cin_skip2pos(trypos) 5272 pos_T *trypos; 5273 { 5274 char_u *line; 5275 char_u *p; 5276 5277 p = line = ml_get(trypos->lnum); 5278 while (*p && (colnr_T)(p - line) < trypos->col) 5279 { 5280 if (cin_iscomment(p)) 5281 p = cin_skipcomment(p); 5282 else 5283 { 5284 p = skip_string(p); 5285 ++p; 5286 } 5287 } 5288 return (int)(p - line); 5289 } 5290 5291 /* 5292 * Find the '{' at the start of the block we are in. 5293 * Return NULL if no match found. 5294 * Ignore a '{' that is in a comment, makes indenting the next three lines 5295 * work. */ 5296 /* foo() */ 5297 /* { */ 5298 /* } */ 5299 5300 static pos_T * 5301 find_start_brace(ind_maxcomment) /* XXX */ 5302 int ind_maxcomment; 5303 { 5304 pos_T cursor_save; 5305 pos_T *trypos; 5306 pos_T *pos; 5307 static pos_T pos_copy; 5308 5309 cursor_save = curwin->w_cursor; 5310 while ((trypos = findmatchlimit(NULL, '{', FM_BLOCKSTOP, 0)) != NULL) 5311 { 5312 pos_copy = *trypos; /* copy pos_T, next findmatch will change it */ 5313 trypos = &pos_copy; 5314 curwin->w_cursor = *trypos; 5315 pos = NULL; 5316 /* ignore the { if it's in a // comment */ 5317 if ((colnr_T)cin_skip2pos(trypos) == trypos->col 5318 && (pos = find_start_comment(ind_maxcomment)) == NULL) /* XXX */ 5319 break; 5320 if (pos != NULL) 5321 curwin->w_cursor.lnum = pos->lnum; 5322 } 5323 curwin->w_cursor = cursor_save; 5324 return trypos; 5325 } 5326 5327 /* 5328 * Find the matching '(', failing if it is in a comment. 5329 * Return NULL of no match found. 5330 */ 5331 static pos_T * 5332 find_match_paren(ind_maxparen, ind_maxcomment) /* XXX */ 5333 int ind_maxparen; 5334 int ind_maxcomment; 5335 { 5336 pos_T cursor_save; 5337 pos_T *trypos; 5338 static pos_T pos_copy; 5339 5340 cursor_save = curwin->w_cursor; 5341 if ((trypos = findmatchlimit(NULL, '(', 0, ind_maxparen)) != NULL) 5342 { 5343 /* check if the ( is in a // comment */ 5344 if ((colnr_T)cin_skip2pos(trypos) > trypos->col) 5345 trypos = NULL; 5346 else 5347 { 5348 pos_copy = *trypos; /* copy trypos, findmatch will change it */ 5349 trypos = &pos_copy; 5350 curwin->w_cursor = *trypos; 5351 if (find_start_comment(ind_maxcomment) != NULL) /* XXX */ 5352 trypos = NULL; 5353 } 5354 } 5355 curwin->w_cursor = cursor_save; 5356 return trypos; 5357 } 5358 5359 /* 5360 * Return ind_maxparen corrected for the difference in line number between the 5361 * cursor position and "startpos". This makes sure that searching for a 5362 * matching paren above the cursor line doesn't find a match because of 5363 * looking a few lines further. 5364 */ 5365 static int 5366 corr_ind_maxparen(ind_maxparen, startpos) 5367 int ind_maxparen; 5368 pos_T *startpos; 5369 { 5370 long n = (long)startpos->lnum - (long)curwin->w_cursor.lnum; 5371 5372 if (n > 0 && n < ind_maxparen / 2) 5373 return ind_maxparen - (int)n; 5374 return ind_maxparen; 5375 } 5376 5377 /* 5378 * Set w_cursor.col to the column number of the last unmatched ')' or '{' in 5379 * line "l". 5380 */ 5381 static int 5382 find_last_paren(l, start, end) 5383 char_u *l; 5384 int start, end; 5385 { 5386 int i; 5387 int retval = FALSE; 5388 int open_count = 0; 5389 5390 curwin->w_cursor.col = 0; /* default is start of line */ 5391 5392 for (i = 0; l[i]; i++) 5393 { 5394 i = (int)(cin_skipcomment(l + i) - l); /* ignore parens in comments */ 5395 i = (int)(skip_string(l + i) - l); /* ignore parens in quotes */ 5396 if (l[i] == start) 5397 ++open_count; 5398 else if (l[i] == end) 5399 { 5400 if (open_count > 0) 5401 --open_count; 5402 else 5403 { 5404 curwin->w_cursor.col = i; 5405 retval = TRUE; 5406 } 5407 } 5408 } 5409 return retval; 5410 } 5411 5412 int 5413 get_c_indent() 5414 { 5415 /* 5416 * spaces from a block's opening brace the prevailing indent for that 5417 * block should be 5418 */ 5419 int ind_level = curbuf->b_p_sw; 5420 5421 /* 5422 * spaces from the edge of the line an open brace that's at the end of a 5423 * line is imagined to be. 5424 */ 5425 int ind_open_imag = 0; 5426 5427 /* 5428 * spaces from the prevailing indent for a line that is not precededof by 5429 * an opening brace. 5430 */ 5431 int ind_no_brace = 0; 5432 5433 /* 5434 * column where the first { of a function should be located } 5435 */ 5436 int ind_first_open = 0; 5437 5438 /* 5439 * spaces from the prevailing indent a leftmost open brace should be 5440 * located 5441 */ 5442 int ind_open_extra = 0; 5443 5444 /* 5445 * spaces from the matching open brace (real location for one at the left 5446 * edge; imaginary location from one that ends a line) the matching close 5447 * brace should be located 5448 */ 5449 int ind_close_extra = 0; 5450 5451 /* 5452 * spaces from the edge of the line an open brace sitting in the leftmost 5453 * column is imagined to be 5454 */ 5455 int ind_open_left_imag = 0; 5456 5457 /* 5458 * spaces from the switch() indent a "case xx" label should be located 5459 */ 5460 int ind_case = curbuf->b_p_sw; 5461 5462 /* 5463 * spaces from the "case xx:" code after a switch() should be located 5464 */ 5465 int ind_case_code = curbuf->b_p_sw; 5466 5467 /* 5468 * lineup break at end of case in switch() with case label 5469 */ 5470 int ind_case_break = 0; 5471 5472 /* 5473 * spaces from the class declaration indent a scope declaration label 5474 * should be located 5475 */ 5476 int ind_scopedecl = curbuf->b_p_sw; 5477 5478 /* 5479 * spaces from the scope declaration label code should be located 5480 */ 5481 int ind_scopedecl_code = curbuf->b_p_sw; 5482 5483 /* 5484 * amount K&R-style parameters should be indented 5485 */ 5486 int ind_param = curbuf->b_p_sw; 5487 5488 /* 5489 * amount a function type spec should be indented 5490 */ 5491 int ind_func_type = curbuf->b_p_sw; 5492 5493 /* 5494 * amount a cpp base class declaration or constructor initialization 5495 * should be indented 5496 */ 5497 int ind_cpp_baseclass = curbuf->b_p_sw; 5498 5499 /* 5500 * additional spaces beyond the prevailing indent a continuation line 5501 * should be located 5502 */ 5503 int ind_continuation = curbuf->b_p_sw; 5504 5505 /* 5506 * spaces from the indent of the line with an unclosed parentheses 5507 */ 5508 int ind_unclosed = curbuf->b_p_sw * 2; 5509 5510 /* 5511 * spaces from the indent of the line with an unclosed parentheses, which 5512 * itself is also unclosed 5513 */ 5514 int ind_unclosed2 = curbuf->b_p_sw; 5515 5516 /* 5517 * suppress ignoring spaces from the indent of a line starting with an 5518 * unclosed parentheses. 5519 */ 5520 int ind_unclosed_noignore = 0; 5521 5522 /* 5523 * If the opening paren is the last nonwhite character on the line, and 5524 * ind_unclosed_wrapped is nonzero, use this indent relative to the outer 5525 * context (for very long lines). 5526 */ 5527 int ind_unclosed_wrapped = 0; 5528 5529 /* 5530 * suppress ignoring white space when lining up with the character after 5531 * an unclosed parentheses. 5532 */ 5533 int ind_unclosed_whiteok = 0; 5534 5535 /* 5536 * indent a closing parentheses under the line start of the matching 5537 * opening parentheses. 5538 */ 5539 int ind_matching_paren = 0; 5540 5541 /* 5542 * Extra indent for comments. 5543 */ 5544 int ind_comment = 0; 5545 5546 /* 5547 * spaces from the comment opener when there is nothing after it. 5548 */ 5549 int ind_in_comment = 3; 5550 5551 /* 5552 * boolean: if non-zero, use ind_in_comment even if there is something 5553 * after the comment opener. 5554 */ 5555 int ind_in_comment2 = 0; 5556 5557 /* 5558 * max lines to search for an open paren 5559 */ 5560 int ind_maxparen = 20; 5561 5562 /* 5563 * max lines to search for an open comment 5564 */ 5565 int ind_maxcomment = 70; 5566 5567 /* 5568 * handle braces for java code 5569 */ 5570 int ind_java = 0; 5571 5572 /* 5573 * handle blocked cases correctly 5574 */ 5575 int ind_keep_case_label = 0; 5576 5577 pos_T cur_curpos; 5578 int amount; 5579 int scope_amount; 5580 int cur_amount; 5581 colnr_T col; 5582 char_u *theline; 5583 char_u *linecopy; 5584 pos_T *trypos; 5585 pos_T *tryposBrace = NULL; 5586 pos_T our_paren_pos; 5587 char_u *start; 5588 int start_brace; 5589 #define BRACE_IN_COL0 1 /* '{' is in comumn 0 */ 5590 #define BRACE_AT_START 2 /* '{' is at start of line */ 5591 #define BRACE_AT_END 3 /* '{' is at end of line */ 5592 linenr_T ourscope; 5593 char_u *l; 5594 char_u *look; 5595 char_u terminated; 5596 int lookfor; 5597 #define LOOKFOR_INITIAL 0 5598 #define LOOKFOR_IF 1 5599 #define LOOKFOR_DO 2 5600 #define LOOKFOR_CASE 3 5601 #define LOOKFOR_ANY 4 5602 #define LOOKFOR_TERM 5 5603 #define LOOKFOR_UNTERM 6 5604 #define LOOKFOR_SCOPEDECL 7 5605 #define LOOKFOR_NOBREAK 8 5606 #define LOOKFOR_CPP_BASECLASS 9 5607 #define LOOKFOR_ENUM_OR_INIT 10 5608 5609 int whilelevel; 5610 linenr_T lnum; 5611 char_u *options; 5612 int fraction = 0; /* init for GCC */ 5613 int divider; 5614 int n; 5615 int iscase; 5616 int lookfor_break; 5617 int cont_amount = 0; /* amount for continuation line */ 5618 5619 for (options = curbuf->b_p_cino; *options; ) 5620 { 5621 l = options++; 5622 if (*options == '-') 5623 ++options; 5624 n = getdigits(&options); 5625 divider = 0; 5626 if (*options == '.') /* ".5s" means a fraction */ 5627 { 5628 fraction = atol((char *)++options); 5629 while (VIM_ISDIGIT(*options)) 5630 { 5631 ++options; 5632 if (divider) 5633 divider *= 10; 5634 else 5635 divider = 10; 5636 } 5637 } 5638 if (*options == 's') /* "2s" means two times 'shiftwidth' */ 5639 { 5640 if (n == 0 && fraction == 0) 5641 n = curbuf->b_p_sw; /* just "s" is one 'shiftwidth' */ 5642 else 5643 { 5644 n *= curbuf->b_p_sw; 5645 if (divider) 5646 n += (curbuf->b_p_sw * fraction + divider / 2) / divider; 5647 } 5648 ++options; 5649 } 5650 if (l[1] == '-') 5651 n = -n; 5652 /* When adding an entry here, also update the default 'cinoptions' in 5653 * change.txt, and add explanation for it! */ 5654 switch (*l) 5655 { 5656 case '>': ind_level = n; break; 5657 case 'e': ind_open_imag = n; break; 5658 case 'n': ind_no_brace = n; break; 5659 case 'f': ind_first_open = n; break; 5660 case '{': ind_open_extra = n; break; 5661 case '}': ind_close_extra = n; break; 5662 case '^': ind_open_left_imag = n; break; 5663 case ':': ind_case = n; break; 5664 case '=': ind_case_code = n; break; 5665 case 'b': ind_case_break = n; break; 5666 case 'p': ind_param = n; break; 5667 case 't': ind_func_type = n; break; 5668 case '/': ind_comment = n; break; 5669 case 'c': ind_in_comment = n; break; 5670 case 'C': ind_in_comment2 = n; break; 5671 case 'i': ind_cpp_baseclass = n; break; 5672 case '+': ind_continuation = n; break; 5673 case '(': ind_unclosed = n; break; 5674 case 'u': ind_unclosed2 = n; break; 5675 case 'U': ind_unclosed_noignore = n; break; 5676 case 'W': ind_unclosed_wrapped = n; break; 5677 case 'w': ind_unclosed_whiteok = n; break; 5678 case 'm': ind_matching_paren = n; break; 5679 case ')': ind_maxparen = n; break; 5680 case '*': ind_maxcomment = n; break; 5681 case 'g': ind_scopedecl = n; break; 5682 case 'h': ind_scopedecl_code = n; break; 5683 case 'j': ind_java = n; break; 5684 case 'l': ind_keep_case_label = n; break; 5685 } 5686 } 5687 5688 /* remember where the cursor was when we started */ 5689 cur_curpos = curwin->w_cursor; 5690 5691 /* Get a copy of the current contents of the line. 5692 * This is required, because only the most recent line obtained with 5693 * ml_get is valid! */ 5694 linecopy = vim_strsave(ml_get(cur_curpos.lnum)); 5695 if (linecopy == NULL) 5696 return 0; 5697 5698 /* 5699 * In insert mode and the cursor is on a ')' truncate the line at the 5700 * cursor position. We don't want to line up with the matching '(' when 5701 * inserting new stuff. 5702 * For unknown reasons the cursor might be past the end of the line, thus 5703 * check for that. 5704 */ 5705 if ((State & INSERT) 5706 && curwin->w_cursor.col < STRLEN(linecopy) 5707 && linecopy[curwin->w_cursor.col] == ')') 5708 linecopy[curwin->w_cursor.col] = NUL; 5709 5710 theline = skipwhite(linecopy); 5711 5712 /* move the cursor to the start of the line */ 5713 5714 curwin->w_cursor.col = 0; 5715 5716 /* 5717 * #defines and so on always go at the left when included in 'cinkeys'. 5718 */ 5719 if (*theline == '#' && (*linecopy == '#' || in_cinkeys('#', ' ', TRUE))) 5720 { 5721 amount = 0; 5722 } 5723 5724 /* 5725 * Is it a non-case label? Then that goes at the left margin too. 5726 */ 5727 else if (cin_islabel(ind_maxcomment)) /* XXX */ 5728 { 5729 amount = 0; 5730 } 5731 5732 /* 5733 * If we're inside a "//" comment and there is a "//" comment in a 5734 * previous line, lineup with that one. 5735 */ 5736 else if (cin_islinecomment(theline) 5737 && (trypos = find_line_comment()) != NULL) /* XXX */ 5738 { 5739 /* find how indented the line beginning the comment is */ 5740 getvcol(curwin, trypos, &col, NULL, NULL); 5741 amount = col; 5742 } 5743 5744 /* 5745 * If we're inside a comment and not looking at the start of the 5746 * comment, try using the 'comments' option. 5747 */ 5748 else if (!cin_iscomment(theline) 5749 && (trypos = find_start_comment(ind_maxcomment)) != NULL) /* XXX */ 5750 { 5751 int lead_start_len = 2; 5752 int lead_middle_len = 1; 5753 char_u lead_start[COM_MAX_LEN]; /* start-comment string */ 5754 char_u lead_middle[COM_MAX_LEN]; /* middle-comment string */ 5755 char_u lead_end[COM_MAX_LEN]; /* end-comment string */ 5756 char_u *p; 5757 int start_align = 0; 5758 int start_off = 0; 5759 int done = FALSE; 5760 5761 /* find how indented the line beginning the comment is */ 5762 getvcol(curwin, trypos, &col, NULL, NULL); 5763 amount = col; 5764 5765 p = curbuf->b_p_com; 5766 while (*p != NUL) 5767 { 5768 int align = 0; 5769 int off = 0; 5770 int what = 0; 5771 5772 while (*p != NUL && *p != ':') 5773 { 5774 if (*p == COM_START || *p == COM_END || *p == COM_MIDDLE) 5775 what = *p++; 5776 else if (*p == COM_LEFT || *p == COM_RIGHT) 5777 align = *p++; 5778 else if (VIM_ISDIGIT(*p) || *p == '-') 5779 off = getdigits(&p); 5780 else 5781 ++p; 5782 } 5783 5784 if (*p == ':') 5785 ++p; 5786 (void)copy_option_part(&p, lead_end, COM_MAX_LEN, ","); 5787 if (what == COM_START) 5788 { 5789 STRCPY(lead_start, lead_end); 5790 lead_start_len = (int)STRLEN(lead_start); 5791 start_off = off; 5792 start_align = align; 5793 } 5794 else if (what == COM_MIDDLE) 5795 { 5796 STRCPY(lead_middle, lead_end); 5797 lead_middle_len = (int)STRLEN(lead_middle); 5798 } 5799 else if (what == COM_END) 5800 { 5801 /* If our line starts with the middle comment string, line it 5802 * up with the comment opener per the 'comments' option. */ 5803 if (STRNCMP(theline, lead_middle, lead_middle_len) == 0 5804 && STRNCMP(theline, lead_end, STRLEN(lead_end)) != 0) 5805 { 5806 done = TRUE; 5807 if (curwin->w_cursor.lnum > 1) 5808 { 5809 /* If the start comment string matches in the previous 5810 * line, use the indent of that line pluss offset. If 5811 * the middle comment string matches in the previous 5812 * line, use the indent of that line. XXX */ 5813 look = skipwhite(ml_get(curwin->w_cursor.lnum - 1)); 5814 if (STRNCMP(look, lead_start, lead_start_len) == 0) 5815 amount = get_indent_lnum(curwin->w_cursor.lnum - 1); 5816 else if (STRNCMP(look, lead_middle, 5817 lead_middle_len) == 0) 5818 { 5819 amount = get_indent_lnum(curwin->w_cursor.lnum - 1); 5820 break; 5821 } 5822 /* If the start comment string doesn't match with the 5823 * start of the comment, skip this entry. XXX */ 5824 else if (STRNCMP(ml_get(trypos->lnum) + trypos->col, 5825 lead_start, lead_start_len) != 0) 5826 continue; 5827 } 5828 if (start_off != 0) 5829 amount += start_off; 5830 else if (start_align == COM_RIGHT) 5831 amount += vim_strsize(lead_start) 5832 - vim_strsize(lead_middle); 5833 break; 5834 } 5835 5836 /* If our line starts with the end comment string, line it up 5837 * with the middle comment */ 5838 if (STRNCMP(theline, lead_middle, lead_middle_len) != 0 5839 && STRNCMP(theline, lead_end, STRLEN(lead_end)) == 0) 5840 { 5841 amount = get_indent_lnum(curwin->w_cursor.lnum - 1); 5842 /* XXX */ 5843 if (off != 0) 5844 amount += off; 5845 else if (align == COM_RIGHT) 5846 amount += vim_strsize(lead_start) 5847 - vim_strsize(lead_middle); 5848 done = TRUE; 5849 break; 5850 } 5851 } 5852 } 5853 5854 /* If our line starts with an asterisk, line up with the 5855 * asterisk in the comment opener; otherwise, line up 5856 * with the first character of the comment text. 5857 */ 5858 if (done) 5859 ; 5860 else if (theline[0] == '*') 5861 amount += 1; 5862 else 5863 { 5864 /* 5865 * If we are more than one line away from the comment opener, take 5866 * the indent of the previous non-empty line. If 'cino' has "CO" 5867 * and we are just below the comment opener and there are any 5868 * white characters after it line up with the text after it; 5869 * otherwise, add the amount specified by "c" in 'cino' 5870 */ 5871 amount = -1; 5872 for (lnum = cur_curpos.lnum - 1; lnum > trypos->lnum; --lnum) 5873 { 5874 if (linewhite(lnum)) /* skip blank lines */ 5875 continue; 5876 amount = get_indent_lnum(lnum); /* XXX */ 5877 break; 5878 } 5879 if (amount == -1) /* use the comment opener */ 5880 { 5881 if (!ind_in_comment2) 5882 { 5883 start = ml_get(trypos->lnum); 5884 look = start + trypos->col + 2; /* skip / and * */ 5885 if (*look != NUL) /* if something after it */ 5886 trypos->col = (colnr_T)(skipwhite(look) - start); 5887 } 5888 getvcol(curwin, trypos, &col, NULL, NULL); 5889 amount = col; 5890 if (ind_in_comment2 || *look == NUL) 5891 amount += ind_in_comment; 5892 } 5893 } 5894 } 5895 5896 /* 5897 * Are we inside parentheses or braces? 5898 */ /* XXX */ 5899 else if (((trypos = find_match_paren(ind_maxparen, ind_maxcomment)) != NULL 5900 && ind_java == 0) 5901 || (tryposBrace = find_start_brace(ind_maxcomment)) != NULL 5902 || trypos != NULL) 5903 { 5904 if (trypos != NULL && tryposBrace != NULL) 5905 { 5906 /* Both an unmatched '(' and '{' is found. Use the one which is 5907 * closer to the current cursor position, set the other to NULL. */ 5908 if (trypos->lnum != tryposBrace->lnum 5909 ? trypos->lnum < tryposBrace->lnum 5910 : trypos->col < tryposBrace->col) 5911 trypos = NULL; 5912 else 5913 tryposBrace = NULL; 5914 } 5915 5916 if (trypos != NULL) 5917 { 5918 /* 5919 * If the matching paren is more than one line away, use the indent of 5920 * a previous non-empty line that matches the same paren. 5921 */ 5922 amount = -1; 5923 cur_amount = MAXCOL; 5924 our_paren_pos = *trypos; 5925 for (lnum = cur_curpos.lnum - 1; lnum > our_paren_pos.lnum; --lnum) 5926 { 5927 l = skipwhite(ml_get(lnum)); 5928 if (cin_nocode(l)) /* skip comment lines */ 5929 continue; 5930 if (cin_ispreproc_cont(&l, &lnum)) /* ignore #defines, #if, etc. */ 5931 continue; 5932 curwin->w_cursor.lnum = lnum; 5933 5934 /* Skip a comment. XXX */ 5935 if ((trypos = find_start_comment(ind_maxcomment)) != NULL) 5936 { 5937 lnum = trypos->lnum + 1; 5938 continue; 5939 } 5940 5941 /* XXX */ 5942 if ((trypos = find_match_paren( 5943 corr_ind_maxparen(ind_maxparen, &cur_curpos), 5944 ind_maxcomment)) != NULL 5945 && trypos->lnum == our_paren_pos.lnum 5946 && trypos->col == our_paren_pos.col) 5947 { 5948 amount = get_indent_lnum(lnum); /* XXX */ 5949 5950 if (theline[0] == ')') 5951 { 5952 if (our_paren_pos.lnum != lnum && cur_amount > amount) 5953 cur_amount = amount; 5954 amount = -1; 5955 } 5956 break; 5957 } 5958 } 5959 5960 /* 5961 * Line up with line where the matching paren is. XXX 5962 * If the line starts with a '(' or the indent for unclosed 5963 * parentheses is zero, line up with the unclosed parentheses. 5964 */ 5965 if (amount == -1) 5966 { 5967 amount = skip_label(our_paren_pos.lnum, &look, ind_maxcomment); 5968 if (theline[0] == ')' || ind_unclosed == 0 5969 || (!ind_unclosed_noignore && *skipwhite(look) == '(')) 5970 { 5971 /* 5972 * If we're looking at a close paren, line up right there; 5973 * otherwise, line up with the next (non-white) character. 5974 * When ind_unclosed_wrapped is set and the matching paren is 5975 * the last nonwhite character of the line, use either the 5976 * indent of the current line or the indentation of the next 5977 * outer paren and add ind_unclosed_wrapped (for very long 5978 * lines). 5979 */ 5980 if (theline[0] != ')') 5981 { 5982 cur_amount = MAXCOL; 5983 l = ml_get(our_paren_pos.lnum); 5984 if (ind_unclosed_wrapped 5985 && cin_ends_in(l, (char_u *)"(", NULL)) 5986 { 5987 /* look for opening unmatched paren, indent one level 5988 * for each additional level */ 5989 n = 1; 5990 for (col = 0; col < our_paren_pos.col; ++col) 5991 { 5992 switch (l[col]) 5993 { 5994 case '(': 5995 case '{': ++n; 5996 break; 5997 5998 case ')': 5999 case '}': if (n > 1) 6000 --n; 6001 break; 6002 } 6003 } 6004 6005 our_paren_pos.col = 0; 6006 amount += n * ind_unclosed_wrapped; 6007 } 6008 else if (ind_unclosed_whiteok) 6009 our_paren_pos.col++; 6010 else 6011 { 6012 col = our_paren_pos.col + 1; 6013 while (vim_iswhite(l[col])) 6014 col++; 6015 if (l[col] != NUL) /* In case of trailing space */ 6016 our_paren_pos.col = col; 6017 else 6018 our_paren_pos.col++; 6019 } 6020 } 6021 6022 /* 6023 * Find how indented the paren is, or the character after it 6024 * if we did the above "if". 6025 */ 6026 if (our_paren_pos.col > 0) 6027 { 6028 getvcol(curwin, &our_paren_pos, &col, NULL, NULL); 6029 if (cur_amount > (int)col) 6030 cur_amount = col; 6031 } 6032 } 6033 6034 if (theline[0] == ')' && ind_matching_paren) 6035 { 6036 /* Line up with the start of the matching paren line. */ 6037 } 6038 else if (ind_unclosed == 0 || (!ind_unclosed_noignore 6039 && *skipwhite(look) == '(')) 6040 { 6041 if (cur_amount != MAXCOL) 6042 amount = cur_amount; 6043 } 6044 else 6045 { 6046 /* add ind_unclosed2 for each '(' before our matching one */ 6047 col = our_paren_pos.col; 6048 while (our_paren_pos.col > 0) 6049 { 6050 --our_paren_pos.col; 6051 switch (*ml_get_pos(&our_paren_pos)) 6052 { 6053 case '(': amount += ind_unclosed2; 6054 col = our_paren_pos.col; 6055 break; 6056 case ')': amount -= ind_unclosed2; 6057 col = MAXCOL; 6058 break; 6059 } 6060 } 6061 6062 /* Use ind_unclosed once, when the first '(' is not inside 6063 * braces */ 6064 if (col == MAXCOL) 6065 amount += ind_unclosed; 6066 else 6067 { 6068 curwin->w_cursor.lnum = our_paren_pos.lnum; 6069 curwin->w_cursor.col = col; 6070 if ((trypos = find_match_paren(ind_maxparen, 6071 ind_maxcomment)) != NULL) 6072 amount += ind_unclosed2; 6073 else 6074 amount += ind_unclosed; 6075 } 6076 /* 6077 * For a line starting with ')' use the minimum of the two 6078 * positions, to avoid giving it more indent than the previous 6079 * lines: 6080 * func_long_name( if (x 6081 * arg && yy 6082 * ) ^ not here ) ^ not here 6083 */ 6084 if (cur_amount < amount) 6085 amount = cur_amount; 6086 } 6087 } 6088 6089 /* add extra indent for a comment */ 6090 if (cin_iscomment(theline)) 6091 amount += ind_comment; 6092 } 6093 6094 /* 6095 * Are we at least inside braces, then? 6096 */ 6097 else 6098 { 6099 trypos = tryposBrace; 6100 6101 ourscope = trypos->lnum; 6102 start = ml_get(ourscope); 6103 6104 /* 6105 * Now figure out how indented the line is in general. 6106 * If the brace was at the start of the line, we use that; 6107 * otherwise, check out the indentation of the line as 6108 * a whole and then add the "imaginary indent" to that. 6109 */ 6110 look = skipwhite(start); 6111 if (*look == '{') 6112 { 6113 getvcol(curwin, trypos, &col, NULL, NULL); 6114 amount = col; 6115 if (*start == '{') 6116 start_brace = BRACE_IN_COL0; 6117 else 6118 start_brace = BRACE_AT_START; 6119 } 6120 else 6121 { 6122 /* 6123 * that opening brace might have been on a continuation 6124 * line. if so, find the start of the line. 6125 */ 6126 curwin->w_cursor.lnum = ourscope; 6127 6128 /* 6129 * position the cursor over the rightmost paren, so that 6130 * matching it will take us back to the start of the line. 6131 */ 6132 lnum = ourscope; 6133 if (find_last_paren(start, '(', ')') 6134 && (trypos = find_match_paren(ind_maxparen, 6135 ind_maxcomment)) != NULL) 6136 lnum = trypos->lnum; 6137 6138 /* 6139 * It could have been something like 6140 * case 1: if (asdf && 6141 * ldfd) { 6142 * } 6143 */ 6144 if (ind_keep_case_label && cin_iscase(skipwhite(ml_get_curline()))) 6145 amount = get_indent(); 6146 else 6147 amount = skip_label(lnum, &l, ind_maxcomment); 6148 6149 start_brace = BRACE_AT_END; 6150 } 6151 6152 /* 6153 * if we're looking at a closing brace, that's where 6154 * we want to be. otherwise, add the amount of room 6155 * that an indent is supposed to be. 6156 */ 6157 if (theline[0] == '}') 6158 { 6159 /* 6160 * they may want closing braces to line up with something 6161 * other than the open brace. indulge them, if so. 6162 */ 6163 amount += ind_close_extra; 6164 } 6165 else 6166 { 6167 /* 6168 * If we're looking at an "else", try to find an "if" 6169 * to match it with. 6170 * If we're looking at a "while", try to find a "do" 6171 * to match it with. 6172 */ 6173 lookfor = LOOKFOR_INITIAL; 6174 if (cin_iselse(theline)) 6175 lookfor = LOOKFOR_IF; 6176 else if (cin_iswhileofdo(theline, cur_curpos.lnum, ind_maxparen)) 6177 /* XXX */ 6178 lookfor = LOOKFOR_DO; 6179 if (lookfor != LOOKFOR_INITIAL) 6180 { 6181 curwin->w_cursor.lnum = cur_curpos.lnum; 6182 if (find_match(lookfor, ourscope, ind_maxparen, 6183 ind_maxcomment) == OK) 6184 { 6185 amount = get_indent(); /* XXX */ 6186 goto theend; 6187 } 6188 } 6189 6190 /* 6191 * We get here if we are not on an "while-of-do" or "else" (or 6192 * failed to find a matching "if"). 6193 * Search backwards for something to line up with. 6194 * First set amount for when we don't find anything. 6195 */ 6196 6197 /* 6198 * if the '{' is _really_ at the left margin, use the imaginary 6199 * location of a left-margin brace. Otherwise, correct the 6200 * location for ind_open_extra. 6201 */ 6202 6203 if (start_brace == BRACE_IN_COL0) /* '{' is in column 0 */ 6204 { 6205 amount = ind_open_left_imag; 6206 } 6207 else 6208 { 6209 if (start_brace == BRACE_AT_END) /* '{' is at end of line */ 6210 amount += ind_open_imag; 6211 else 6212 { 6213 /* Compensate for adding ind_open_extra later. */ 6214 amount -= ind_open_extra; 6215 if (amount < 0) 6216 amount = 0; 6217 } 6218 } 6219 6220 lookfor_break = FALSE; 6221 6222 if (cin_iscase(theline)) /* it's a switch() label */ 6223 { 6224 lookfor = LOOKFOR_CASE; /* find a previous switch() label */ 6225 amount += ind_case; 6226 } 6227 else if (cin_isscopedecl(theline)) /* private:, ... */ 6228 { 6229 lookfor = LOOKFOR_SCOPEDECL; /* class decl is this block */ 6230 amount += ind_scopedecl; 6231 } 6232 else 6233 { 6234 if (ind_case_break && cin_isbreak(theline)) /* break; ... */ 6235 lookfor_break = TRUE; 6236 6237 lookfor = LOOKFOR_INITIAL; 6238 amount += ind_level; /* ind_level from start of block */ 6239 } 6240 scope_amount = amount; 6241 whilelevel = 0; 6242 6243 /* 6244 * Search backwards. If we find something we recognize, line up 6245 * with that. 6246 * 6247 * if we're looking at an open brace, indent 6248 * the usual amount relative to the conditional 6249 * that opens the block. 6250 */ 6251 curwin->w_cursor = cur_curpos; 6252 for (;;) 6253 { 6254 curwin->w_cursor.lnum--; 6255 curwin->w_cursor.col = 0; 6256 6257 /* 6258 * If we went all the way back to the start of our scope, line 6259 * up with it. 6260 */ 6261 if (curwin->w_cursor.lnum <= ourscope) 6262 { 6263 /* we reached end of scope: 6264 * if looking for a enum or structure initialization 6265 * go further back: 6266 * if it is an initializer (enum xxx or xxx =), then 6267 * don't add ind_continuation, otherwise it is a variable 6268 * declaration: 6269 * int x, 6270 * here; <-- add ind_continuation 6271 */ 6272 if (lookfor == LOOKFOR_ENUM_OR_INIT) 6273 { 6274 if (curwin->w_cursor.lnum == 0 6275 || curwin->w_cursor.lnum 6276 < ourscope - ind_maxparen) 6277 { 6278 /* nothing found (abuse ind_maxparen as limit) 6279 * assume terminated line (i.e. a variable 6280 * initialization) */ 6281 if (cont_amount > 0) 6282 amount = cont_amount; 6283 else 6284 amount += ind_continuation; 6285 break; 6286 } 6287 6288 l = ml_get_curline(); 6289 6290 /* 6291 * If we're in a comment now, skip to the start of the 6292 * comment. 6293 */ 6294 trypos = find_start_comment(ind_maxcomment); 6295 if (trypos != NULL) 6296 { 6297 curwin->w_cursor.lnum = trypos->lnum + 1; 6298 continue; 6299 } 6300 6301 /* 6302 * Skip preprocessor directives and blank lines. 6303 */ 6304 if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum)) 6305 continue; 6306 6307 if (cin_nocode(l)) 6308 continue; 6309 6310 terminated = cin_isterminated(l, FALSE, TRUE); 6311 6312 /* 6313 * If we are at top level and the line looks like a 6314 * function declaration, we are done 6315 * (it's a variable declaration). 6316 */ 6317 if (start_brace != BRACE_IN_COL0 6318 || !cin_isfuncdecl(&l, curwin->w_cursor.lnum)) 6319 { 6320 /* if the line is terminated with another ',' 6321 * it is a continued variable initialization. 6322 * don't add extra indent. 6323 * TODO: does not work, if a function 6324 * declaration is split over multiple lines: 6325 * cin_isfuncdecl returns FALSE then. 6326 */ 6327 if (terminated == ',') 6328 break; 6329 6330 /* if it es a enum declaration or an assignment, 6331 * we are done. 6332 */ 6333 if (terminated != ';' && cin_isinit()) 6334 break; 6335 6336 /* nothing useful found */ 6337 if (terminated == 0 || terminated == '{') 6338 continue; 6339 } 6340 6341 if (terminated != ';') 6342 { 6343 /* Skip parens and braces. Position the cursor 6344 * over the rightmost paren, so that matching it 6345 * will take us back to the start of the line. 6346 */ /* XXX */ 6347 trypos = NULL; 6348 if (find_last_paren(l, '(', ')')) 6349 trypos = find_match_paren(ind_maxparen, 6350 ind_maxcomment); 6351 6352 if (trypos == NULL && find_last_paren(l, '{', '}')) 6353 trypos = find_start_brace(ind_maxcomment); 6354 6355 if (trypos != NULL) 6356 { 6357 curwin->w_cursor.lnum = trypos->lnum + 1; 6358 continue; 6359 } 6360 } 6361 6362 /* it's a variable declaration, add indentation 6363 * like in 6364 * int a, 6365 * b; 6366 */ 6367 if (cont_amount > 0) 6368 amount = cont_amount; 6369 else 6370 amount += ind_continuation; 6371 } 6372 else if (lookfor == LOOKFOR_UNTERM) 6373 { 6374 if (cont_amount > 0) 6375 amount = cont_amount; 6376 else 6377 amount += ind_continuation; 6378 } 6379 else if (lookfor != LOOKFOR_TERM 6380 && lookfor != LOOKFOR_CPP_BASECLASS) 6381 { 6382 amount = scope_amount; 6383 if (theline[0] == '{') 6384 amount += ind_open_extra; 6385 } 6386 break; 6387 } 6388 6389 /* 6390 * If we're in a comment now, skip to the start of the comment. 6391 */ /* XXX */ 6392 if ((trypos = find_start_comment(ind_maxcomment)) != NULL) 6393 { 6394 curwin->w_cursor.lnum = trypos->lnum + 1; 6395 continue; 6396 } 6397 6398 l = ml_get_curline(); 6399 6400 /* 6401 * If this is a switch() label, may line up relative to that. 6402 * if this is a C++ scope declaration, do the same. 6403 */ 6404 iscase = cin_iscase(l); 6405 if (iscase || cin_isscopedecl(l)) 6406 { 6407 /* we are only looking for cpp base class 6408 * declaration/initialization any longer */ 6409 if (lookfor == LOOKFOR_CPP_BASECLASS) 6410 break; 6411 6412 /* When looking for a "do" we are not interested in 6413 * labels. */ 6414 if (whilelevel > 0) 6415 continue; 6416 6417 /* 6418 * case xx: 6419 * c = 99 + <- this indent plus continuation 6420 *-> here; 6421 */ 6422 if (lookfor == LOOKFOR_UNTERM 6423 || lookfor == LOOKFOR_ENUM_OR_INIT) 6424 { 6425 if (cont_amount > 0) 6426 amount = cont_amount; 6427 else 6428 amount += ind_continuation; 6429 break; 6430 } 6431 6432 /* 6433 * case xx: <- line up with this case 6434 * x = 333; 6435 * case yy: 6436 */ 6437 if ( (iscase && lookfor == LOOKFOR_CASE) 6438 || (iscase && lookfor_break) 6439 || (!iscase && lookfor == LOOKFOR_SCOPEDECL)) 6440 { 6441 /* 6442 * Check that this case label is not for another 6443 * switch() 6444 */ /* XXX */ 6445 if ((trypos = find_start_brace(ind_maxcomment)) == 6446 NULL || trypos->lnum == ourscope) 6447 { 6448 amount = get_indent(); /* XXX */ 6449 break; 6450 } 6451 continue; 6452 } 6453 6454 n = get_indent_nolabel(curwin->w_cursor.lnum); /* XXX */ 6455 6456 /* 6457 * case xx: if (cond) <- line up with this if 6458 * y = y + 1; 6459 * -> s = 99; 6460 * 6461 * case xx: 6462 * if (cond) <- line up with this line 6463 * y = y + 1; 6464 * -> s = 99; 6465 */ 6466 if (lookfor == LOOKFOR_TERM) 6467 { 6468 if (n) 6469 amount = n; 6470 6471 if (!lookfor_break) 6472 break; 6473 } 6474 6475 /* 6476 * case xx: x = x + 1; <- line up with this x 6477 * -> y = y + 1; 6478 * 6479 * case xx: if (cond) <- line up with this if 6480 * -> y = y + 1; 6481 */ 6482 if (n) 6483 { 6484 amount = n; 6485 l = after_label(ml_get_curline()); 6486 if (l != NULL && cin_is_cinword(l)) 6487 amount += ind_level + ind_no_brace; 6488 break; 6489 } 6490 6491 /* 6492 * Try to get the indent of a statement before the switch 6493 * label. If nothing is found, line up relative to the 6494 * switch label. 6495 * break; <- may line up with this line 6496 * case xx: 6497 * -> y = 1; 6498 */ 6499 scope_amount = get_indent() + (iscase /* XXX */ 6500 ? ind_case_code : ind_scopedecl_code); 6501 lookfor = ind_case_break ? LOOKFOR_NOBREAK : LOOKFOR_ANY; 6502 continue; 6503 } 6504 6505 /* 6506 * Looking for a switch() label or C++ scope declaration, 6507 * ignore other lines, skip {}-blocks. 6508 */ 6509 if (lookfor == LOOKFOR_CASE || lookfor == LOOKFOR_SCOPEDECL) 6510 { 6511 if (find_last_paren(l, '{', '}') && (trypos = 6512 find_start_brace(ind_maxcomment)) != NULL) 6513 curwin->w_cursor.lnum = trypos->lnum + 1; 6514 continue; 6515 } 6516 6517 /* 6518 * Ignore jump labels with nothing after them. 6519 */ 6520 if (cin_islabel(ind_maxcomment)) 6521 { 6522 l = after_label(ml_get_curline()); 6523 if (l == NULL || cin_nocode(l)) 6524 continue; 6525 } 6526 6527 /* 6528 * Ignore #defines, #if, etc. 6529 * Ignore comment and empty lines. 6530 * (need to get the line again, cin_islabel() may have 6531 * unlocked it) 6532 */ 6533 l = ml_get_curline(); 6534 if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum) 6535 || cin_nocode(l)) 6536 continue; 6537 6538 /* 6539 * Are we at the start of a cpp base class declaration or 6540 * constructor initialization? 6541 */ /* XXX */ 6542 if (lookfor != LOOKFOR_TERM && ind_cpp_baseclass 6543 && cin_is_cpp_baseclass(l, &col)) 6544 { 6545 if (lookfor == LOOKFOR_UNTERM) 6546 { 6547 if (cont_amount > 0) 6548 amount = cont_amount; 6549 else 6550 amount += ind_continuation; 6551 } 6552 else if (col == 0 || theline[0] == '{') 6553 { 6554 amount = get_indent(); 6555 if (find_last_paren(l, '(', ')') 6556 && (trypos = find_match_paren(ind_maxparen, 6557 ind_maxcomment)) != NULL) 6558 amount = get_indent_lnum(trypos->lnum); /* XXX */ 6559 if (theline[0] != '{') 6560 amount += ind_cpp_baseclass; 6561 } 6562 else 6563 { 6564 curwin->w_cursor.col = col; 6565 getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL); 6566 amount = (int)col; 6567 } 6568 break; 6569 } 6570 else if (lookfor == LOOKFOR_CPP_BASECLASS) 6571 { 6572 /* only look, whether there is a cpp base class 6573 * declaration or initialization before the opening brace. */ 6574 if (cin_isterminated(l, TRUE, FALSE)) 6575 break; 6576 else 6577 continue; 6578 } 6579 6580 /* 6581 * What happens next depends on the line being terminated. 6582 * If terminated with a ',' only consider it terminating if 6583 * there is anoter unterminated statement behind, eg: 6584 * 123, 6585 * sizeof 6586 * here 6587 * Otherwise check whether it is a enumeration or structure 6588 * initialisation (not indented) or a variable declaration 6589 * (indented). 6590 */ 6591 terminated = cin_isterminated(l, FALSE, TRUE); 6592 6593 if (terminated == 0 || (lookfor != LOOKFOR_UNTERM 6594 && terminated == ',')) 6595 { 6596 /* 6597 * if we're in the middle of a paren thing, 6598 * go back to the line that starts it so 6599 * we can get the right prevailing indent 6600 * if ( foo && 6601 * bar ) 6602 */ 6603 /* 6604 * position the cursor over the rightmost paren, so that 6605 * matching it will take us back to the start of the line. 6606 */ 6607 (void)find_last_paren(l, '(', ')'); 6608 trypos = find_match_paren( 6609 corr_ind_maxparen(ind_maxparen, &cur_curpos), 6610 ind_maxcomment); 6611 6612 /* 6613 * If we are looking for ',', we also look for matching 6614 * braces. 6615 */ 6616 if (trypos == NULL && find_last_paren(l, '{', '}')) 6617 trypos = find_start_brace(ind_maxcomment); 6618 6619 if (trypos != NULL) 6620 { 6621 /* 6622 * Check if we are on a case label now. This is 6623 * handled above. 6624 * case xx: if ( asdf && 6625 * asdf) 6626 */ 6627 curwin->w_cursor.lnum = trypos->lnum; 6628 l = ml_get_curline(); 6629 if (cin_iscase(l) || cin_isscopedecl(l)) 6630 { 6631 ++curwin->w_cursor.lnum; 6632 continue; 6633 } 6634 } 6635 6636 /* 6637 * Skip over continuation lines to find the one to get the 6638 * indent from 6639 * char *usethis = "bla\ 6640 * bla", 6641 * here; 6642 */ 6643 if (terminated == ',') 6644 { 6645 while (curwin->w_cursor.lnum > 1) 6646 { 6647 l = ml_get(curwin->w_cursor.lnum - 1); 6648 if (*l == NUL || l[STRLEN(l) - 1] != '\\') 6649 break; 6650 --curwin->w_cursor.lnum; 6651 } 6652 } 6653 6654 /* 6655 * Get indent and pointer to text for current line, 6656 * ignoring any jump label. XXX 6657 */ 6658 cur_amount = skip_label(curwin->w_cursor.lnum, 6659 &l, ind_maxcomment); 6660 6661 /* 6662 * If this is just above the line we are indenting, and it 6663 * starts with a '{', line it up with this line. 6664 * while (not) 6665 * -> { 6666 * } 6667 */ 6668 if (terminated != ',' && lookfor != LOOKFOR_TERM 6669 && theline[0] == '{') 6670 { 6671 amount = cur_amount; 6672 /* 6673 * Only add ind_open_extra when the current line 6674 * doesn't start with a '{', which must have a match 6675 * in the same line (scope is the same). Probably: 6676 * { 1, 2 }, 6677 * -> { 3, 4 } 6678 */ 6679 if (*skipwhite(l) != '{') 6680 amount += ind_open_extra; 6681 6682 if (ind_cpp_baseclass) 6683 { 6684 /* have to look back, whether it is a cpp base 6685 * class declaration or initialization */ 6686 lookfor = LOOKFOR_CPP_BASECLASS; 6687 continue; 6688 } 6689 break; 6690 } 6691 6692 /* 6693 * Check if we are after an "if", "while", etc. 6694 * Also allow " } else". 6695 */ 6696 if (cin_is_cinword(l) || cin_iselse(skipwhite(l))) 6697 { 6698 /* 6699 * Found an unterminated line after an if (), line up 6700 * with the last one. 6701 * if (cond) 6702 * 100 + 6703 * -> here; 6704 */ 6705 if (lookfor == LOOKFOR_UNTERM 6706 || lookfor == LOOKFOR_ENUM_OR_INIT) 6707 { 6708 if (cont_amount > 0) 6709 amount = cont_amount; 6710 else 6711 amount += ind_continuation; 6712 break; 6713 } 6714 6715 /* 6716 * If this is just above the line we are indenting, we 6717 * are finished. 6718 * while (not) 6719 * -> here; 6720 * Otherwise this indent can be used when the line 6721 * before this is terminated. 6722 * yyy; 6723 * if (stat) 6724 * while (not) 6725 * xxx; 6726 * -> here; 6727 */ 6728 amount = cur_amount; 6729 if (theline[0] == '{') 6730 amount += ind_open_extra; 6731 if (lookfor != LOOKFOR_TERM) 6732 { 6733 amount += ind_level + ind_no_brace; 6734 break; 6735 } 6736 6737 /* 6738 * Special trick: when expecting the while () after a 6739 * do, line up with the while() 6740 * do 6741 * x = 1; 6742 * -> here 6743 */ 6744 l = skipwhite(ml_get_curline()); 6745 if (cin_isdo(l)) 6746 { 6747 if (whilelevel == 0) 6748 break; 6749 --whilelevel; 6750 } 6751 6752 /* 6753 * When searching for a terminated line, don't use the 6754 * one between the "if" and the "else". 6755 * Need to use the scope of this "else". XXX 6756 * If whilelevel != 0 continue looking for a "do {". 6757 */ 6758 if (cin_iselse(l) 6759 && whilelevel == 0 6760 && ((trypos = find_start_brace(ind_maxcomment)) 6761 == NULL 6762 || find_match(LOOKFOR_IF, trypos->lnum, 6763 ind_maxparen, ind_maxcomment) == FAIL)) 6764 break; 6765 } 6766 6767 /* 6768 * If we're below an unterminated line that is not an 6769 * "if" or something, we may line up with this line or 6770 * add someting for a continuation line, depending on 6771 * the line before this one. 6772 */ 6773 else 6774 { 6775 /* 6776 * Found two unterminated lines on a row, line up with 6777 * the last one. 6778 * c = 99 + 6779 * 100 + 6780 * -> here; 6781 */ 6782 if (lookfor == LOOKFOR_UNTERM) 6783 { 6784 /* When line ends in a comma add extra indent */ 6785 if (terminated == ',') 6786 amount += ind_continuation; 6787 break; 6788 } 6789 6790 if (lookfor == LOOKFOR_ENUM_OR_INIT) 6791 { 6792 /* Found two lines ending in ',', lineup with the 6793 * lowest one, but check for cpp base class 6794 * declaration/initialization, if it is an 6795 * opening brace or we are looking just for 6796 * enumerations/initializations. */ 6797 if (terminated == ',') 6798 { 6799 if (ind_cpp_baseclass == 0) 6800 break; 6801 6802 lookfor = LOOKFOR_CPP_BASECLASS; 6803 continue; 6804 } 6805 6806 /* Ignore unterminated lines in between, but 6807 * reduce indent. */ 6808 if (amount > cur_amount) 6809 amount = cur_amount; 6810 } 6811 else 6812 { 6813 /* 6814 * Found first unterminated line on a row, may 6815 * line up with this line, remember its indent 6816 * 100 + 6817 * -> here; 6818 */ 6819 amount = cur_amount; 6820 6821 /* 6822 * If previous line ends in ',', check whether we 6823 * are in an initialization or enum 6824 * struct xxx = 6825 * { 6826 * sizeof a, 6827 * 124 }; 6828 * or a normal possible continuation line. 6829 * but only, of no other statement has been found 6830 * yet. 6831 */ 6832 if (lookfor == LOOKFOR_INITIAL && terminated == ',') 6833 { 6834 lookfor = LOOKFOR_ENUM_OR_INIT; 6835 cont_amount = cin_first_id_amount(); 6836 } 6837 else 6838 { 6839 if (lookfor == LOOKFOR_INITIAL 6840 && *l != NUL 6841 && l[STRLEN(l) - 1] == '\\') 6842 /* XXX */ 6843 cont_amount = cin_get_equal_amount( 6844 curwin->w_cursor.lnum); 6845 if (lookfor != LOOKFOR_TERM) 6846 lookfor = LOOKFOR_UNTERM; 6847 } 6848 } 6849 } 6850 } 6851 6852 /* 6853 * Check if we are after a while (cond); 6854 * If so: Ignore until the matching "do". 6855 */ 6856 /* XXX */ 6857 else if (cin_iswhileofdo(l, 6858 curwin->w_cursor.lnum, ind_maxparen)) 6859 { 6860 /* 6861 * Found an unterminated line after a while ();, line up 6862 * with the last one. 6863 * while (cond); 6864 * 100 + <- line up with this one 6865 * -> here; 6866 */ 6867 if (lookfor == LOOKFOR_UNTERM 6868 || lookfor == LOOKFOR_ENUM_OR_INIT) 6869 { 6870 if (cont_amount > 0) 6871 amount = cont_amount; 6872 else 6873 amount += ind_continuation; 6874 break; 6875 } 6876 6877 if (whilelevel == 0) 6878 { 6879 lookfor = LOOKFOR_TERM; 6880 amount = get_indent(); /* XXX */ 6881 if (theline[0] == '{') 6882 amount += ind_open_extra; 6883 } 6884 ++whilelevel; 6885 } 6886 6887 /* 6888 * We are after a "normal" statement. 6889 * If we had another statement we can stop now and use the 6890 * indent of that other statement. 6891 * Otherwise the indent of the current statement may be used, 6892 * search backwards for the next "normal" statement. 6893 */ 6894 else 6895 { 6896 /* 6897 * Skip single break line, if before a switch label. It 6898 * may be lined up with the case label. 6899 */ 6900 if (lookfor == LOOKFOR_NOBREAK 6901 && cin_isbreak(skipwhite(ml_get_curline()))) 6902 { 6903 lookfor = LOOKFOR_ANY; 6904 continue; 6905 } 6906 6907 /* 6908 * Handle "do {" line. 6909 */ 6910 if (whilelevel > 0) 6911 { 6912 l = cin_skipcomment(ml_get_curline()); 6913 if (cin_isdo(l)) 6914 { 6915 amount = get_indent(); /* XXX */ 6916 --whilelevel; 6917 continue; 6918 } 6919 } 6920 6921 /* 6922 * Found a terminated line above an unterminated line. Add 6923 * the amount for a continuation line. 6924 * x = 1; 6925 * y = foo + 6926 * -> here; 6927 * or 6928 * int x = 1; 6929 * int foo, 6930 * -> here; 6931 */ 6932 if (lookfor == LOOKFOR_UNTERM 6933 || lookfor == LOOKFOR_ENUM_OR_INIT) 6934 { 6935 if (cont_amount > 0) 6936 amount = cont_amount; 6937 else 6938 amount += ind_continuation; 6939 break; 6940 } 6941 6942 /* 6943 * Found a terminated line above a terminated line or "if" 6944 * etc. line. Use the amount of the line below us. 6945 * x = 1; x = 1; 6946 * if (asdf) y = 2; 6947 * while (asdf) ->here; 6948 * here; 6949 * ->foo; 6950 */ 6951 if (lookfor == LOOKFOR_TERM) 6952 { 6953 if (!lookfor_break && whilelevel == 0) 6954 break; 6955 } 6956 6957 /* 6958 * First line above the one we're indenting is terminated. 6959 * To know what needs to be done look further backward for 6960 * a terminated line. 6961 */ 6962 else 6963 { 6964 /* 6965 * position the cursor over the rightmost paren, so 6966 * that matching it will take us back to the start of 6967 * the line. Helps for: 6968 * func(asdr, 6969 * asdfasdf); 6970 * here; 6971 */ 6972 term_again: 6973 l = ml_get_curline(); 6974 if (find_last_paren(l, '(', ')') 6975 && (trypos = find_match_paren(ind_maxparen, 6976 ind_maxcomment)) != NULL) 6977 { 6978 /* 6979 * Check if we are on a case label now. This is 6980 * handled above. 6981 * case xx: if ( asdf && 6982 * asdf) 6983 */ 6984 curwin->w_cursor.lnum = trypos->lnum; 6985 l = ml_get_curline(); 6986 if (cin_iscase(l) || cin_isscopedecl(l)) 6987 { 6988 ++curwin->w_cursor.lnum; 6989 continue; 6990 } 6991 } 6992 6993 /* When aligning with the case statement, don't align 6994 * with a statement after it. 6995 * case 1: { <-- don't use this { position 6996 * stat; 6997 * } 6998 * case 2: 6999 * stat; 7000 * } 7001 */ 7002 iscase = (ind_keep_case_label && cin_iscase(l)); 7003 7004 /* 7005 * Get indent and pointer to text for current line, 7006 * ignoring any jump label. 7007 */ 7008 amount = skip_label(curwin->w_cursor.lnum, 7009 &l, ind_maxcomment); 7010 7011 if (theline[0] == '{') 7012 amount += ind_open_extra; 7013 /* See remark above: "Only add ind_open_extra.." */ 7014 if (*skipwhite(l) == '{') 7015 amount -= ind_open_extra; 7016 lookfor = iscase ? LOOKFOR_ANY : LOOKFOR_TERM; 7017 7018 /* 7019 * If we're at the end of a block, skip to the start of 7020 * that block. 7021 */ 7022 curwin->w_cursor.col = 0; 7023 if (*cin_skipcomment(l) == '}' 7024 && (trypos = find_start_brace(ind_maxcomment)) 7025 != NULL) /* XXX */ 7026 { 7027 curwin->w_cursor.lnum = trypos->lnum; 7028 /* if not "else {" check for terminated again */ 7029 /* but skip block for "} else {" */ 7030 l = cin_skipcomment(ml_get_curline()); 7031 if (*l == '}' || !cin_iselse(l)) 7032 goto term_again; 7033 ++curwin->w_cursor.lnum; 7034 } 7035 } 7036 } 7037 } 7038 } 7039 } 7040 7041 /* add extra indent for a comment */ 7042 if (cin_iscomment(theline)) 7043 amount += ind_comment; 7044 } 7045 7046 /* 7047 * ok -- we're not inside any sort of structure at all! 7048 * 7049 * this means we're at the top level, and everything should 7050 * basically just match where the previous line is, except 7051 * for the lines immediately following a function declaration, 7052 * which are K&R-style parameters and need to be indented. 7053 */ 7054 else 7055 { 7056 /* 7057 * if our line starts with an open brace, forget about any 7058 * prevailing indent and make sure it looks like the start 7059 * of a function 7060 */ 7061 7062 if (theline[0] == '{') 7063 { 7064 amount = ind_first_open; 7065 } 7066 7067 /* 7068 * If the NEXT line is a function declaration, the current 7069 * line needs to be indented as a function type spec. 7070 * Don't do this if the current line looks like a comment 7071 * or if the current line is terminated, ie. ends in ';'. 7072 */ 7073 else if (cur_curpos.lnum < curbuf->b_ml.ml_line_count 7074 && !cin_nocode(theline) 7075 && !cin_ends_in(theline, (char_u *)":", NULL) 7076 && !cin_ends_in(theline, (char_u *)",", NULL) 7077 && cin_isfuncdecl(NULL, cur_curpos.lnum + 1) 7078 && !cin_isterminated(theline, FALSE, TRUE)) 7079 { 7080 amount = ind_func_type; 7081 } 7082 else 7083 { 7084 amount = 0; 7085 curwin->w_cursor = cur_curpos; 7086 7087 /* search backwards until we find something we recognize */ 7088 7089 while (curwin->w_cursor.lnum > 1) 7090 { 7091 curwin->w_cursor.lnum--; 7092 curwin->w_cursor.col = 0; 7093 7094 l = ml_get_curline(); 7095 7096 /* 7097 * If we're in a comment now, skip to the start of the comment. 7098 */ /* XXX */ 7099 if ((trypos = find_start_comment(ind_maxcomment)) != NULL) 7100 { 7101 curwin->w_cursor.lnum = trypos->lnum + 1; 7102 continue; 7103 } 7104 7105 /* 7106 * Are we at the start of a cpp base class declaration or constructor 7107 * initialization? 7108 */ /* XXX */ 7109 if (ind_cpp_baseclass != 0 && theline[0] != '{' 7110 && cin_is_cpp_baseclass(l, &col)) 7111 { 7112 if (col == 0) 7113 { 7114 amount = get_indent() + ind_cpp_baseclass; /* XXX */ 7115 if (find_last_paren(l, '(', ')') 7116 && (trypos = find_match_paren(ind_maxparen, 7117 ind_maxcomment)) != NULL) 7118 amount = get_indent_lnum(trypos->lnum) 7119 + ind_cpp_baseclass; /* XXX */ 7120 } 7121 else 7122 { 7123 curwin->w_cursor.col = col; 7124 getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL); 7125 amount = (int)col; 7126 } 7127 break; 7128 } 7129 7130 /* 7131 * Skip preprocessor directives and blank lines. 7132 */ 7133 if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum)) 7134 continue; 7135 7136 if (cin_nocode(l)) 7137 continue; 7138 7139 /* 7140 * If the previous line ends in ',', use one level of 7141 * indentation: 7142 * int foo, 7143 * bar; 7144 * do this before checking for '}' in case of eg. 7145 * enum foobar 7146 * { 7147 * ... 7148 * } foo, 7149 * bar; 7150 */ 7151 n = 0; 7152 if (cin_ends_in(l, (char_u *)",", NULL) 7153 || (*l != NUL && (n = l[STRLEN(l) - 1]) == '\\')) 7154 { 7155 /* take us back to opening paren */ 7156 if (find_last_paren(l, '(', ')') 7157 && (trypos = find_match_paren(ind_maxparen, 7158 ind_maxcomment)) != NULL) 7159 curwin->w_cursor.lnum = trypos->lnum; 7160 7161 /* For a line ending in ',' that is a continuation line go 7162 * back to the first line with a backslash: 7163 * char *foo = "bla\ 7164 * bla", 7165 * here; 7166 */ 7167 while (n == 0 && curwin->w_cursor.lnum > 1) 7168 { 7169 l = ml_get(curwin->w_cursor.lnum - 1); 7170 if (*l == NUL || l[STRLEN(l) - 1] != '\\') 7171 break; 7172 --curwin->w_cursor.lnum; 7173 } 7174 7175 amount = get_indent(); /* XXX */ 7176 7177 if (amount == 0) 7178 amount = cin_first_id_amount(); 7179 if (amount == 0) 7180 amount = ind_continuation; 7181 break; 7182 } 7183 7184 /* 7185 * If the line looks like a function declaration, and we're 7186 * not in a comment, put it the left margin. 7187 */ 7188 if (cin_isfuncdecl(NULL, cur_curpos.lnum)) /* XXX */ 7189 break; 7190 l = ml_get_curline(); 7191 7192 /* 7193 * Finding the closing '}' of a previous function. Put 7194 * current line at the left margin. For when 'cino' has "fs". 7195 */ 7196 if (*skipwhite(l) == '}') 7197 break; 7198 7199 /* (matching {) 7200 * If the previous line ends on '};' (maybe followed by 7201 * comments) align at column 0. For example: 7202 * char *string_array[] = { "foo", 7203 * / * x * / "b};ar" }; / * foobar * / 7204 */ 7205 if (cin_ends_in(l, (char_u *)"};", NULL)) 7206 break; 7207 7208 /* 7209 * If the PREVIOUS line is a function declaration, the current 7210 * line (and the ones that follow) needs to be indented as 7211 * parameters. 7212 */ 7213 if (cin_isfuncdecl(&l, curwin->w_cursor.lnum)) 7214 { 7215 amount = ind_param; 7216 break; 7217 } 7218 7219 /* 7220 * If the previous line ends in ';' and the line before the 7221 * previous line ends in ',' or '\', ident to column zero: 7222 * int foo, 7223 * bar; 7224 * indent_to_0 here; 7225 */ 7226 if (cin_ends_in(l, (char_u*)";", NULL)) 7227 { 7228 l = ml_get(curwin->w_cursor.lnum - 1); 7229 if (cin_ends_in(l, (char_u *)",", NULL) 7230 || (*l != NUL && l[STRLEN(l) - 1] == '\\')) 7231 break; 7232 l = ml_get_curline(); 7233 } 7234 7235 /* 7236 * Doesn't look like anything interesting -- so just 7237 * use the indent of this line. 7238 * 7239 * Position the cursor over the rightmost paren, so that 7240 * matching it will take us back to the start of the line. 7241 */ 7242 find_last_paren(l, '(', ')'); 7243 7244 if ((trypos = find_match_paren(ind_maxparen, 7245 ind_maxcomment)) != NULL) 7246 curwin->w_cursor.lnum = trypos->lnum; 7247 amount = get_indent(); /* XXX */ 7248 break; 7249 } 7250 7251 /* add extra indent for a comment */ 7252 if (cin_iscomment(theline)) 7253 amount += ind_comment; 7254 7255 /* add extra indent if the previous line ended in a backslash: 7256 * "asdfasdf\ 7257 * here"; 7258 * char *foo = "asdf\ 7259 * here"; 7260 */ 7261 if (cur_curpos.lnum > 1) 7262 { 7263 l = ml_get(cur_curpos.lnum - 1); 7264 if (*l != NUL && l[STRLEN(l) - 1] == '\\') 7265 { 7266 cur_amount = cin_get_equal_amount(cur_curpos.lnum - 1); 7267 if (cur_amount > 0) 7268 amount = cur_amount; 7269 else if (cur_amount == 0) 7270 amount += ind_continuation; 7271 } 7272 } 7273 } 7274 } 7275 7276 theend: 7277 /* put the cursor back where it belongs */ 7278 curwin->w_cursor = cur_curpos; 7279 7280 vim_free(linecopy); 7281 7282 if (amount < 0) 7283 return 0; 7284 return amount; 7285 } 7286 7287 static int 7288 find_match(lookfor, ourscope, ind_maxparen, ind_maxcomment) 7289 int lookfor; 7290 linenr_T ourscope; 7291 int ind_maxparen; 7292 int ind_maxcomment; 7293 { 7294 char_u *look; 7295 pos_T *theirscope; 7296 char_u *mightbeif; 7297 int elselevel; 7298 int whilelevel; 7299 7300 if (lookfor == LOOKFOR_IF) 7301 { 7302 elselevel = 1; 7303 whilelevel = 0; 7304 } 7305 else 7306 { 7307 elselevel = 0; 7308 whilelevel = 1; 7309 } 7310 7311 curwin->w_cursor.col = 0; 7312 7313 while (curwin->w_cursor.lnum > ourscope + 1) 7314 { 7315 curwin->w_cursor.lnum--; 7316 curwin->w_cursor.col = 0; 7317 7318 look = cin_skipcomment(ml_get_curline()); 7319 if (cin_iselse(look) 7320 || cin_isif(look) 7321 || cin_isdo(look) /* XXX */ 7322 || cin_iswhileofdo(look, curwin->w_cursor.lnum, ind_maxparen)) 7323 { 7324 /* 7325 * if we've gone outside the braces entirely, 7326 * we must be out of scope... 7327 */ 7328 theirscope = find_start_brace(ind_maxcomment); /* XXX */ 7329 if (theirscope == NULL) 7330 break; 7331 7332 /* 7333 * and if the brace enclosing this is further 7334 * back than the one enclosing the else, we're 7335 * out of luck too. 7336 */ 7337 if (theirscope->lnum < ourscope) 7338 break; 7339 7340 /* 7341 * and if they're enclosed in a *deeper* brace, 7342 * then we can ignore it because it's in a 7343 * different scope... 7344 */ 7345 if (theirscope->lnum > ourscope) 7346 continue; 7347 7348 /* 7349 * if it was an "else" (that's not an "else if") 7350 * then we need to go back to another if, so 7351 * increment elselevel 7352 */ 7353 look = cin_skipcomment(ml_get_curline()); 7354 if (cin_iselse(look)) 7355 { 7356 mightbeif = cin_skipcomment(look + 4); 7357 if (!cin_isif(mightbeif)) 7358 ++elselevel; 7359 continue; 7360 } 7361 7362 /* 7363 * if it was a "while" then we need to go back to 7364 * another "do", so increment whilelevel. XXX 7365 */ 7366 if (cin_iswhileofdo(look, curwin->w_cursor.lnum, ind_maxparen)) 7367 { 7368 ++whilelevel; 7369 continue; 7370 } 7371 7372 /* If it's an "if" decrement elselevel */ 7373 look = cin_skipcomment(ml_get_curline()); 7374 if (cin_isif(look)) 7375 { 7376 elselevel--; 7377 /* 7378 * When looking for an "if" ignore "while"s that 7379 * get in the way. 7380 */ 7381 if (elselevel == 0 && lookfor == LOOKFOR_IF) 7382 whilelevel = 0; 7383 } 7384 7385 /* If it's a "do" decrement whilelevel */ 7386 if (cin_isdo(look)) 7387 whilelevel--; 7388 7389 /* 7390 * if we've used up all the elses, then 7391 * this must be the if that we want! 7392 * match the indent level of that if. 7393 */ 7394 if (elselevel <= 0 && whilelevel <= 0) 7395 { 7396 return OK; 7397 } 7398 } 7399 } 7400 return FAIL; 7401 } 7402 7403 # if defined(FEAT_EVAL) || defined(PROTO) 7404 /* 7405 * Get indent level from 'indentexpr'. 7406 */ 7407 int 7408 get_expr_indent() 7409 { 7410 int indent; 7411 pos_T pos; 7412 int save_State; 7413 7414 pos = curwin->w_cursor; 7415 set_vim_var_nr(VV_LNUM, curwin->w_cursor.lnum); 7416 ++sandbox; 7417 indent = eval_to_number(curbuf->b_p_inde); 7418 --sandbox; 7419 7420 /* Restore the cursor position so that 'indentexpr' doesn't need to. 7421 * Pretend to be in Insert mode, allow cursor past end of line for "o" 7422 * command. */ 7423 save_State = State; 7424 State = INSERT; 7425 curwin->w_cursor = pos; 7426 check_cursor(); 7427 State = save_State; 7428 7429 /* If there is an error, just keep the current indent. */ 7430 if (indent < 0) 7431 indent = get_indent(); 7432 7433 return indent; 7434 } 7435 # endif 7436 7437 #endif /* FEAT_CINDENT */ 7438 7439 #if defined(FEAT_LISP) || defined(PROTO) 7440 7441 static int lisp_match __ARGS((char_u *p)); 7442 7443 static int 7444 lisp_match(p) 7445 char_u *p; 7446 { 7447 char_u buf[LSIZE]; 7448 int len; 7449 char_u *word = p_lispwords; 7450 7451 while (*word != NUL) 7452 { 7453 (void)copy_option_part(&word, buf, LSIZE, ","); 7454 len = (int)STRLEN(buf); 7455 if (STRNCMP(buf, p, len) == 0 && p[len] == ' ') 7456 return TRUE; 7457 } 7458 return FALSE; 7459 } 7460 7461 /* 7462 * When 'p' is present in 'cpoptions, a Vi compatible method is used. 7463 * The incompatible newer method is quite a bit better at indenting 7464 * code in lisp-like languages than the traditional one; it's still 7465 * mostly heuristics however -- Dirk van Deun, [email protected] 7466 * 7467 * TODO: 7468 * Findmatch() should be adapted for lisp, also to make showmatch 7469 * work correctly: now (v5.3) it seems all C/C++ oriented: 7470 * - it does not recognize the #\( and #\) notations as character literals 7471 * - it doesn't know about comments starting with a semicolon 7472 * - it incorrectly interprets '(' as a character literal 7473 * All this messes up get_lisp_indent in some rare cases. 7474 * Update from Sergey Khorev: 7475 * I tried to fix the first two issues. 7476 */ 7477 int 7478 get_lisp_indent() 7479 { 7480 pos_T *pos, realpos, paren; 7481 int amount; 7482 char_u *that; 7483 colnr_T col; 7484 colnr_T firsttry; 7485 int parencount, quotecount; 7486 int vi_lisp; 7487 7488 /* Set vi_lisp to use the vi-compatible method */ 7489 vi_lisp = (vim_strchr(p_cpo, CPO_LISP) != NULL); 7490 7491 realpos = curwin->w_cursor; 7492 curwin->w_cursor.col = 0; 7493 7494 if ((pos = findmatch(NULL, '(')) == NULL) 7495 pos = findmatch(NULL, '['); 7496 else 7497 { 7498 paren = *pos; 7499 pos = findmatch(NULL, '['); 7500 if (pos == NULL || ltp(pos, &paren)) 7501 pos = &paren; 7502 } 7503 if (pos != NULL) 7504 { 7505 /* Extra trick: Take the indent of the first previous non-white 7506 * line that is at the same () level. */ 7507 amount = -1; 7508 parencount = 0; 7509 7510 while (--curwin->w_cursor.lnum >= pos->lnum) 7511 { 7512 if (linewhite(curwin->w_cursor.lnum)) 7513 continue; 7514 for (that = ml_get_curline(); *that != NUL; ++that) 7515 { 7516 if (*that == ';') 7517 { 7518 while (*(that + 1) != NUL) 7519 ++that; 7520 continue; 7521 } 7522 if (*that == '\\') 7523 { 7524 if (*(that + 1) != NUL) 7525 ++that; 7526 continue; 7527 } 7528 if (*that == '"' && *(that + 1) != NUL) 7529 { 7530 that++; 7531 while (*that && (*that != '"' || *(that - 1) == '\\')) 7532 ++that; 7533 } 7534 if (*that == '(' || *that == '[') 7535 ++parencount; 7536 else if (*that == ')' || *that == ']') 7537 --parencount; 7538 } 7539 if (parencount == 0) 7540 { 7541 amount = get_indent(); 7542 break; 7543 } 7544 } 7545 7546 if (amount == -1) 7547 { 7548 curwin->w_cursor.lnum = pos->lnum; 7549 curwin->w_cursor.col = pos->col; 7550 col = pos->col; 7551 7552 that = ml_get_curline(); 7553 7554 if (vi_lisp && get_indent() == 0) 7555 amount = 2; 7556 else 7557 { 7558 amount = 0; 7559 while (*that && col) 7560 { 7561 amount += lbr_chartabsize_adv(&that, (colnr_T)amount); 7562 col--; 7563 } 7564 7565 /* 7566 * Some keywords require "body" indenting rules (the 7567 * non-standard-lisp ones are Scheme special forms): 7568 * 7569 * (let ((a 1)) instead (let ((a 1)) 7570 * (...)) of (...)) 7571 */ 7572 7573 if (!vi_lisp && (*that == '(' || *that == '[') 7574 && lisp_match(that + 1)) 7575 amount += 2; 7576 else 7577 { 7578 that++; 7579 amount++; 7580 firsttry = amount; 7581 7582 while (vim_iswhite(*that)) 7583 { 7584 amount += lbr_chartabsize(that, (colnr_T)amount); 7585 ++that; 7586 } 7587 7588 if (*that && *that != ';') /* not a comment line */ 7589 { 7590 /* test *that != '(' to accomodate first let/do 7591 * argument if it is more than one line */ 7592 if (!vi_lisp && *that != '(' && *that != '[') 7593 firsttry++; 7594 7595 parencount = 0; 7596 quotecount = 0; 7597 7598 if (vi_lisp 7599 || (*that != '"' 7600 && *that != '\'' 7601 && *that != '#' 7602 && (*that < '0' || *that > '9'))) 7603 { 7604 while (*that 7605 && (!vim_iswhite(*that) 7606 || quotecount 7607 || parencount) 7608 && (!((*that == '(' || *that == '[') 7609 && !quotecount 7610 && !parencount 7611 && vi_lisp))) 7612 { 7613 if (*that == '"') 7614 quotecount = !quotecount; 7615 if ((*that == '(' || *that == '[') 7616 && !quotecount) 7617 ++parencount; 7618 if ((*that == ')' || *that == ']') 7619 && !quotecount) 7620 --parencount; 7621 if (*that == '\\' && *(that+1) != NUL) 7622 amount += lbr_chartabsize_adv(&that, 7623 (colnr_T)amount); 7624 amount += lbr_chartabsize_adv(&that, 7625 (colnr_T)amount); 7626 } 7627 } 7628 while (vim_iswhite(*that)) 7629 { 7630 amount += lbr_chartabsize(that, (colnr_T)amount); 7631 that++; 7632 } 7633 if (!*that || *that == ';') 7634 amount = firsttry; 7635 } 7636 } 7637 } 7638 } 7639 } 7640 else 7641 amount = 0; /* no matching '(' or '[' found, use zero indent */ 7642 7643 curwin->w_cursor = realpos; 7644 7645 return amount; 7646 } 7647 #endif /* FEAT_LISP */ 7648 7649 void 7650 prepare_to_exit() 7651 { 7652 #ifdef FEAT_GUI 7653 if (gui.in_use) 7654 { 7655 gui.dying = TRUE; 7656 out_trash(); /* trash any pending output */ 7657 } 7658 else 7659 #endif 7660 { 7661 windgoto((int)Rows - 1, 0); 7662 7663 /* 7664 * Switch terminal mode back now, so messages end up on the "normal" 7665 * screen (if there are two screens). 7666 */ 7667 settmode(TMODE_COOK); 7668 #ifdef WIN3264 7669 if (can_end_termcap_mode(FALSE) == TRUE) 7670 #endif 7671 stoptermcap(); 7672 out_flush(); 7673 } 7674 } 7675 7676 /* 7677 * Preserve files and exit. 7678 * When called IObuff must contain a message. 7679 */ 7680 void 7681 preserve_exit() 7682 { 7683 buf_T *buf; 7684 7685 prepare_to_exit(); 7686 7687 out_str(IObuff); 7688 screen_start(); /* don't know where cursor is now */ 7689 out_flush(); 7690 7691 ml_close_notmod(); /* close all not-modified buffers */ 7692 7693 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 7694 { 7695 if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL) 7696 { 7697 OUT_STR(_("Vim: preserving files...\n")); 7698 screen_start(); /* don't know where cursor is now */ 7699 out_flush(); 7700 ml_sync_all(FALSE, FALSE); /* preserve all swap files */ 7701 break; 7702 } 7703 } 7704 7705 ml_close_all(FALSE); /* close all memfiles, without deleting */ 7706 7707 OUT_STR(_("Vim: Finished.\n")); 7708 7709 getout(1); 7710 } 7711 7712 /* 7713 * return TRUE if "fname" exists. 7714 */ 7715 int 7716 vim_fexists(fname) 7717 char_u *fname; 7718 { 7719 struct stat st; 7720 7721 if (mch_stat((char *)fname, &st)) 7722 return FALSE; 7723 return TRUE; 7724 } 7725 7726 /* 7727 * Check for CTRL-C pressed, but only once in a while. 7728 * Should be used instead of ui_breakcheck() for functions that check for 7729 * each line in the file. Calling ui_breakcheck() each time takes too much 7730 * time, because it can be a system call. 7731 */ 7732 7733 #ifndef BREAKCHECK_SKIP 7734 # ifdef FEAT_GUI /* assume the GUI only runs on fast computers */ 7735 # define BREAKCHECK_SKIP 200 7736 # else 7737 # define BREAKCHECK_SKIP 32 7738 # endif 7739 #endif 7740 7741 static int breakcheck_count = 0; 7742 7743 void 7744 line_breakcheck() 7745 { 7746 if (++breakcheck_count >= BREAKCHECK_SKIP) 7747 { 7748 breakcheck_count = 0; 7749 ui_breakcheck(); 7750 } 7751 } 7752 7753 /* 7754 * Like line_breakcheck() but check 10 times less often. 7755 */ 7756 void 7757 fast_breakcheck() 7758 { 7759 if (++breakcheck_count >= BREAKCHECK_SKIP * 10) 7760 { 7761 breakcheck_count = 0; 7762 ui_breakcheck(); 7763 } 7764 } 7765 7766 /* 7767 * Expand wildcards. Calls gen_expand_wildcards() and removes files matching 7768 * 'wildignore'. 7769 */ 7770 int 7771 expand_wildcards(num_pat, pat, num_file, file, flags) 7772 int num_pat; /* number of input patterns */ 7773 char_u **pat; /* array of input patterns */ 7774 int *num_file; /* resulting number of files */ 7775 char_u ***file; /* array of resulting files */ 7776 int flags; /* EW_DIR, etc. */ 7777 { 7778 int retval; 7779 int i, j; 7780 char_u *p; 7781 int non_suf_match; /* number without matching suffix */ 7782 7783 retval = gen_expand_wildcards(num_pat, pat, num_file, file, flags); 7784 7785 /* When keeping all matches, return here */ 7786 if (flags & EW_KEEPALL) 7787 return retval; 7788 7789 #ifdef FEAT_WILDIGN 7790 /* 7791 * Remove names that match 'wildignore'. 7792 */ 7793 if (*p_wig) 7794 { 7795 char_u *ffname; 7796 7797 /* check all files in (*file)[] */ 7798 for (i = 0; i < *num_file; ++i) 7799 { 7800 ffname = FullName_save((*file)[i], FALSE); 7801 if (ffname == NULL) /* out of memory */ 7802 break; 7803 # ifdef VMS 7804 vms_remove_version(ffname); 7805 # endif 7806 if (match_file_list(p_wig, (*file)[i], ffname)) 7807 { 7808 /* remove this matching file from the list */ 7809 vim_free((*file)[i]); 7810 for (j = i; j + 1 < *num_file; ++j) 7811 (*file)[j] = (*file)[j + 1]; 7812 --*num_file; 7813 --i; 7814 } 7815 vim_free(ffname); 7816 } 7817 } 7818 #endif 7819 7820 /* 7821 * Move the names where 'suffixes' match to the end. 7822 */ 7823 if (*num_file > 1) 7824 { 7825 non_suf_match = 0; 7826 for (i = 0; i < *num_file; ++i) 7827 { 7828 if (!match_suffix((*file)[i])) 7829 { 7830 /* 7831 * Move the name without matching suffix to the front 7832 * of the list. 7833 */ 7834 p = (*file)[i]; 7835 for (j = i; j > non_suf_match; --j) 7836 (*file)[j] = (*file)[j - 1]; 7837 (*file)[non_suf_match++] = p; 7838 } 7839 } 7840 } 7841 7842 return retval; 7843 } 7844 7845 /* 7846 * Return TRUE if "fname" matches with an entry in 'suffixes'. 7847 */ 7848 int 7849 match_suffix(fname) 7850 char_u *fname; 7851 { 7852 int fnamelen, setsuflen; 7853 char_u *setsuf; 7854 #define MAXSUFLEN 30 /* maximum length of a file suffix */ 7855 char_u suf_buf[MAXSUFLEN]; 7856 7857 fnamelen = (int)STRLEN(fname); 7858 setsuflen = 0; 7859 for (setsuf = p_su; *setsuf; ) 7860 { 7861 setsuflen = copy_option_part(&setsuf, suf_buf, MAXSUFLEN, ".,"); 7862 if (fnamelen >= setsuflen 7863 && fnamencmp(suf_buf, fname + fnamelen - setsuflen, 7864 (size_t)setsuflen) == 0) 7865 break; 7866 setsuflen = 0; 7867 } 7868 return (setsuflen != 0); 7869 } 7870 7871 #if !defined(NO_EXPANDPATH) || defined(PROTO) 7872 7873 # ifdef VIM_BACKTICK 7874 static int vim_backtick __ARGS((char_u *p)); 7875 static int expand_backtick __ARGS((garray_T *gap, char_u *pat, int flags)); 7876 # endif 7877 7878 # if defined(MSDOS) || defined(FEAT_GUI_W16) || defined(WIN3264) 7879 /* 7880 * File name expansion code for MS-DOS, Win16 and Win32. It's here because 7881 * it's shared between these systems. 7882 */ 7883 # if defined(DJGPP) || defined(PROTO) 7884 # define _cdecl /* DJGPP doesn't have this */ 7885 # else 7886 # ifdef __BORLANDC__ 7887 # define _cdecl _RTLENTRYF 7888 # endif 7889 # endif 7890 7891 /* 7892 * comparison function for qsort in dos_expandpath() 7893 */ 7894 static int _cdecl 7895 pstrcmp(const void *a, const void *b) 7896 { 7897 return (pathcmp(*(char **)a, *(char **)b)); 7898 } 7899 7900 # ifndef WIN3264 7901 static void 7902 namelowcpy( 7903 char_u *d, 7904 char_u *s) 7905 { 7906 # ifdef DJGPP 7907 if (USE_LONG_FNAME) /* don't lower case on Windows 95/NT systems */ 7908 while (*s) 7909 *d++ = *s++; 7910 else 7911 # endif 7912 while (*s) 7913 *d++ = TOLOWER_LOC(*s++); 7914 *d = NUL; 7915 } 7916 # endif 7917 7918 /* 7919 * Recursively build up a list of files in "gap" matching the first wildcard 7920 * in `path'. Called by expand_wildcards(). 7921 * Return the number of matches found. 7922 * "path" has backslashes before chars that are not to be expanded, starting 7923 * at "path[wildoff]". 7924 */ 7925 static int 7926 dos_expandpath( 7927 garray_T *gap, 7928 char_u *path, 7929 int wildoff, 7930 int flags) /* EW_* flags */ 7931 { 7932 char_u *buf; 7933 char_u *path_end; 7934 char_u *p, *s, *e; 7935 int start_len = gap->ga_len; 7936 int ok; 7937 #ifdef WIN3264 7938 WIN32_FIND_DATA fb; 7939 HANDLE hFind = (HANDLE)0; 7940 # ifdef FEAT_MBYTE 7941 WIN32_FIND_DATAW wfb; 7942 WCHAR *wn = NULL; /* UCS-2 name, NULL when not used. */ 7943 # endif 7944 #else 7945 struct ffblk fb; 7946 #endif 7947 int matches; 7948 int starts_with_dot; 7949 int len; 7950 char_u *pat; 7951 regmatch_T regmatch; 7952 char_u *matchname; 7953 7954 /* make room for file name */ 7955 buf = alloc((unsigned int)STRLEN(path) + BASENAMELEN + 5); 7956 if (buf == NULL) 7957 return 0; 7958 7959 /* 7960 * Find the first part in the path name that contains a wildcard or a ~1. 7961 * Copy it into buf, including the preceding characters. 7962 */ 7963 p = buf; 7964 s = buf; 7965 e = NULL; 7966 path_end = path; 7967 while (*path_end != NUL) 7968 { 7969 /* May ignore a wildcard that has a backslash before it; it will 7970 * be removed by rem_backslash() or file_pat_to_reg_pat() below. */ 7971 if (path_end >= path + wildoff && rem_backslash(path_end)) 7972 *p++ = *path_end++; 7973 else if (*path_end == '\\' || *path_end == ':' || *path_end == '/') 7974 { 7975 if (e != NULL) 7976 break; 7977 s = p + 1; 7978 } 7979 else if (path_end >= path + wildoff 7980 && vim_strchr((char_u *)"*?[~", *path_end) != NULL) 7981 e = p; 7982 #ifdef FEAT_MBYTE 7983 if (has_mbyte) 7984 { 7985 len = (*mb_ptr2len_check)(path_end); 7986 STRNCPY(p, path_end, len); 7987 p += len; 7988 path_end += len; 7989 } 7990 else 7991 #endif 7992 *p++ = *path_end++; 7993 } 7994 e = p; 7995 *e = NUL; 7996 7997 /* now we have one wildcard component between s and e */ 7998 /* Remove backslashes between "wildoff" and the start of the wildcard 7999 * component. */ 8000 for (p = buf + wildoff; p < s; ++p) 8001 if (rem_backslash(p)) 8002 { 8003 STRCPY(p, p + 1); 8004 --e; 8005 --s; 8006 } 8007 8008 starts_with_dot = (*s == '.'); 8009 pat = file_pat_to_reg_pat(s, e, NULL, FALSE); 8010 if (pat == NULL) 8011 { 8012 vim_free(buf); 8013 return 0; 8014 } 8015 8016 /* compile the regexp into a program */ 8017 regmatch.rm_ic = TRUE; /* Always ignore case */ 8018 regmatch.regprog = vim_regcomp(pat, RE_MAGIC); 8019 vim_free(pat); 8020 8021 if (regmatch.regprog == NULL) 8022 { 8023 vim_free(buf); 8024 return 0; 8025 } 8026 8027 /* remember the pattern or file name being looked for */ 8028 matchname = vim_strsave(s); 8029 8030 /* Scan all files in the directory with "dir/ *.*" */ 8031 STRCPY(s, "*.*"); 8032 #ifdef WIN3264 8033 # ifdef FEAT_MBYTE 8034 if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) 8035 { 8036 /* The active codepage differs from 'encoding'. Attempt using the 8037 * wide function. If it fails because it is not implemented fall back 8038 * to the non-wide version (for Windows 98) */ 8039 wn = enc_to_ucs2(buf, NULL); 8040 if (wn != NULL) 8041 { 8042 hFind = FindFirstFileW(wn, &wfb); 8043 if (hFind == INVALID_HANDLE_VALUE 8044 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 8045 { 8046 vim_free(wn); 8047 wn = NULL; 8048 } 8049 } 8050 } 8051 8052 if (wn == NULL) 8053 # endif 8054 hFind = FindFirstFile(buf, &fb); 8055 ok = (hFind != INVALID_HANDLE_VALUE); 8056 #else 8057 /* If we are expanding wildcards we try both files and directories */ 8058 ok = (findfirst((char *)buf, &fb, 8059 (*path_end != NUL || (flags & EW_DIR)) ? FA_DIREC : 0) == 0); 8060 #endif 8061 8062 while (ok) 8063 { 8064 #ifdef WIN3264 8065 # ifdef FEAT_MBYTE 8066 if (wn != NULL) 8067 p = ucs2_to_enc(wfb.cFileName, NULL); /* p is allocated here */ 8068 else 8069 # endif 8070 p = (char_u *)fb.cFileName; 8071 #else 8072 p = (char_u *)fb.ff_name; 8073 #endif 8074 /* Ignore entries starting with a dot, unless when asked for. Accept 8075 * all entries found with "matchname". */ 8076 if ((p[0] != '.' || starts_with_dot) 8077 && (matchname == NULL 8078 || vim_regexec(®match, p, (colnr_T)0))) 8079 { 8080 #ifdef WIN3264 8081 STRCPY(s, p); 8082 #else 8083 namelowcpy(s, p); 8084 #endif 8085 len = (int)STRLEN(buf); 8086 STRCPY(buf + len, path_end); 8087 if (mch_has_exp_wildcard(path_end)) 8088 { 8089 /* need to expand another component of the path */ 8090 /* remove backslashes for the remaining components only */ 8091 (void)dos_expandpath(gap, buf, len + 1, flags); 8092 } 8093 else 8094 { 8095 /* no more wildcards, check if there is a match */ 8096 /* remove backslashes for the remaining components only */ 8097 if (*path_end != 0) 8098 backslash_halve(buf + len + 1); 8099 if (mch_getperm(buf) >= 0) /* add existing file */ 8100 addfile(gap, buf, flags); 8101 } 8102 } 8103 8104 #ifdef WIN3264 8105 # ifdef FEAT_MBYTE 8106 if (wn != NULL) 8107 { 8108 vim_free(p); 8109 ok = FindNextFileW(hFind, &wfb); 8110 } 8111 else 8112 # endif 8113 ok = FindNextFile(hFind, &fb); 8114 #else 8115 ok = (findnext(&fb) == 0); 8116 #endif 8117 8118 /* If no more matches and no match was used, try expanding the name 8119 * itself. Finds the long name of a short filename. */ 8120 if (!ok && matchname != NULL && gap->ga_len == start_len) 8121 { 8122 STRCPY(s, matchname); 8123 #ifdef WIN3264 8124 FindClose(hFind); 8125 # ifdef FEAT_MBYTE 8126 if (wn != NULL) 8127 { 8128 vim_free(wn); 8129 wn = enc_to_ucs2(buf, NULL); 8130 if (wn != NULL) 8131 hFind = FindFirstFileW(wn, &wfb); 8132 } 8133 if (wn == NULL) 8134 # endif 8135 hFind = FindFirstFile(buf, &fb); 8136 ok = (hFind != INVALID_HANDLE_VALUE); 8137 #else 8138 ok = (findfirst((char *)buf, &fb, 8139 (*path_end != NUL || (flags & EW_DIR)) ? FA_DIREC : 0) == 0); 8140 #endif 8141 vim_free(matchname); 8142 matchname = NULL; 8143 } 8144 } 8145 8146 #ifdef WIN3264 8147 FindClose(hFind); 8148 # ifdef FEAT_MBYTE 8149 vim_free(wn); 8150 # endif 8151 #endif 8152 vim_free(buf); 8153 vim_free(regmatch.regprog); 8154 vim_free(matchname); 8155 8156 matches = gap->ga_len - start_len; 8157 if (matches > 0) 8158 qsort(((char_u **)gap->ga_data) + start_len, (size_t)matches, 8159 sizeof(char_u *), pstrcmp); 8160 return matches; 8161 } 8162 8163 int 8164 mch_expandpath( 8165 garray_T *gap, 8166 char_u *path, 8167 int flags) /* EW_* flags */ 8168 { 8169 return dos_expandpath(gap, path, 0, flags); 8170 } 8171 # endif /* MSDOS || FEAT_GUI_W16 || WIN3264 */ 8172 8173 /* 8174 * Generic wildcard expansion code. 8175 * 8176 * Characters in "pat" that should not be expanded must be preceded with a 8177 * backslash. E.g., "/path\ with\ spaces/my\*star*" 8178 * 8179 * Return FAIL when no single file was found. In this case "num_file" is not 8180 * set, and "file" may contain an error message. 8181 * Return OK when some files found. "num_file" is set to the number of 8182 * matches, "file" to the array of matches. Call FreeWild() later. 8183 */ 8184 int 8185 gen_expand_wildcards(num_pat, pat, num_file, file, flags) 8186 int num_pat; /* number of input patterns */ 8187 char_u **pat; /* array of input patterns */ 8188 int *num_file; /* resulting number of files */ 8189 char_u ***file; /* array of resulting files */ 8190 int flags; /* EW_* flags */ 8191 { 8192 int i; 8193 garray_T ga; 8194 char_u *p; 8195 static int recursive = FALSE; 8196 int add_pat; 8197 8198 /* 8199 * expand_env() is called to expand things like "~user". If this fails, 8200 * it calls ExpandOne(), which brings us back here. In this case, always 8201 * call the machine specific expansion function, if possible. Otherwise, 8202 * return FAIL. 8203 */ 8204 if (recursive) 8205 #ifdef SPECIAL_WILDCHAR 8206 return mch_expand_wildcards(num_pat, pat, num_file, file, flags); 8207 #else 8208 return FAIL; 8209 #endif 8210 8211 #ifdef SPECIAL_WILDCHAR 8212 /* 8213 * If there are any special wildcard characters which we cannot handle 8214 * here, call machine specific function for all the expansion. This 8215 * avoids starting the shell for each argument separately. 8216 * For `=expr` do use the internal function. 8217 */ 8218 for (i = 0; i < num_pat; i++) 8219 { 8220 if (vim_strpbrk(pat[i], (char_u *)SPECIAL_WILDCHAR) != NULL 8221 # ifdef VIM_BACKTICK 8222 && !(vim_backtick(pat[i]) && pat[i][1] == '=') 8223 # endif 8224 ) 8225 return mch_expand_wildcards(num_pat, pat, num_file, file, flags); 8226 } 8227 #endif 8228 8229 recursive = TRUE; 8230 8231 /* 8232 * The matching file names are stored in a growarray. Init it empty. 8233 */ 8234 ga_init2(&ga, (int)sizeof(char_u *), 30); 8235 8236 for (i = 0; i < num_pat; ++i) 8237 { 8238 add_pat = -1; 8239 p = pat[i]; 8240 8241 #ifdef VIM_BACKTICK 8242 if (vim_backtick(p)) 8243 add_pat = expand_backtick(&ga, p, flags); 8244 else 8245 #endif 8246 { 8247 /* 8248 * First expand environment variables, "~/" and "~user/". 8249 */ 8250 if (vim_strpbrk(p, (char_u *)"$~") != NULL) 8251 { 8252 p = expand_env_save(p); 8253 if (p == NULL) 8254 p = pat[i]; 8255 #ifdef UNIX 8256 /* 8257 * On Unix, if expand_env() can't expand an environment 8258 * variable, use the shell to do that. Discard previously 8259 * found file names and start all over again. 8260 */ 8261 else if (vim_strpbrk(p, (char_u *)"$~") != NULL) 8262 { 8263 vim_free(p); 8264 ga_clear(&ga); 8265 i = mch_expand_wildcards(num_pat, pat, num_file, file, 8266 flags); 8267 recursive = FALSE; 8268 return i; 8269 } 8270 #endif 8271 } 8272 8273 /* 8274 * If there are wildcards: Expand file names and add each match to 8275 * the list. If there is no match, and EW_NOTFOUND is given, add 8276 * the pattern. 8277 * If there are no wildcards: Add the file name if it exists or 8278 * when EW_NOTFOUND is given. 8279 */ 8280 if (mch_has_exp_wildcard(p)) 8281 add_pat = mch_expandpath(&ga, p, flags); 8282 } 8283 8284 if (add_pat == -1 || (add_pat == 0 && (flags & EW_NOTFOUND))) 8285 { 8286 char_u *t = backslash_halve_save(p); 8287 8288 #if defined(MACOS_CLASSIC) 8289 slash_to_colon(t); 8290 #endif 8291 /* When EW_NOTFOUND is used, always add files and dirs. Makes 8292 * "vim c:/" work. */ 8293 if (flags & EW_NOTFOUND) 8294 addfile(&ga, t, flags | EW_DIR | EW_FILE); 8295 else if (mch_getperm(t) >= 0) 8296 addfile(&ga, t, flags); 8297 vim_free(t); 8298 } 8299 8300 if (p != pat[i]) 8301 vim_free(p); 8302 } 8303 8304 *num_file = ga.ga_len; 8305 *file = (ga.ga_data != NULL) ? (char_u **)ga.ga_data : (char_u **)""; 8306 8307 recursive = FALSE; 8308 8309 return (ga.ga_data != NULL) ? OK : FAIL; 8310 } 8311 8312 # ifdef VIM_BACKTICK 8313 8314 /* 8315 * Return TRUE if we can expand this backtick thing here. 8316 */ 8317 static int 8318 vim_backtick(p) 8319 char_u *p; 8320 { 8321 return (*p == '`' && *(p + 1) != NUL && *(p + STRLEN(p) - 1) == '`'); 8322 } 8323 8324 /* 8325 * Expand an item in `backticks` by executing it as a command. 8326 * Currently only works when pat[] starts and ends with a `. 8327 * Returns number of file names found. 8328 */ 8329 static int 8330 expand_backtick(gap, pat, flags) 8331 garray_T *gap; 8332 char_u *pat; 8333 int flags; /* EW_* flags */ 8334 { 8335 char_u *p; 8336 char_u *cmd; 8337 char_u *buffer; 8338 int cnt = 0; 8339 int i; 8340 8341 /* Create the command: lop off the backticks. */ 8342 cmd = vim_strnsave(pat + 1, (int)STRLEN(pat) - 2); 8343 if (cmd == NULL) 8344 return 0; 8345 8346 #ifdef FEAT_EVAL 8347 if (*cmd == '=') /* `={expr}`: Expand expression */ 8348 buffer = eval_to_string(cmd + 1, &p); 8349 else 8350 #endif 8351 buffer = get_cmd_output(cmd, (flags & EW_SILENT) ? SHELL_SILENT : 0); 8352 vim_free(cmd); 8353 if (buffer == NULL) 8354 return 0; 8355 8356 cmd = buffer; 8357 while (*cmd != NUL) 8358 { 8359 cmd = skipwhite(cmd); /* skip over white space */ 8360 p = cmd; 8361 while (*p != NUL && *p != '\r' && *p != '\n') /* skip over entry */ 8362 ++p; 8363 /* add an entry if it is not empty */ 8364 if (p > cmd) 8365 { 8366 i = *p; 8367 *p = NUL; 8368 addfile(gap, cmd, flags); 8369 *p = i; 8370 ++cnt; 8371 } 8372 cmd = p; 8373 while (*cmd != NUL && (*cmd == '\r' || *cmd == '\n')) 8374 ++cmd; 8375 } 8376 8377 vim_free(buffer); 8378 return cnt; 8379 } 8380 # endif /* VIM_BACKTICK */ 8381 8382 /* 8383 * Add a file to a file list. Accepted flags: 8384 * EW_DIR add directories 8385 * EW_FILE add files 8386 * EW_NOTFOUND add even when it doesn't exist 8387 * EW_ADDSLASH add slash after directory name 8388 */ 8389 void 8390 addfile(gap, f, flags) 8391 garray_T *gap; 8392 char_u *f; /* filename */ 8393 int flags; 8394 { 8395 char_u *p; 8396 int isdir; 8397 8398 /* if the file/dir doesn't exist, may not add it */ 8399 if (!(flags & EW_NOTFOUND) && mch_getperm(f) < 0) 8400 return; 8401 8402 #ifdef FNAME_ILLEGAL 8403 /* if the file/dir contains illegal characters, don't add it */ 8404 if (vim_strpbrk(f, (char_u *)FNAME_ILLEGAL) != NULL) 8405 return; 8406 #endif 8407 8408 isdir = mch_isdir(f); 8409 if ((isdir && !(flags & EW_DIR)) || (!isdir && !(flags & EW_FILE))) 8410 return; 8411 8412 /* Make room for another item in the file list. */ 8413 if (ga_grow(gap, 1) == FAIL) 8414 return; 8415 8416 p = alloc((unsigned)(STRLEN(f) + 1 + isdir)); 8417 if (p == NULL) 8418 return; 8419 8420 STRCPY(p, f); 8421 #ifdef BACKSLASH_IN_FILENAME 8422 slash_adjust(p); 8423 #endif 8424 /* 8425 * Append a slash or backslash after directory names if none is present. 8426 */ 8427 #ifndef DONT_ADD_PATHSEP_TO_DIR 8428 if (isdir && (flags & EW_ADDSLASH)) 8429 add_pathsep(p); 8430 #endif 8431 ((char_u **)gap->ga_data)[gap->ga_len++] = p; 8432 --gap->ga_room; 8433 } 8434 #endif /* !NO_EXPANDPATH */ 8435 8436 #if defined(VIM_BACKTICK) || defined(FEAT_EVAL) || defined(PROTO) 8437 8438 #ifndef SEEK_SET 8439 # define SEEK_SET 0 8440 #endif 8441 #ifndef SEEK_END 8442 # define SEEK_END 2 8443 #endif 8444 8445 /* 8446 * Get the stdout of an external command. 8447 * Returns an allocated string, or NULL for error. 8448 */ 8449 char_u * 8450 get_cmd_output(cmd, flags) 8451 char_u *cmd; 8452 int flags; /* can be SHELL_SILENT */ 8453 { 8454 char_u *tempname; 8455 char_u *command; 8456 char_u *buffer = NULL; 8457 int len; 8458 int i = 0; 8459 FILE *fd; 8460 8461 if (check_restricted() || check_secure()) 8462 return NULL; 8463 8464 /* get a name for the temp file */ 8465 if ((tempname = vim_tempname('o')) == NULL) 8466 { 8467 EMSG(_(e_notmp)); 8468 return NULL; 8469 } 8470 8471 /* Add the redirection stuff */ 8472 command = make_filter_cmd(cmd, NULL, tempname); 8473 if (command == NULL) 8474 goto done; 8475 8476 /* 8477 * Call the shell to execute the command (errors are ignored). 8478 * Don't check timestamps here. 8479 */ 8480 ++no_check_timestamps; 8481 call_shell(command, SHELL_DOOUT | SHELL_EXPAND | flags); 8482 --no_check_timestamps; 8483 8484 vim_free(command); 8485 8486 /* 8487 * read the names from the file into memory 8488 */ 8489 # ifdef VMS 8490 /* created temporary file is not allways readable as binary */ 8491 fd = mch_fopen((char *)tempname, "r"); 8492 # else 8493 fd = mch_fopen((char *)tempname, READBIN); 8494 # endif 8495 8496 if (fd == NULL) 8497 { 8498 EMSG2(_(e_notopen), tempname); 8499 goto done; 8500 } 8501 8502 fseek(fd, 0L, SEEK_END); 8503 len = ftell(fd); /* get size of temp file */ 8504 fseek(fd, 0L, SEEK_SET); 8505 8506 buffer = alloc(len + 1); 8507 if (buffer != NULL) 8508 i = (int)fread((char *)buffer, (size_t)1, (size_t)len, fd); 8509 fclose(fd); 8510 mch_remove(tempname); 8511 if (buffer == NULL) 8512 goto done; 8513 #ifdef VMS 8514 len = i; /* VMS doesn't give us what we asked for... */ 8515 #endif 8516 if (i != len) 8517 { 8518 EMSG2(_(e_notread), tempname); 8519 vim_free(buffer); 8520 buffer = NULL; 8521 } 8522 else 8523 buffer[len] = '\0'; /* make sure the buffer is terminated */ 8524 8525 done: 8526 vim_free(tempname); 8527 return buffer; 8528 } 8529 #endif 8530 8531 /* 8532 * Free the list of files returned by expand_wildcards() or other expansion 8533 * functions. 8534 */ 8535 void 8536 FreeWild(count, files) 8537 int count; 8538 char_u **files; 8539 { 8540 if (files == NULL || count <= 0) 8541 return; 8542 #if defined(__EMX__) && defined(__ALWAYS_HAS_TRAILING_NULL_POINTER) /* XXX */ 8543 /* 8544 * Is this still OK for when other functions than expand_wildcards() have 8545 * been used??? 8546 */ 8547 _fnexplodefree((char **)files); 8548 #else 8549 while (count--) 8550 vim_free(files[count]); 8551 vim_free(files); 8552 #endif 8553 } 8554 8555 /* 8556 * return TRUE when need to go to Insert mode because of 'insertmode'. 8557 * Don't do this when still processing a command or a mapping. 8558 * Don't do this when inside a ":normal" command. 8559 */ 8560 int 8561 goto_im() 8562 { 8563 return (p_im && stuff_empty() && typebuf_typed()); 8564 } 8565