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 * ops.c: implementation of various operators: op_shift, op_delete, op_tilde, 12 * op_change, op_yank, do_put, do_join 13 */ 14 15 #include "vim.h" 16 17 /* 18 * Number of registers. 19 * 0 = unnamed register, for normal yanks and puts 20 * 1..9 = registers '1' to '9', for deletes 21 * 10..35 = registers 'a' to 'z' 22 * 36 = delete register '-' 23 * 37 = Selection register '*'. Only if FEAT_CLIPBOARD defined 24 * 38 = Clipboard register '+'. Only if FEAT_CLIPBOARD and FEAT_X11 defined 25 */ 26 /* 27 * Symbolic names for some registers. 28 */ 29 #define DELETION_REGISTER 36 30 #ifdef FEAT_CLIPBOARD 31 # define STAR_REGISTER 37 32 # ifdef FEAT_X11 33 # define PLUS_REGISTER 38 34 # else 35 # define PLUS_REGISTER STAR_REGISTER /* there is only one */ 36 # endif 37 #endif 38 #ifdef FEAT_DND 39 # define TILDE_REGISTER (PLUS_REGISTER + 1) 40 #endif 41 42 #ifdef FEAT_CLIPBOARD 43 # ifdef FEAT_DND 44 # define NUM_REGISTERS (TILDE_REGISTER + 1) 45 # else 46 # define NUM_REGISTERS (PLUS_REGISTER + 1) 47 # endif 48 #else 49 # define NUM_REGISTERS 37 50 #endif 51 52 /* 53 * Each yank register is an array of pointers to lines. 54 */ 55 static struct yankreg 56 { 57 char_u **y_array; /* pointer to array of line pointers */ 58 linenr_T y_size; /* number of lines in y_array */ 59 char_u y_type; /* MLINE, MCHAR or MBLOCK */ 60 #ifdef FEAT_VISUAL 61 colnr_T y_width; /* only set if y_type == MBLOCK */ 62 #endif 63 } y_regs[NUM_REGISTERS]; 64 65 static struct yankreg *y_current; /* ptr to current yankreg */ 66 static int y_append; /* TRUE when appending */ 67 static struct yankreg *y_previous = NULL; /* ptr to last written yankreg */ 68 69 /* 70 * structure used by block_prep, op_delete and op_yank for blockwise operators 71 * also op_change, op_shift, op_insert, op_replace - AKelly 72 */ 73 struct block_def 74 { 75 int startspaces; /* 'extra' cols before first char */ 76 int endspaces; /* 'extra' cols after last char */ 77 int textlen; /* chars in block */ 78 char_u *textstart; /* pointer to 1st char (partially) in block */ 79 colnr_T textcol; /* index of chars (partially) in block */ 80 colnr_T start_vcol; /* start col of 1st char wholly inside block */ 81 colnr_T end_vcol; /* start col of 1st char wholly after block */ 82 #ifdef FEAT_VISUALEXTRA 83 int is_short; /* TRUE if line is too short to fit in block */ 84 int is_MAX; /* TRUE if curswant==MAXCOL when starting */ 85 int is_oneChar; /* TRUE if block within one character */ 86 int pre_whitesp; /* screen cols of ws before block */ 87 int pre_whitesp_c; /* chars of ws before block */ 88 colnr_T end_char_vcols; /* number of vcols of post-block char */ 89 #endif 90 colnr_T start_char_vcols; /* number of vcols of pre-block char */ 91 }; 92 93 #ifdef FEAT_VISUALEXTRA 94 static void shift_block __ARGS((oparg_T *oap, int amount)); 95 static void block_insert __ARGS((oparg_T *oap, char_u *s, int b_insert, struct block_def*bdp)); 96 #endif 97 static int stuff_yank __ARGS((int, char_u *)); 98 static void put_reedit_in_typebuf __ARGS((int silent)); 99 static int put_in_typebuf __ARGS((char_u *s, int esc, int colon, 100 int silent)); 101 static void stuffescaped __ARGS((char_u *arg, int literally)); 102 #ifdef FEAT_MBYTE 103 static void mb_adjust_opend __ARGS((oparg_T *oap)); 104 #endif 105 static void free_yank __ARGS((long)); 106 static void free_yank_all __ARGS((void)); 107 static int yank_copy_line __ARGS((struct block_def *bd, long y_idx)); 108 #ifdef FEAT_CLIPBOARD 109 static void copy_yank_reg __ARGS((struct yankreg *reg)); 110 # if defined(FEAT_VISUAL) || defined(FEAT_EVAL) 111 static void may_set_selection __ARGS((void)); 112 # endif 113 #endif 114 static void dis_msg __ARGS((char_u *p, int skip_esc)); 115 #if defined(FEAT_COMMENTS) || defined(PROTO) 116 static char_u *skip_comment __ARGS((char_u *line, int process, int include_space, int *is_comment)); 117 #endif 118 #ifdef FEAT_VISUAL 119 static void block_prep __ARGS((oparg_T *oap, struct block_def *, linenr_T, int)); 120 #endif 121 #if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL) 122 static void str_to_reg __ARGS((struct yankreg *y_ptr, int type, char_u *str, long len, long blocklen)); 123 #endif 124 static int ends_in_white __ARGS((linenr_T lnum)); 125 #ifdef FEAT_COMMENTS 126 static int same_leader __ARGS((linenr_T lnum, int, char_u *, int, char_u *)); 127 static int fmt_check_par __ARGS((linenr_T, int *, char_u **, int do_comments)); 128 #else 129 static int fmt_check_par __ARGS((linenr_T)); 130 #endif 131 132 /* 133 * The names of operators. 134 * IMPORTANT: Index must correspond with defines in vim.h!!! 135 * The third field indicates whether the operator always works on lines. 136 */ 137 static char opchars[][3] = 138 { 139 {NUL, NUL, FALSE}, /* OP_NOP */ 140 {'d', NUL, FALSE}, /* OP_DELETE */ 141 {'y', NUL, FALSE}, /* OP_YANK */ 142 {'c', NUL, FALSE}, /* OP_CHANGE */ 143 {'<', NUL, TRUE}, /* OP_LSHIFT */ 144 {'>', NUL, TRUE}, /* OP_RSHIFT */ 145 {'!', NUL, TRUE}, /* OP_FILTER */ 146 {'g', '~', FALSE}, /* OP_TILDE */ 147 {'=', NUL, TRUE}, /* OP_INDENT */ 148 {'g', 'q', TRUE}, /* OP_FORMAT */ 149 {':', NUL, TRUE}, /* OP_COLON */ 150 {'g', 'U', FALSE}, /* OP_UPPER */ 151 {'g', 'u', FALSE}, /* OP_LOWER */ 152 {'J', NUL, TRUE}, /* DO_JOIN */ 153 {'g', 'J', TRUE}, /* DO_JOIN_NS */ 154 {'g', '?', FALSE}, /* OP_ROT13 */ 155 {'r', NUL, FALSE}, /* OP_REPLACE */ 156 {'I', NUL, FALSE}, /* OP_INSERT */ 157 {'A', NUL, FALSE}, /* OP_APPEND */ 158 {'z', 'f', TRUE}, /* OP_FOLD */ 159 {'z', 'o', TRUE}, /* OP_FOLDOPEN */ 160 {'z', 'O', TRUE}, /* OP_FOLDOPENREC */ 161 {'z', 'c', TRUE}, /* OP_FOLDCLOSE */ 162 {'z', 'C', TRUE}, /* OP_FOLDCLOSEREC */ 163 {'z', 'd', TRUE}, /* OP_FOLDDEL */ 164 {'z', 'D', TRUE}, /* OP_FOLDDELREC */ 165 {'g', 'w', TRUE}, /* OP_FORMAT2 */ 166 {'g', '@', FALSE}, /* OP_FUNCTION */ 167 }; 168 169 /* 170 * Translate a command name into an operator type. 171 * Must only be called with a valid operator name! 172 */ 173 int 174 get_op_type(char1, char2) 175 int char1; 176 int char2; 177 { 178 int i; 179 180 if (char1 == 'r') /* ignore second character */ 181 return OP_REPLACE; 182 if (char1 == '~') /* when tilde is an operator */ 183 return OP_TILDE; 184 for (i = 0; ; ++i) 185 if (opchars[i][0] == char1 && opchars[i][1] == char2) 186 break; 187 return i; 188 } 189 190 #if defined(FEAT_VISUAL) || defined(PROTO) 191 /* 192 * Return TRUE if operator "op" always works on whole lines. 193 */ 194 int 195 op_on_lines(op) 196 int op; 197 { 198 return opchars[op][2]; 199 } 200 #endif 201 202 /* 203 * Get first operator command character. 204 * Returns 'g' or 'z' if there is another command character. 205 */ 206 int 207 get_op_char(optype) 208 int optype; 209 { 210 return opchars[optype][0]; 211 } 212 213 /* 214 * Get second operator command character. 215 */ 216 int 217 get_extra_op_char(optype) 218 int optype; 219 { 220 return opchars[optype][1]; 221 } 222 223 /* 224 * op_shift - handle a shift operation 225 */ 226 void 227 op_shift(oap, curs_top, amount) 228 oparg_T *oap; 229 int curs_top; 230 int amount; 231 { 232 long i; 233 int first_char; 234 char_u *s; 235 #ifdef FEAT_VISUAL 236 int block_col = 0; 237 #endif 238 239 if (u_save((linenr_T)(oap->start.lnum - 1), 240 (linenr_T)(oap->end.lnum + 1)) == FAIL) 241 return; 242 243 #ifdef FEAT_VISUAL 244 if (oap->block_mode) 245 block_col = curwin->w_cursor.col; 246 #endif 247 248 for (i = oap->line_count; --i >= 0; ) 249 { 250 first_char = *ml_get_curline(); 251 if (first_char == NUL) /* empty line */ 252 curwin->w_cursor.col = 0; 253 #ifdef FEAT_VISUALEXTRA 254 else if (oap->block_mode) 255 shift_block(oap, amount); 256 #endif 257 else 258 /* Move the line right if it doesn't start with '#', 'smartindent' 259 * isn't set or 'cindent' isn't set or '#' isn't in 'cino'. */ 260 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) 261 if (first_char != '#' || !preprocs_left()) 262 #endif 263 { 264 shift_line(oap->op_type == OP_LSHIFT, p_sr, amount, FALSE); 265 } 266 ++curwin->w_cursor.lnum; 267 } 268 269 changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L); 270 271 #ifdef FEAT_VISUAL 272 if (oap->block_mode) 273 { 274 curwin->w_cursor.lnum = oap->start.lnum; 275 curwin->w_cursor.col = block_col; 276 } 277 else 278 #endif 279 if (curs_top) /* put cursor on first line, for ">>" */ 280 { 281 curwin->w_cursor.lnum = oap->start.lnum; 282 beginline(BL_SOL | BL_FIX); /* shift_line() may have set cursor.col */ 283 } 284 else 285 --curwin->w_cursor.lnum; /* put cursor on last line, for ":>" */ 286 287 if (oap->line_count > p_report) 288 { 289 if (oap->op_type == OP_RSHIFT) 290 s = (char_u *)">"; 291 else 292 s = (char_u *)"<"; 293 if (oap->line_count == 1) 294 { 295 if (amount == 1) 296 sprintf((char *)IObuff, _("1 line %sed 1 time"), s); 297 else 298 sprintf((char *)IObuff, _("1 line %sed %d times"), s, amount); 299 } 300 else 301 { 302 if (amount == 1) 303 sprintf((char *)IObuff, _("%ld lines %sed 1 time"), 304 oap->line_count, s); 305 else 306 sprintf((char *)IObuff, _("%ld lines %sed %d times"), 307 oap->line_count, s, amount); 308 } 309 msg(IObuff); 310 } 311 312 /* 313 * Set "'[" and "']" marks. 314 */ 315 curbuf->b_op_start = oap->start; 316 curbuf->b_op_end.lnum = oap->end.lnum; 317 curbuf->b_op_end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum)); 318 if (curbuf->b_op_end.col > 0) 319 --curbuf->b_op_end.col; 320 } 321 322 /* 323 * shift the current line one shiftwidth left (if left != 0) or right 324 * leaves cursor on first blank in the line 325 */ 326 void 327 shift_line(left, round, amount, call_changed_bytes) 328 int left; 329 int round; 330 int amount; 331 int call_changed_bytes; /* call changed_bytes() */ 332 { 333 int count; 334 int i, j; 335 int p_sw = (int)get_sw_value(); 336 337 count = get_indent(); /* get current indent */ 338 339 if (round) /* round off indent */ 340 { 341 i = count / p_sw; /* number of p_sw rounded down */ 342 j = count % p_sw; /* extra spaces */ 343 if (j && left) /* first remove extra spaces */ 344 --amount; 345 if (left) 346 { 347 i -= amount; 348 if (i < 0) 349 i = 0; 350 } 351 else 352 i += amount; 353 count = i * p_sw; 354 } 355 else /* original vi indent */ 356 { 357 if (left) 358 { 359 count -= p_sw * amount; 360 if (count < 0) 361 count = 0; 362 } 363 else 364 count += p_sw * amount; 365 } 366 367 /* Set new indent */ 368 #ifdef FEAT_VREPLACE 369 if (State & VREPLACE_FLAG) 370 change_indent(INDENT_SET, count, FALSE, NUL, call_changed_bytes); 371 else 372 #endif 373 (void)set_indent(count, call_changed_bytes ? SIN_CHANGED : 0); 374 } 375 376 #if defined(FEAT_VISUALEXTRA) || defined(PROTO) 377 /* 378 * Shift one line of the current block one shiftwidth right or left. 379 * Leaves cursor on first character in block. 380 */ 381 static void 382 shift_block(oap, amount) 383 oparg_T *oap; 384 int amount; 385 { 386 int left = (oap->op_type == OP_LSHIFT); 387 int oldstate = State; 388 int total; 389 char_u *newp, *oldp; 390 int oldcol = curwin->w_cursor.col; 391 int p_sw = (int)get_sw_value(); 392 int p_ts = (int)curbuf->b_p_ts; 393 struct block_def bd; 394 int incr; 395 colnr_T ws_vcol; 396 int i = 0, j = 0; 397 int len; 398 #ifdef FEAT_RIGHTLEFT 399 int old_p_ri = p_ri; 400 401 p_ri = 0; /* don't want revins in indent */ 402 #endif 403 404 State = INSERT; /* don't want REPLACE for State */ 405 block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE); 406 if (bd.is_short) 407 return; 408 409 /* total is number of screen columns to be inserted/removed */ 410 total = amount * p_sw; 411 oldp = ml_get_curline(); 412 413 if (!left) 414 { 415 /* 416 * 1. Get start vcol 417 * 2. Total ws vcols 418 * 3. Divvy into TABs & spp 419 * 4. Construct new string 420 */ 421 total += bd.pre_whitesp; /* all virtual WS upto & incl a split TAB */ 422 ws_vcol = bd.start_vcol - bd.pre_whitesp; 423 if (bd.startspaces) 424 { 425 #ifdef FEAT_MBYTE 426 if (has_mbyte) 427 bd.textstart += (*mb_ptr2len)(bd.textstart); 428 else 429 #endif 430 ++bd.textstart; 431 } 432 for ( ; vim_iswhite(*bd.textstart); ) 433 { 434 incr = lbr_chartabsize_adv(&bd.textstart, (colnr_T)(bd.start_vcol)); 435 total += incr; 436 bd.start_vcol += incr; 437 } 438 /* OK, now total=all the VWS reqd, and textstart points at the 1st 439 * non-ws char in the block. */ 440 if (!curbuf->b_p_et) 441 i = ((ws_vcol % p_ts) + total) / p_ts; /* number of tabs */ 442 if (i) 443 j = ((ws_vcol % p_ts) + total) % p_ts; /* number of spp */ 444 else 445 j = total; 446 /* if we're splitting a TAB, allow for it */ 447 bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0); 448 len = (int)STRLEN(bd.textstart) + 1; 449 newp = alloc_check((unsigned)(bd.textcol + i + j + len)); 450 if (newp == NULL) 451 return; 452 vim_memset(newp, NUL, (size_t)(bd.textcol + i + j + len)); 453 mch_memmove(newp, oldp, (size_t)bd.textcol); 454 copy_chars(newp + bd.textcol, (size_t)i, TAB); 455 copy_spaces(newp + bd.textcol + i, (size_t)j); 456 /* the end */ 457 mch_memmove(newp + bd.textcol + i + j, bd.textstart, (size_t)len); 458 } 459 else /* left */ 460 { 461 colnr_T destination_col; /* column to which text in block will 462 be shifted */ 463 char_u *verbatim_copy_end; /* end of the part of the line which is 464 copied verbatim */ 465 colnr_T verbatim_copy_width;/* the (displayed) width of this part 466 of line */ 467 unsigned fill; /* nr of spaces that replace a TAB */ 468 unsigned new_line_len; /* the length of the line after the 469 block shift */ 470 size_t block_space_width; 471 size_t shift_amount; 472 char_u *non_white = bd.textstart; 473 colnr_T non_white_col; 474 475 /* 476 * Firstly, let's find the first non-whitespace character that is 477 * displayed after the block's start column and the character's column 478 * number. Also, let's calculate the width of all the whitespace 479 * characters that are displayed in the block and precede the searched 480 * non-whitespace character. 481 */ 482 483 /* If "bd.startspaces" is set, "bd.textstart" points to the character, 484 * the part of which is displayed at the block's beginning. Let's start 485 * searching from the next character. */ 486 if (bd.startspaces) 487 mb_ptr_adv(non_white); 488 489 /* The character's column is in "bd.start_vcol". */ 490 non_white_col = bd.start_vcol; 491 492 while (vim_iswhite(*non_white)) 493 { 494 incr = lbr_chartabsize_adv(&non_white, non_white_col); 495 non_white_col += incr; 496 } 497 498 block_space_width = non_white_col - oap->start_vcol; 499 /* We will shift by "total" or "block_space_width", whichever is less. 500 */ 501 shift_amount = (block_space_width < (size_t)total 502 ? block_space_width : (size_t)total); 503 504 /* The column to which we will shift the text. */ 505 destination_col = (colnr_T)(non_white_col - shift_amount); 506 507 /* Now let's find out how much of the beginning of the line we can 508 * reuse without modification. */ 509 verbatim_copy_end = bd.textstart; 510 verbatim_copy_width = bd.start_vcol; 511 512 /* If "bd.startspaces" is set, "bd.textstart" points to the character 513 * preceding the block. We have to subtract its width to obtain its 514 * column number. */ 515 if (bd.startspaces) 516 verbatim_copy_width -= bd.start_char_vcols; 517 while (verbatim_copy_width < destination_col) 518 { 519 incr = lbr_chartabsize(verbatim_copy_end, verbatim_copy_width); 520 if (verbatim_copy_width + incr > destination_col) 521 break; 522 verbatim_copy_width += incr; 523 mb_ptr_adv(verbatim_copy_end); 524 } 525 526 /* If "destination_col" is different from the width of the initial 527 * part of the line that will be copied, it means we encountered a tab 528 * character, which we will have to partly replace with spaces. */ 529 fill = destination_col - verbatim_copy_width; 530 531 /* The replacement line will consist of: 532 * - the beginning of the original line up to "verbatim_copy_end", 533 * - "fill" number of spaces, 534 * - the rest of the line, pointed to by non_white. */ 535 new_line_len = (unsigned)(verbatim_copy_end - oldp) 536 + fill 537 + (unsigned)STRLEN(non_white) + 1; 538 539 newp = alloc_check(new_line_len); 540 if (newp == NULL) 541 return; 542 mch_memmove(newp, oldp, (size_t)(verbatim_copy_end - oldp)); 543 copy_spaces(newp + (verbatim_copy_end - oldp), (size_t)fill); 544 STRMOVE(newp + (verbatim_copy_end - oldp) + fill, non_white); 545 } 546 /* replace the line */ 547 ml_replace(curwin->w_cursor.lnum, newp, FALSE); 548 changed_bytes(curwin->w_cursor.lnum, (colnr_T)bd.textcol); 549 State = oldstate; 550 curwin->w_cursor.col = oldcol; 551 #ifdef FEAT_RIGHTLEFT 552 p_ri = old_p_ri; 553 #endif 554 } 555 #endif 556 557 #ifdef FEAT_VISUALEXTRA 558 /* 559 * Insert string "s" (b_insert ? before : after) block :AKelly 560 * Caller must prepare for undo. 561 */ 562 static void 563 block_insert(oap, s, b_insert, bdp) 564 oparg_T *oap; 565 char_u *s; 566 int b_insert; 567 struct block_def *bdp; 568 { 569 int p_ts; 570 int count = 0; /* extra spaces to replace a cut TAB */ 571 int spaces = 0; /* non-zero if cutting a TAB */ 572 colnr_T offset; /* pointer along new line */ 573 unsigned s_len; /* STRLEN(s) */ 574 char_u *newp, *oldp; /* new, old lines */ 575 linenr_T lnum; /* loop var */ 576 int oldstate = State; 577 578 State = INSERT; /* don't want REPLACE for State */ 579 s_len = (unsigned)STRLEN(s); 580 581 for (lnum = oap->start.lnum + 1; lnum <= oap->end.lnum; lnum++) 582 { 583 block_prep(oap, bdp, lnum, TRUE); 584 if (bdp->is_short && b_insert) 585 continue; /* OP_INSERT, line ends before block start */ 586 587 oldp = ml_get(lnum); 588 589 if (b_insert) 590 { 591 p_ts = bdp->start_char_vcols; 592 spaces = bdp->startspaces; 593 if (spaces != 0) 594 count = p_ts - 1; /* we're cutting a TAB */ 595 offset = bdp->textcol; 596 } 597 else /* append */ 598 { 599 p_ts = bdp->end_char_vcols; 600 if (!bdp->is_short) /* spaces = padding after block */ 601 { 602 spaces = (bdp->endspaces ? p_ts - bdp->endspaces : 0); 603 if (spaces != 0) 604 count = p_ts - 1; /* we're cutting a TAB */ 605 offset = bdp->textcol + bdp->textlen - (spaces != 0); 606 } 607 else /* spaces = padding to block edge */ 608 { 609 /* if $ used, just append to EOL (ie spaces==0) */ 610 if (!bdp->is_MAX) 611 spaces = (oap->end_vcol - bdp->end_vcol) + 1; 612 count = spaces; 613 offset = bdp->textcol + bdp->textlen; 614 } 615 } 616 617 newp = alloc_check((unsigned)(STRLEN(oldp)) + s_len + count + 1); 618 if (newp == NULL) 619 continue; 620 621 /* copy up to shifted part */ 622 mch_memmove(newp, oldp, (size_t)(offset)); 623 oldp += offset; 624 625 /* insert pre-padding */ 626 copy_spaces(newp + offset, (size_t)spaces); 627 628 /* copy the new text */ 629 mch_memmove(newp + offset + spaces, s, (size_t)s_len); 630 offset += s_len; 631 632 if (spaces && !bdp->is_short) 633 { 634 /* insert post-padding */ 635 copy_spaces(newp + offset + spaces, (size_t)(p_ts - spaces)); 636 /* We're splitting a TAB, don't copy it. */ 637 oldp++; 638 /* We allowed for that TAB, remember this now */ 639 count++; 640 } 641 642 if (spaces > 0) 643 offset += count; 644 STRMOVE(newp + offset, oldp); 645 646 ml_replace(lnum, newp, FALSE); 647 648 if (lnum == oap->end.lnum) 649 { 650 /* Set "']" mark to the end of the block instead of the end of 651 * the insert in the first line. */ 652 curbuf->b_op_end.lnum = oap->end.lnum; 653 curbuf->b_op_end.col = offset; 654 } 655 } /* for all lnum */ 656 657 changed_lines(oap->start.lnum + 1, 0, oap->end.lnum + 1, 0L); 658 659 State = oldstate; 660 } 661 #endif 662 663 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(PROTO) 664 /* 665 * op_reindent - handle reindenting a block of lines. 666 */ 667 void 668 op_reindent(oap, how) 669 oparg_T *oap; 670 int (*how) __ARGS((void)); 671 { 672 long i; 673 char_u *l; 674 int count; 675 linenr_T first_changed = 0; 676 linenr_T last_changed = 0; 677 linenr_T start_lnum = curwin->w_cursor.lnum; 678 679 /* Don't even try when 'modifiable' is off. */ 680 if (!curbuf->b_p_ma) 681 { 682 EMSG(_(e_modifiable)); 683 return; 684 } 685 686 for (i = oap->line_count; --i >= 0 && !got_int; ) 687 { 688 /* it's a slow thing to do, so give feedback so there's no worry that 689 * the computer's just hung. */ 690 691 if (i > 1 692 && (i % 50 == 0 || i == oap->line_count - 1) 693 && oap->line_count > p_report) 694 smsg((char_u *)_("%ld lines to indent... "), i); 695 696 /* 697 * Be vi-compatible: For lisp indenting the first line is not 698 * indented, unless there is only one line. 699 */ 700 #ifdef FEAT_LISP 701 if (i != oap->line_count - 1 || oap->line_count == 1 702 || how != get_lisp_indent) 703 #endif 704 { 705 l = skipwhite(ml_get_curline()); 706 if (*l == NUL) /* empty or blank line */ 707 count = 0; 708 else 709 count = how(); /* get the indent for this line */ 710 711 if (set_indent(count, SIN_UNDO)) 712 { 713 /* did change the indent, call changed_lines() later */ 714 if (first_changed == 0) 715 first_changed = curwin->w_cursor.lnum; 716 last_changed = curwin->w_cursor.lnum; 717 } 718 } 719 ++curwin->w_cursor.lnum; 720 curwin->w_cursor.col = 0; /* make sure it's valid */ 721 } 722 723 /* put cursor on first non-blank of indented line */ 724 curwin->w_cursor.lnum = start_lnum; 725 beginline(BL_SOL | BL_FIX); 726 727 /* Mark changed lines so that they will be redrawn. When Visual 728 * highlighting was present, need to continue until the last line. When 729 * there is no change still need to remove the Visual highlighting. */ 730 if (last_changed != 0) 731 changed_lines(first_changed, 0, 732 #ifdef FEAT_VISUAL 733 oap->is_VIsual ? start_lnum + oap->line_count : 734 #endif 735 last_changed + 1, 0L); 736 #ifdef FEAT_VISUAL 737 else if (oap->is_VIsual) 738 redraw_curbuf_later(INVERTED); 739 #endif 740 741 if (oap->line_count > p_report) 742 { 743 i = oap->line_count - (i + 1); 744 if (i == 1) 745 MSG(_("1 line indented ")); 746 else 747 smsg((char_u *)_("%ld lines indented "), i); 748 } 749 /* set '[ and '] marks */ 750 curbuf->b_op_start = oap->start; 751 curbuf->b_op_end = oap->end; 752 } 753 #endif /* defined(FEAT_LISP) || defined(FEAT_CINDENT) */ 754 755 #if defined(FEAT_EVAL) || defined(PROTO) 756 /* 757 * Keep the last expression line here, for repeating. 758 */ 759 static char_u *expr_line = NULL; 760 761 /* 762 * Get an expression for the "\"=expr1" or "CTRL-R =expr1" 763 * Returns '=' when OK, NUL otherwise. 764 */ 765 int 766 get_expr_register() 767 { 768 char_u *new_line; 769 770 new_line = getcmdline('=', 0L, 0); 771 if (new_line == NULL) 772 return NUL; 773 if (*new_line == NUL) /* use previous line */ 774 vim_free(new_line); 775 else 776 set_expr_line(new_line); 777 return '='; 778 } 779 780 /* 781 * Set the expression for the '=' register. 782 * Argument must be an allocated string. 783 */ 784 void 785 set_expr_line(new_line) 786 char_u *new_line; 787 { 788 vim_free(expr_line); 789 expr_line = new_line; 790 } 791 792 /* 793 * Get the result of the '=' register expression. 794 * Returns a pointer to allocated memory, or NULL for failure. 795 */ 796 char_u * 797 get_expr_line() 798 { 799 char_u *expr_copy; 800 char_u *rv; 801 static int nested = 0; 802 803 if (expr_line == NULL) 804 return NULL; 805 806 /* Make a copy of the expression, because evaluating it may cause it to be 807 * changed. */ 808 expr_copy = vim_strsave(expr_line); 809 if (expr_copy == NULL) 810 return NULL; 811 812 /* When we are invoked recursively limit the evaluation to 10 levels. 813 * Then return the string as-is. */ 814 if (nested >= 10) 815 return expr_copy; 816 817 ++nested; 818 rv = eval_to_string(expr_copy, NULL, TRUE); 819 --nested; 820 vim_free(expr_copy); 821 return rv; 822 } 823 824 /* 825 * Get the '=' register expression itself, without evaluating it. 826 */ 827 char_u * 828 get_expr_line_src() 829 { 830 if (expr_line == NULL) 831 return NULL; 832 return vim_strsave(expr_line); 833 } 834 #endif /* FEAT_EVAL */ 835 836 /* 837 * Check if 'regname' is a valid name of a yank register. 838 * Note: There is no check for 0 (default register), caller should do this 839 */ 840 int 841 valid_yank_reg(regname, writing) 842 int regname; 843 int writing; /* if TRUE check for writable registers */ 844 { 845 if ( (regname > 0 && ASCII_ISALNUM(regname)) 846 || (!writing && vim_strchr((char_u *) 847 #ifdef FEAT_EVAL 848 "/.%#:=" 849 #else 850 "/.%#:" 851 #endif 852 , regname) != NULL) 853 || regname == '"' 854 || regname == '-' 855 || regname == '_' 856 #ifdef FEAT_CLIPBOARD 857 || regname == '*' 858 || regname == '+' 859 #endif 860 #ifdef FEAT_DND 861 || (!writing && regname == '~') 862 #endif 863 ) 864 return TRUE; 865 return FALSE; 866 } 867 868 /* 869 * Set y_current and y_append, according to the value of "regname". 870 * Cannot handle the '_' register. 871 * Must only be called with a valid register name! 872 * 873 * If regname is 0 and writing, use register 0 874 * If regname is 0 and reading, use previous register 875 */ 876 void 877 get_yank_register(regname, writing) 878 int regname; 879 int writing; 880 { 881 int i; 882 883 y_append = FALSE; 884 if ((regname == 0 || regname == '"') && !writing && y_previous != NULL) 885 { 886 y_current = y_previous; 887 return; 888 } 889 i = regname; 890 if (VIM_ISDIGIT(i)) 891 i -= '0'; 892 else if (ASCII_ISLOWER(i)) 893 i = CharOrdLow(i) + 10; 894 else if (ASCII_ISUPPER(i)) 895 { 896 i = CharOrdUp(i) + 10; 897 y_append = TRUE; 898 } 899 else if (regname == '-') 900 i = DELETION_REGISTER; 901 #ifdef FEAT_CLIPBOARD 902 /* When selection is not available, use register 0 instead of '*' */ 903 else if (clip_star.available && regname == '*') 904 i = STAR_REGISTER; 905 /* When clipboard is not available, use register 0 instead of '+' */ 906 else if (clip_plus.available && regname == '+') 907 i = PLUS_REGISTER; 908 #endif 909 #ifdef FEAT_DND 910 else if (!writing && regname == '~') 911 i = TILDE_REGISTER; 912 #endif 913 else /* not 0-9, a-z, A-Z or '-': use register 0 */ 914 i = 0; 915 y_current = &(y_regs[i]); 916 if (writing) /* remember the register we write into for do_put() */ 917 y_previous = y_current; 918 } 919 920 #if defined(FEAT_CLIPBOARD) || defined(PROTO) 921 /* 922 * When "regname" is a clipboard register, obtain the selection. If it's not 923 * available return zero, otherwise return "regname". 924 */ 925 int 926 may_get_selection(regname) 927 int regname; 928 { 929 if (regname == '*') 930 { 931 if (!clip_star.available) 932 regname = 0; 933 else 934 clip_get_selection(&clip_star); 935 } 936 else if (regname == '+') 937 { 938 if (!clip_plus.available) 939 regname = 0; 940 else 941 clip_get_selection(&clip_plus); 942 } 943 return regname; 944 } 945 #endif 946 947 #if defined(FEAT_VISUAL) || defined(PROTO) 948 /* 949 * Obtain the contents of a "normal" register. The register is made empty. 950 * The returned pointer has allocated memory, use put_register() later. 951 */ 952 void * 953 get_register(name, copy) 954 int name; 955 int copy; /* make a copy, if FALSE make register empty. */ 956 { 957 struct yankreg *reg; 958 int i; 959 960 #ifdef FEAT_CLIPBOARD 961 /* When Visual area changed, may have to update selection. Obtain the 962 * selection too. */ 963 if (name == '*' && clip_star.available) 964 { 965 if (clip_isautosel_star()) 966 clip_update_selection(&clip_star); 967 may_get_selection(name); 968 } 969 if (name == '+' && clip_plus.available) 970 { 971 if (clip_isautosel_plus()) 972 clip_update_selection(&clip_plus); 973 may_get_selection(name); 974 } 975 #endif 976 977 get_yank_register(name, 0); 978 reg = (struct yankreg *)alloc((unsigned)sizeof(struct yankreg)); 979 if (reg != NULL) 980 { 981 *reg = *y_current; 982 if (copy) 983 { 984 /* If we run out of memory some or all of the lines are empty. */ 985 if (reg->y_size == 0) 986 reg->y_array = NULL; 987 else 988 reg->y_array = (char_u **)alloc((unsigned)(sizeof(char_u *) 989 * reg->y_size)); 990 if (reg->y_array != NULL) 991 { 992 for (i = 0; i < reg->y_size; ++i) 993 reg->y_array[i] = vim_strsave(y_current->y_array[i]); 994 } 995 } 996 else 997 y_current->y_array = NULL; 998 } 999 return (void *)reg; 1000 } 1001 1002 /* 1003 * Put "reg" into register "name". Free any previous contents and "reg". 1004 */ 1005 void 1006 put_register(name, reg) 1007 int name; 1008 void *reg; 1009 { 1010 get_yank_register(name, 0); 1011 free_yank_all(); 1012 *y_current = *(struct yankreg *)reg; 1013 vim_free(reg); 1014 1015 # ifdef FEAT_CLIPBOARD 1016 /* Send text written to clipboard register to the clipboard. */ 1017 may_set_selection(); 1018 # endif 1019 } 1020 1021 void 1022 free_register(reg) 1023 void *reg; 1024 { 1025 struct yankreg tmp; 1026 1027 tmp = *y_current; 1028 *y_current = *(struct yankreg *)reg; 1029 free_yank_all(); 1030 vim_free(reg); 1031 *y_current = tmp; 1032 } 1033 #endif 1034 1035 #if defined(FEAT_MOUSE) || defined(PROTO) 1036 /* 1037 * return TRUE if the current yank register has type MLINE 1038 */ 1039 int 1040 yank_register_mline(regname) 1041 int regname; 1042 { 1043 if (regname != 0 && !valid_yank_reg(regname, FALSE)) 1044 return FALSE; 1045 if (regname == '_') /* black hole is always empty */ 1046 return FALSE; 1047 get_yank_register(regname, FALSE); 1048 return (y_current->y_type == MLINE); 1049 } 1050 #endif 1051 1052 /* 1053 * Start or stop recording into a yank register. 1054 * 1055 * Return FAIL for failure, OK otherwise. 1056 */ 1057 int 1058 do_record(c) 1059 int c; 1060 { 1061 char_u *p; 1062 static int regname; 1063 struct yankreg *old_y_previous, *old_y_current; 1064 int retval; 1065 1066 if (Recording == FALSE) /* start recording */ 1067 { 1068 /* registers 0-9, a-z and " are allowed */ 1069 if (c < 0 || (!ASCII_ISALNUM(c) && c != '"')) 1070 retval = FAIL; 1071 else 1072 { 1073 Recording = TRUE; 1074 showmode(); 1075 regname = c; 1076 retval = OK; 1077 } 1078 } 1079 else /* stop recording */ 1080 { 1081 /* 1082 * Get the recorded key hits. K_SPECIAL and CSI will be escaped, this 1083 * needs to be removed again to put it in a register. exec_reg then 1084 * adds the escaping back later. 1085 */ 1086 Recording = FALSE; 1087 MSG(""); 1088 p = get_recorded(); 1089 if (p == NULL) 1090 retval = FAIL; 1091 else 1092 { 1093 /* Remove escaping for CSI and K_SPECIAL in multi-byte chars. */ 1094 vim_unescape_csi(p); 1095 1096 /* 1097 * We don't want to change the default register here, so save and 1098 * restore the current register name. 1099 */ 1100 old_y_previous = y_previous; 1101 old_y_current = y_current; 1102 1103 retval = stuff_yank(regname, p); 1104 1105 y_previous = old_y_previous; 1106 y_current = old_y_current; 1107 } 1108 } 1109 return retval; 1110 } 1111 1112 /* 1113 * Stuff string "p" into yank register "regname" as a single line (append if 1114 * uppercase). "p" must have been alloced. 1115 * 1116 * return FAIL for failure, OK otherwise 1117 */ 1118 static int 1119 stuff_yank(regname, p) 1120 int regname; 1121 char_u *p; 1122 { 1123 char_u *lp; 1124 char_u **pp; 1125 1126 /* check for read-only register */ 1127 if (regname != 0 && !valid_yank_reg(regname, TRUE)) 1128 { 1129 vim_free(p); 1130 return FAIL; 1131 } 1132 if (regname == '_') /* black hole: don't do anything */ 1133 { 1134 vim_free(p); 1135 return OK; 1136 } 1137 get_yank_register(regname, TRUE); 1138 if (y_append && y_current->y_array != NULL) 1139 { 1140 pp = &(y_current->y_array[y_current->y_size - 1]); 1141 lp = lalloc((long_u)(STRLEN(*pp) + STRLEN(p) + 1), TRUE); 1142 if (lp == NULL) 1143 { 1144 vim_free(p); 1145 return FAIL; 1146 } 1147 STRCPY(lp, *pp); 1148 STRCAT(lp, p); 1149 vim_free(p); 1150 vim_free(*pp); 1151 *pp = lp; 1152 } 1153 else 1154 { 1155 free_yank_all(); 1156 if ((y_current->y_array = 1157 (char_u **)alloc((unsigned)sizeof(char_u *))) == NULL) 1158 { 1159 vim_free(p); 1160 return FAIL; 1161 } 1162 y_current->y_array[0] = p; 1163 y_current->y_size = 1; 1164 y_current->y_type = MCHAR; /* used to be MLINE, why? */ 1165 } 1166 return OK; 1167 } 1168 1169 static int execreg_lastc = NUL; 1170 1171 /* 1172 * execute a yank register: copy it into the stuff buffer 1173 * 1174 * return FAIL for failure, OK otherwise 1175 */ 1176 int 1177 do_execreg(regname, colon, addcr, silent) 1178 int regname; 1179 int colon; /* insert ':' before each line */ 1180 int addcr; /* always add '\n' to end of line */ 1181 int silent; /* set "silent" flag in typeahead buffer */ 1182 { 1183 long i; 1184 char_u *p; 1185 int retval = OK; 1186 int remap; 1187 1188 if (regname == '@') /* repeat previous one */ 1189 { 1190 if (execreg_lastc == NUL) 1191 { 1192 EMSG(_("E748: No previously used register")); 1193 return FAIL; 1194 } 1195 regname = execreg_lastc; 1196 } 1197 /* check for valid regname */ 1198 if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE)) 1199 { 1200 emsg_invreg(regname); 1201 return FAIL; 1202 } 1203 execreg_lastc = regname; 1204 1205 #ifdef FEAT_CLIPBOARD 1206 regname = may_get_selection(regname); 1207 #endif 1208 1209 if (regname == '_') /* black hole: don't stuff anything */ 1210 return OK; 1211 1212 #ifdef FEAT_CMDHIST 1213 if (regname == ':') /* use last command line */ 1214 { 1215 if (last_cmdline == NULL) 1216 { 1217 EMSG(_(e_nolastcmd)); 1218 return FAIL; 1219 } 1220 vim_free(new_last_cmdline); /* don't keep the cmdline containing @: */ 1221 new_last_cmdline = NULL; 1222 /* Escape all control characters with a CTRL-V */ 1223 p = vim_strsave_escaped_ext(last_cmdline, 1224 (char_u *)"\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037", Ctrl_V, FALSE); 1225 if (p != NULL) 1226 { 1227 /* When in Visual mode "'<,'>" will be prepended to the command. 1228 * Remove it when it's already there. */ 1229 if (VIsual_active && STRNCMP(p, "'<,'>", 5) == 0) 1230 retval = put_in_typebuf(p + 5, TRUE, TRUE, silent); 1231 else 1232 retval = put_in_typebuf(p, TRUE, TRUE, silent); 1233 } 1234 vim_free(p); 1235 } 1236 #endif 1237 #ifdef FEAT_EVAL 1238 else if (regname == '=') 1239 { 1240 p = get_expr_line(); 1241 if (p == NULL) 1242 return FAIL; 1243 retval = put_in_typebuf(p, TRUE, colon, silent); 1244 vim_free(p); 1245 } 1246 #endif 1247 else if (regname == '.') /* use last inserted text */ 1248 { 1249 p = get_last_insert_save(); 1250 if (p == NULL) 1251 { 1252 EMSG(_(e_noinstext)); 1253 return FAIL; 1254 } 1255 retval = put_in_typebuf(p, FALSE, colon, silent); 1256 vim_free(p); 1257 } 1258 else 1259 { 1260 get_yank_register(regname, FALSE); 1261 if (y_current->y_array == NULL) 1262 return FAIL; 1263 1264 /* Disallow remaping for ":@r". */ 1265 remap = colon ? REMAP_NONE : REMAP_YES; 1266 1267 /* 1268 * Insert lines into typeahead buffer, from last one to first one. 1269 */ 1270 put_reedit_in_typebuf(silent); 1271 for (i = y_current->y_size; --i >= 0; ) 1272 { 1273 char_u *escaped; 1274 1275 /* insert NL between lines and after last line if type is MLINE */ 1276 if (y_current->y_type == MLINE || i < y_current->y_size - 1 1277 || addcr) 1278 { 1279 if (ins_typebuf((char_u *)"\n", remap, 0, TRUE, silent) == FAIL) 1280 return FAIL; 1281 } 1282 escaped = vim_strsave_escape_csi(y_current->y_array[i]); 1283 if (escaped == NULL) 1284 return FAIL; 1285 retval = ins_typebuf(escaped, remap, 0, TRUE, silent); 1286 vim_free(escaped); 1287 if (retval == FAIL) 1288 return FAIL; 1289 if (colon && ins_typebuf((char_u *)":", remap, 0, TRUE, silent) 1290 == FAIL) 1291 return FAIL; 1292 } 1293 Exec_reg = TRUE; /* disable the 'q' command */ 1294 } 1295 return retval; 1296 } 1297 1298 /* 1299 * If "restart_edit" is not zero, put it in the typeahead buffer, so that it's 1300 * used only after other typeahead has been processed. 1301 */ 1302 static void 1303 put_reedit_in_typebuf(silent) 1304 int silent; 1305 { 1306 char_u buf[3]; 1307 1308 if (restart_edit != NUL) 1309 { 1310 if (restart_edit == 'V') 1311 { 1312 buf[0] = 'g'; 1313 buf[1] = 'R'; 1314 buf[2] = NUL; 1315 } 1316 else 1317 { 1318 buf[0] = restart_edit == 'I' ? 'i' : restart_edit; 1319 buf[1] = NUL; 1320 } 1321 if (ins_typebuf(buf, REMAP_NONE, 0, TRUE, silent) == OK) 1322 restart_edit = NUL; 1323 } 1324 } 1325 1326 /* 1327 * Insert register contents "s" into the typeahead buffer, so that it will be 1328 * executed again. 1329 * When "esc" is TRUE it is to be taken literally: Escape CSI characters and 1330 * no remapping. 1331 */ 1332 static int 1333 put_in_typebuf(s, esc, colon, silent) 1334 char_u *s; 1335 int esc; 1336 int colon; /* add ':' before the line */ 1337 int silent; 1338 { 1339 int retval = OK; 1340 1341 put_reedit_in_typebuf(silent); 1342 if (colon) 1343 retval = ins_typebuf((char_u *)"\n", REMAP_NONE, 0, TRUE, silent); 1344 if (retval == OK) 1345 { 1346 char_u *p; 1347 1348 if (esc) 1349 p = vim_strsave_escape_csi(s); 1350 else 1351 p = s; 1352 if (p == NULL) 1353 retval = FAIL; 1354 else 1355 retval = ins_typebuf(p, esc ? REMAP_NONE : REMAP_YES, 1356 0, TRUE, silent); 1357 if (esc) 1358 vim_free(p); 1359 } 1360 if (colon && retval == OK) 1361 retval = ins_typebuf((char_u *)":", REMAP_NONE, 0, TRUE, silent); 1362 return retval; 1363 } 1364 1365 /* 1366 * Insert a yank register: copy it into the Read buffer. 1367 * Used by CTRL-R command and middle mouse button in insert mode. 1368 * 1369 * return FAIL for failure, OK otherwise 1370 */ 1371 int 1372 insert_reg(regname, literally) 1373 int regname; 1374 int literally; /* insert literally, not as if typed */ 1375 { 1376 long i; 1377 int retval = OK; 1378 char_u *arg; 1379 int allocated; 1380 1381 /* 1382 * It is possible to get into an endless loop by having CTRL-R a in 1383 * register a and then, in insert mode, doing CTRL-R a. 1384 * If you hit CTRL-C, the loop will be broken here. 1385 */ 1386 ui_breakcheck(); 1387 if (got_int) 1388 return FAIL; 1389 1390 /* check for valid regname */ 1391 if (regname != NUL && !valid_yank_reg(regname, FALSE)) 1392 return FAIL; 1393 1394 #ifdef FEAT_CLIPBOARD 1395 regname = may_get_selection(regname); 1396 #endif 1397 1398 if (regname == '.') /* insert last inserted text */ 1399 retval = stuff_inserted(NUL, 1L, TRUE); 1400 else if (get_spec_reg(regname, &arg, &allocated, TRUE)) 1401 { 1402 if (arg == NULL) 1403 return FAIL; 1404 stuffescaped(arg, literally); 1405 if (allocated) 1406 vim_free(arg); 1407 } 1408 else /* name or number register */ 1409 { 1410 get_yank_register(regname, FALSE); 1411 if (y_current->y_array == NULL) 1412 retval = FAIL; 1413 else 1414 { 1415 for (i = 0; i < y_current->y_size; ++i) 1416 { 1417 stuffescaped(y_current->y_array[i], literally); 1418 /* 1419 * Insert a newline between lines and after last line if 1420 * y_type is MLINE. 1421 */ 1422 if (y_current->y_type == MLINE || i < y_current->y_size - 1) 1423 stuffcharReadbuff('\n'); 1424 } 1425 } 1426 } 1427 1428 return retval; 1429 } 1430 1431 /* 1432 * Stuff a string into the typeahead buffer, such that edit() will insert it 1433 * literally ("literally" TRUE) or interpret is as typed characters. 1434 */ 1435 static void 1436 stuffescaped(arg, literally) 1437 char_u *arg; 1438 int literally; 1439 { 1440 int c; 1441 char_u *start; 1442 1443 while (*arg != NUL) 1444 { 1445 /* Stuff a sequence of normal ASCII characters, that's fast. Also 1446 * stuff K_SPECIAL to get the effect of a special key when "literally" 1447 * is TRUE. */ 1448 start = arg; 1449 while ((*arg >= ' ' 1450 #ifndef EBCDIC 1451 && *arg < DEL /* EBCDIC: chars above space are normal */ 1452 #endif 1453 ) 1454 || (*arg == K_SPECIAL && !literally)) 1455 ++arg; 1456 if (arg > start) 1457 stuffReadbuffLen(start, (long)(arg - start)); 1458 1459 /* stuff a single special character */ 1460 if (*arg != NUL) 1461 { 1462 #ifdef FEAT_MBYTE 1463 if (has_mbyte) 1464 c = mb_cptr2char_adv(&arg); 1465 else 1466 #endif 1467 c = *arg++; 1468 if (literally && ((c < ' ' && c != TAB) || c == DEL)) 1469 stuffcharReadbuff(Ctrl_V); 1470 stuffcharReadbuff(c); 1471 } 1472 } 1473 } 1474 1475 /* 1476 * If "regname" is a special register, return TRUE and store a pointer to its 1477 * value in "argp". 1478 */ 1479 int 1480 get_spec_reg(regname, argp, allocated, errmsg) 1481 int regname; 1482 char_u **argp; 1483 int *allocated; /* return: TRUE when value was allocated */ 1484 int errmsg; /* give error message when failing */ 1485 { 1486 int cnt; 1487 1488 *argp = NULL; 1489 *allocated = FALSE; 1490 switch (regname) 1491 { 1492 case '%': /* file name */ 1493 if (errmsg) 1494 check_fname(); /* will give emsg if not set */ 1495 *argp = curbuf->b_fname; 1496 return TRUE; 1497 1498 case '#': /* alternate file name */ 1499 *argp = getaltfname(errmsg); /* may give emsg if not set */ 1500 return TRUE; 1501 1502 #ifdef FEAT_EVAL 1503 case '=': /* result of expression */ 1504 *argp = get_expr_line(); 1505 *allocated = TRUE; 1506 return TRUE; 1507 #endif 1508 1509 case ':': /* last command line */ 1510 if (last_cmdline == NULL && errmsg) 1511 EMSG(_(e_nolastcmd)); 1512 *argp = last_cmdline; 1513 return TRUE; 1514 1515 case '/': /* last search-pattern */ 1516 if (last_search_pat() == NULL && errmsg) 1517 EMSG(_(e_noprevre)); 1518 *argp = last_search_pat(); 1519 return TRUE; 1520 1521 case '.': /* last inserted text */ 1522 *argp = get_last_insert_save(); 1523 *allocated = TRUE; 1524 if (*argp == NULL && errmsg) 1525 EMSG(_(e_noinstext)); 1526 return TRUE; 1527 1528 #ifdef FEAT_SEARCHPATH 1529 case Ctrl_F: /* Filename under cursor */ 1530 case Ctrl_P: /* Path under cursor, expand via "path" */ 1531 if (!errmsg) 1532 return FALSE; 1533 *argp = file_name_at_cursor(FNAME_MESS | FNAME_HYP 1534 | (regname == Ctrl_P ? FNAME_EXP : 0), 1L, NULL); 1535 *allocated = TRUE; 1536 return TRUE; 1537 #endif 1538 1539 case Ctrl_W: /* word under cursor */ 1540 case Ctrl_A: /* WORD (mnemonic All) under cursor */ 1541 if (!errmsg) 1542 return FALSE; 1543 cnt = find_ident_under_cursor(argp, regname == Ctrl_W 1544 ? (FIND_IDENT|FIND_STRING) : FIND_STRING); 1545 *argp = cnt ? vim_strnsave(*argp, cnt) : NULL; 1546 *allocated = TRUE; 1547 return TRUE; 1548 1549 case '_': /* black hole: always empty */ 1550 *argp = (char_u *)""; 1551 return TRUE; 1552 } 1553 1554 return FALSE; 1555 } 1556 1557 /* 1558 * Paste a yank register into the command line. 1559 * Only for non-special registers. 1560 * Used by CTRL-R command in command-line mode 1561 * insert_reg() can't be used here, because special characters from the 1562 * register contents will be interpreted as commands. 1563 * 1564 * return FAIL for failure, OK otherwise 1565 */ 1566 int 1567 cmdline_paste_reg(regname, literally, remcr) 1568 int regname; 1569 int literally; /* Insert text literally instead of "as typed" */ 1570 int remcr; /* don't add trailing CR */ 1571 { 1572 long i; 1573 1574 get_yank_register(regname, FALSE); 1575 if (y_current->y_array == NULL) 1576 return FAIL; 1577 1578 for (i = 0; i < y_current->y_size; ++i) 1579 { 1580 cmdline_paste_str(y_current->y_array[i], literally); 1581 1582 /* Insert ^M between lines and after last line if type is MLINE. 1583 * Don't do this when "remcr" is TRUE and the next line is empty. */ 1584 if (y_current->y_type == MLINE 1585 || (i < y_current->y_size - 1 1586 && !(remcr 1587 && i == y_current->y_size - 2 1588 && *y_current->y_array[i + 1] == NUL))) 1589 cmdline_paste_str((char_u *)"\r", literally); 1590 1591 /* Check for CTRL-C, in case someone tries to paste a few thousand 1592 * lines and gets bored. */ 1593 ui_breakcheck(); 1594 if (got_int) 1595 return FAIL; 1596 } 1597 return OK; 1598 } 1599 1600 #if defined(FEAT_CLIPBOARD) || defined(PROTO) 1601 /* 1602 * Adjust the register name pointed to with "rp" for the clipboard being 1603 * used always and the clipboard being available. 1604 */ 1605 void 1606 adjust_clip_reg(rp) 1607 int *rp; 1608 { 1609 /* If no reg. specified, and "unnamed" or "unnamedplus" is in 'clipboard', 1610 * use '*' or '+' reg, respectively. "unnamedplus" prevails. */ 1611 if (*rp == 0 && clip_unnamed != 0) 1612 *rp = ((clip_unnamed & CLIP_UNNAMED_PLUS) && clip_plus.available) 1613 ? '+' : '*'; 1614 if (!clip_star.available && *rp == '*') 1615 *rp = 0; 1616 if (!clip_plus.available && *rp == '+') 1617 *rp = 0; 1618 } 1619 #endif 1620 1621 /* 1622 * Handle a delete operation. 1623 * 1624 * Return FAIL if undo failed, OK otherwise. 1625 */ 1626 int 1627 op_delete(oap) 1628 oparg_T *oap; 1629 { 1630 int n; 1631 linenr_T lnum; 1632 char_u *ptr; 1633 #ifdef FEAT_VISUAL 1634 char_u *newp, *oldp; 1635 struct block_def bd; 1636 #endif 1637 linenr_T old_lcount = curbuf->b_ml.ml_line_count; 1638 int did_yank = FALSE; 1639 int orig_regname = oap->regname; 1640 1641 if (curbuf->b_ml.ml_flags & ML_EMPTY) /* nothing to do */ 1642 return OK; 1643 1644 /* Nothing to delete, return here. Do prepare undo, for op_change(). */ 1645 if (oap->empty) 1646 return u_save_cursor(); 1647 1648 if (!curbuf->b_p_ma) 1649 { 1650 EMSG(_(e_modifiable)); 1651 return FAIL; 1652 } 1653 1654 #ifdef FEAT_CLIPBOARD 1655 adjust_clip_reg(&oap->regname); 1656 #endif 1657 1658 #ifdef FEAT_MBYTE 1659 if (has_mbyte) 1660 mb_adjust_opend(oap); 1661 #endif 1662 1663 /* 1664 * Imitate the strange Vi behaviour: If the delete spans more than one 1665 * line and motion_type == MCHAR and the result is a blank line, make the 1666 * delete linewise. Don't do this for the change command or Visual mode. 1667 */ 1668 if ( oap->motion_type == MCHAR 1669 #ifdef FEAT_VISUAL 1670 && !oap->is_VIsual 1671 && !oap->block_mode 1672 #endif 1673 && oap->line_count > 1 1674 && oap->motion_force == NUL 1675 && oap->op_type == OP_DELETE) 1676 { 1677 ptr = ml_get(oap->end.lnum) + oap->end.col; 1678 if (*ptr != NUL) 1679 ptr += oap->inclusive; 1680 ptr = skipwhite(ptr); 1681 if (*ptr == NUL && inindent(0)) 1682 oap->motion_type = MLINE; 1683 } 1684 1685 /* 1686 * Check for trying to delete (e.g. "D") in an empty line. 1687 * Note: For the change operator it is ok. 1688 */ 1689 if ( oap->motion_type == MCHAR 1690 && oap->line_count == 1 1691 && oap->op_type == OP_DELETE 1692 && *ml_get(oap->start.lnum) == NUL) 1693 { 1694 /* 1695 * It's an error to operate on an empty region, when 'E' included in 1696 * 'cpoptions' (Vi compatible). 1697 */ 1698 #ifdef FEAT_VIRTUALEDIT 1699 if (virtual_op) 1700 /* Virtual editing: Nothing gets deleted, but we set the '[ and '] 1701 * marks as if it happened. */ 1702 goto setmarks; 1703 #endif 1704 if (vim_strchr(p_cpo, CPO_EMPTYREGION) != NULL) 1705 beep_flush(); 1706 return OK; 1707 } 1708 1709 /* 1710 * Do a yank of whatever we're about to delete. 1711 * If a yank register was specified, put the deleted text into that 1712 * register. For the black hole register '_' don't yank anything. 1713 */ 1714 if (oap->regname != '_') 1715 { 1716 if (oap->regname != 0) 1717 { 1718 /* check for read-only register */ 1719 if (!valid_yank_reg(oap->regname, TRUE)) 1720 { 1721 beep_flush(); 1722 return OK; 1723 } 1724 get_yank_register(oap->regname, TRUE); /* yank into specif'd reg. */ 1725 if (op_yank(oap, TRUE, FALSE) == OK) /* yank without message */ 1726 did_yank = TRUE; 1727 } 1728 1729 /* 1730 * Put deleted text into register 1 and shift number registers if the 1731 * delete contains a line break, or when a regname has been specified. 1732 * Use the register name from before adjust_clip_reg() may have 1733 * changed it. 1734 */ 1735 if (orig_regname != 0 || oap->motion_type == MLINE 1736 || oap->line_count > 1 || oap->use_reg_one) 1737 { 1738 y_current = &y_regs[9]; 1739 free_yank_all(); /* free register nine */ 1740 for (n = 9; n > 1; --n) 1741 y_regs[n] = y_regs[n - 1]; 1742 y_previous = y_current = &y_regs[1]; 1743 y_regs[1].y_array = NULL; /* set register one to empty */ 1744 if (op_yank(oap, TRUE, FALSE) == OK) 1745 did_yank = TRUE; 1746 } 1747 1748 /* Yank into small delete register when no named register specified 1749 * and the delete is within one line. */ 1750 if (( 1751 #ifdef FEAT_CLIPBOARD 1752 ((clip_unnamed & CLIP_UNNAMED) && oap->regname == '*') || 1753 ((clip_unnamed & CLIP_UNNAMED_PLUS) && oap->regname == '+') || 1754 #endif 1755 oap->regname == 0) && oap->motion_type != MLINE 1756 && oap->line_count == 1) 1757 { 1758 oap->regname = '-'; 1759 get_yank_register(oap->regname, TRUE); 1760 if (op_yank(oap, TRUE, FALSE) == OK) 1761 did_yank = TRUE; 1762 oap->regname = 0; 1763 } 1764 1765 /* 1766 * If there's too much stuff to fit in the yank register, then get a 1767 * confirmation before doing the delete. This is crude, but simple. 1768 * And it avoids doing a delete of something we can't put back if we 1769 * want. 1770 */ 1771 if (!did_yank) 1772 { 1773 int msg_silent_save = msg_silent; 1774 1775 msg_silent = 0; /* must display the prompt */ 1776 n = ask_yesno((char_u *)_("cannot yank; delete anyway"), TRUE); 1777 msg_silent = msg_silent_save; 1778 if (n != 'y') 1779 { 1780 EMSG(_(e_abort)); 1781 return FAIL; 1782 } 1783 } 1784 } 1785 1786 #ifdef FEAT_VISUAL 1787 /* 1788 * block mode delete 1789 */ 1790 if (oap->block_mode) 1791 { 1792 if (u_save((linenr_T)(oap->start.lnum - 1), 1793 (linenr_T)(oap->end.lnum + 1)) == FAIL) 1794 return FAIL; 1795 1796 for (lnum = curwin->w_cursor.lnum; lnum <= oap->end.lnum; ++lnum) 1797 { 1798 block_prep(oap, &bd, lnum, TRUE); 1799 if (bd.textlen == 0) /* nothing to delete */ 1800 continue; 1801 1802 /* Adjust cursor position for tab replaced by spaces and 'lbr'. */ 1803 if (lnum == curwin->w_cursor.lnum) 1804 { 1805 curwin->w_cursor.col = bd.textcol + bd.startspaces; 1806 # ifdef FEAT_VIRTUALEDIT 1807 curwin->w_cursor.coladd = 0; 1808 # endif 1809 } 1810 1811 /* n == number of chars deleted 1812 * If we delete a TAB, it may be replaced by several characters. 1813 * Thus the number of characters may increase! 1814 */ 1815 n = bd.textlen - bd.startspaces - bd.endspaces; 1816 oldp = ml_get(lnum); 1817 newp = alloc_check((unsigned)STRLEN(oldp) + 1 - n); 1818 if (newp == NULL) 1819 continue; 1820 /* copy up to deleted part */ 1821 mch_memmove(newp, oldp, (size_t)bd.textcol); 1822 /* insert spaces */ 1823 copy_spaces(newp + bd.textcol, 1824 (size_t)(bd.startspaces + bd.endspaces)); 1825 /* copy the part after the deleted part */ 1826 oldp += bd.textcol + bd.textlen; 1827 STRMOVE(newp + bd.textcol + bd.startspaces + bd.endspaces, oldp); 1828 /* replace the line */ 1829 ml_replace(lnum, newp, FALSE); 1830 } 1831 1832 check_cursor_col(); 1833 changed_lines(curwin->w_cursor.lnum, curwin->w_cursor.col, 1834 oap->end.lnum + 1, 0L); 1835 oap->line_count = 0; /* no lines deleted */ 1836 } 1837 else 1838 #endif 1839 if (oap->motion_type == MLINE) 1840 { 1841 if (oap->op_type == OP_CHANGE) 1842 { 1843 /* Delete the lines except the first one. Temporarily move the 1844 * cursor to the next line. Save the current line number, if the 1845 * last line is deleted it may be changed. 1846 */ 1847 if (oap->line_count > 1) 1848 { 1849 lnum = curwin->w_cursor.lnum; 1850 ++curwin->w_cursor.lnum; 1851 del_lines((long)(oap->line_count - 1), TRUE); 1852 curwin->w_cursor.lnum = lnum; 1853 } 1854 if (u_save_cursor() == FAIL) 1855 return FAIL; 1856 if (curbuf->b_p_ai) /* don't delete indent */ 1857 { 1858 beginline(BL_WHITE); /* cursor on first non-white */ 1859 did_ai = TRUE; /* delete the indent when ESC hit */ 1860 ai_col = curwin->w_cursor.col; 1861 } 1862 else 1863 beginline(0); /* cursor in column 0 */ 1864 truncate_line(FALSE); /* delete the rest of the line */ 1865 /* leave cursor past last char in line */ 1866 if (oap->line_count > 1) 1867 u_clearline(); /* "U" command not possible after "2cc" */ 1868 } 1869 else 1870 { 1871 del_lines(oap->line_count, TRUE); 1872 beginline(BL_WHITE | BL_FIX); 1873 u_clearline(); /* "U" command not possible after "dd" */ 1874 } 1875 } 1876 else 1877 { 1878 #ifdef FEAT_VIRTUALEDIT 1879 if (virtual_op) 1880 { 1881 int endcol = 0; 1882 1883 /* For virtualedit: break the tabs that are partly included. */ 1884 if (gchar_pos(&oap->start) == '\t') 1885 { 1886 if (u_save_cursor() == FAIL) /* save first line for undo */ 1887 return FAIL; 1888 if (oap->line_count == 1) 1889 endcol = getviscol2(oap->end.col, oap->end.coladd); 1890 coladvance_force(getviscol2(oap->start.col, oap->start.coladd)); 1891 oap->start = curwin->w_cursor; 1892 if (oap->line_count == 1) 1893 { 1894 coladvance(endcol); 1895 oap->end.col = curwin->w_cursor.col; 1896 oap->end.coladd = curwin->w_cursor.coladd; 1897 curwin->w_cursor = oap->start; 1898 } 1899 } 1900 1901 /* Break a tab only when it's included in the area. */ 1902 if (gchar_pos(&oap->end) == '\t' 1903 && (int)oap->end.coladd < oap->inclusive) 1904 { 1905 /* save last line for undo */ 1906 if (u_save((linenr_T)(oap->end.lnum - 1), 1907 (linenr_T)(oap->end.lnum + 1)) == FAIL) 1908 return FAIL; 1909 curwin->w_cursor = oap->end; 1910 coladvance_force(getviscol2(oap->end.col, oap->end.coladd)); 1911 oap->end = curwin->w_cursor; 1912 curwin->w_cursor = oap->start; 1913 } 1914 } 1915 #endif 1916 1917 if (oap->line_count == 1) /* delete characters within one line */ 1918 { 1919 if (u_save_cursor() == FAIL) /* save line for undo */ 1920 return FAIL; 1921 1922 /* if 'cpoptions' contains '$', display '$' at end of change */ 1923 if ( vim_strchr(p_cpo, CPO_DOLLAR) != NULL 1924 && oap->op_type == OP_CHANGE 1925 && oap->end.lnum == curwin->w_cursor.lnum 1926 #ifdef FEAT_VISUAL 1927 && !oap->is_VIsual 1928 #endif 1929 ) 1930 display_dollar(oap->end.col - !oap->inclusive); 1931 1932 n = oap->end.col - oap->start.col + 1 - !oap->inclusive; 1933 1934 #ifdef FEAT_VIRTUALEDIT 1935 if (virtual_op) 1936 { 1937 /* fix up things for virtualedit-delete: 1938 * break the tabs which are going to get in our way 1939 */ 1940 char_u *curline = ml_get_curline(); 1941 int len = (int)STRLEN(curline); 1942 1943 if (oap->end.coladd != 0 1944 && (int)oap->end.col >= len - 1 1945 && !(oap->start.coladd && (int)oap->end.col >= len - 1)) 1946 n++; 1947 /* Delete at least one char (e.g, when on a control char). */ 1948 if (n == 0 && oap->start.coladd != oap->end.coladd) 1949 n = 1; 1950 1951 /* When deleted a char in the line, reset coladd. */ 1952 if (gchar_cursor() != NUL) 1953 curwin->w_cursor.coladd = 0; 1954 } 1955 #endif 1956 if (oap->op_type == OP_DELETE 1957 && oap->inclusive 1958 && oap->end.lnum == curbuf->b_ml.ml_line_count 1959 && n > (int)STRLEN(ml_get(oap->end.lnum))) 1960 { 1961 /* Special case: gH<Del> deletes the last line. */ 1962 del_lines(1L, FALSE); 1963 } 1964 else 1965 { 1966 (void)del_bytes((long)n, !virtual_op, oap->op_type == OP_DELETE 1967 #ifdef FEAT_VISUAL 1968 && !oap->is_VIsual 1969 #endif 1970 ); 1971 } 1972 } 1973 else /* delete characters between lines */ 1974 { 1975 pos_T curpos; 1976 int delete_last_line; 1977 1978 /* save deleted and changed lines for undo */ 1979 if (u_save((linenr_T)(curwin->w_cursor.lnum - 1), 1980 (linenr_T)(curwin->w_cursor.lnum + oap->line_count)) == FAIL) 1981 return FAIL; 1982 1983 delete_last_line = (oap->end.lnum == curbuf->b_ml.ml_line_count); 1984 truncate_line(TRUE); /* delete from cursor to end of line */ 1985 1986 curpos = curwin->w_cursor; /* remember curwin->w_cursor */ 1987 ++curwin->w_cursor.lnum; 1988 del_lines((long)(oap->line_count - 2), FALSE); 1989 1990 if (delete_last_line) 1991 oap->end.lnum = curbuf->b_ml.ml_line_count; 1992 1993 n = (oap->end.col + 1 - !oap->inclusive); 1994 if (oap->inclusive && delete_last_line 1995 && n > (int)STRLEN(ml_get(oap->end.lnum))) 1996 { 1997 /* Special case: gH<Del> deletes the last line. */ 1998 del_lines(1L, FALSE); 1999 curwin->w_cursor = curpos; /* restore curwin->w_cursor */ 2000 if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) 2001 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 2002 } 2003 else 2004 { 2005 /* delete from start of line until op_end */ 2006 curwin->w_cursor.col = 0; 2007 (void)del_bytes((long)n, !virtual_op, oap->op_type == OP_DELETE 2008 #ifdef FEAT_VISUAL 2009 && !oap->is_VIsual 2010 #endif 2011 ); 2012 curwin->w_cursor = curpos; /* restore curwin->w_cursor */ 2013 } 2014 if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) 2015 (void)do_join(2, FALSE, FALSE, FALSE); 2016 } 2017 } 2018 2019 msgmore(curbuf->b_ml.ml_line_count - old_lcount); 2020 2021 #ifdef FEAT_VIRTUALEDIT 2022 setmarks: 2023 #endif 2024 #ifdef FEAT_VISUAL 2025 if (oap->block_mode) 2026 { 2027 curbuf->b_op_end.lnum = oap->end.lnum; 2028 curbuf->b_op_end.col = oap->start.col; 2029 } 2030 else 2031 #endif 2032 curbuf->b_op_end = oap->start; 2033 curbuf->b_op_start = oap->start; 2034 2035 return OK; 2036 } 2037 2038 #ifdef FEAT_MBYTE 2039 /* 2040 * Adjust end of operating area for ending on a multi-byte character. 2041 * Used for deletion. 2042 */ 2043 static void 2044 mb_adjust_opend(oap) 2045 oparg_T *oap; 2046 { 2047 char_u *p; 2048 2049 if (oap->inclusive) 2050 { 2051 p = ml_get(oap->end.lnum); 2052 oap->end.col += mb_tail_off(p, p + oap->end.col); 2053 } 2054 } 2055 #endif 2056 2057 #if defined(FEAT_VISUALEXTRA) || defined(PROTO) 2058 /* 2059 * Replace a whole area with one character. 2060 */ 2061 int 2062 op_replace(oap, c) 2063 oparg_T *oap; 2064 int c; 2065 { 2066 int n, numc; 2067 #ifdef FEAT_MBYTE 2068 int num_chars; 2069 #endif 2070 char_u *newp, *oldp; 2071 size_t oldlen; 2072 struct block_def bd; 2073 2074 if ((curbuf->b_ml.ml_flags & ML_EMPTY ) || oap->empty) 2075 return OK; /* nothing to do */ 2076 2077 #ifdef FEAT_MBYTE 2078 if (has_mbyte) 2079 mb_adjust_opend(oap); 2080 #endif 2081 2082 if (u_save((linenr_T)(oap->start.lnum - 1), 2083 (linenr_T)(oap->end.lnum + 1)) == FAIL) 2084 return FAIL; 2085 2086 /* 2087 * block mode replace 2088 */ 2089 if (oap->block_mode) 2090 { 2091 bd.is_MAX = (curwin->w_curswant == MAXCOL); 2092 for ( ; curwin->w_cursor.lnum <= oap->end.lnum; ++curwin->w_cursor.lnum) 2093 { 2094 curwin->w_cursor.col = 0; /* make sure cursor position is valid */ 2095 block_prep(oap, &bd, curwin->w_cursor.lnum, TRUE); 2096 if (bd.textlen == 0 && (!virtual_op || bd.is_MAX)) 2097 continue; /* nothing to replace */ 2098 2099 /* n == number of extra chars required 2100 * If we split a TAB, it may be replaced by several characters. 2101 * Thus the number of characters may increase! 2102 */ 2103 #ifdef FEAT_VIRTUALEDIT 2104 /* If the range starts in virtual space, count the initial 2105 * coladd offset as part of "startspaces" */ 2106 if (virtual_op && bd.is_short && *bd.textstart == NUL) 2107 { 2108 pos_T vpos; 2109 2110 vpos.lnum = curwin->w_cursor.lnum; 2111 getvpos(&vpos, oap->start_vcol); 2112 bd.startspaces += vpos.coladd; 2113 n = bd.startspaces; 2114 } 2115 else 2116 #endif 2117 /* allow for pre spaces */ 2118 n = (bd.startspaces ? bd.start_char_vcols - 1 : 0); 2119 2120 /* allow for post spp */ 2121 n += (bd.endspaces 2122 #ifdef FEAT_VIRTUALEDIT 2123 && !bd.is_oneChar 2124 #endif 2125 && bd.end_char_vcols > 0) ? bd.end_char_vcols - 1 : 0; 2126 /* Figure out how many characters to replace. */ 2127 numc = oap->end_vcol - oap->start_vcol + 1; 2128 if (bd.is_short && (!virtual_op || bd.is_MAX)) 2129 numc -= (oap->end_vcol - bd.end_vcol) + 1; 2130 2131 #ifdef FEAT_MBYTE 2132 /* A double-wide character can be replaced only up to half the 2133 * times. */ 2134 if ((*mb_char2cells)(c) > 1) 2135 { 2136 if ((numc & 1) && !bd.is_short) 2137 { 2138 ++bd.endspaces; 2139 ++n; 2140 } 2141 numc = numc / 2; 2142 } 2143 2144 /* Compute bytes needed, move character count to num_chars. */ 2145 num_chars = numc; 2146 numc *= (*mb_char2len)(c); 2147 #endif 2148 /* oldlen includes textlen, so don't double count */ 2149 n += numc - bd.textlen; 2150 2151 oldp = ml_get_curline(); 2152 oldlen = STRLEN(oldp); 2153 newp = alloc_check((unsigned)oldlen + 1 + n); 2154 if (newp == NULL) 2155 continue; 2156 vim_memset(newp, NUL, (size_t)(oldlen + 1 + n)); 2157 /* copy up to deleted part */ 2158 mch_memmove(newp, oldp, (size_t)bd.textcol); 2159 oldp += bd.textcol + bd.textlen; 2160 /* insert pre-spaces */ 2161 copy_spaces(newp + bd.textcol, (size_t)bd.startspaces); 2162 /* insert replacement chars CHECK FOR ALLOCATED SPACE */ 2163 #ifdef FEAT_MBYTE 2164 if (has_mbyte) 2165 { 2166 n = (int)STRLEN(newp); 2167 while (--num_chars >= 0) 2168 n += (*mb_char2bytes)(c, newp + n); 2169 } 2170 else 2171 #endif 2172 copy_chars(newp + STRLEN(newp), (size_t)numc, c); 2173 if (!bd.is_short) 2174 { 2175 /* insert post-spaces */ 2176 copy_spaces(newp + STRLEN(newp), (size_t)bd.endspaces); 2177 /* copy the part after the changed part */ 2178 STRMOVE(newp + STRLEN(newp), oldp); 2179 } 2180 /* replace the line */ 2181 ml_replace(curwin->w_cursor.lnum, newp, FALSE); 2182 } 2183 } 2184 else 2185 { 2186 /* 2187 * MCHAR and MLINE motion replace. 2188 */ 2189 if (oap->motion_type == MLINE) 2190 { 2191 oap->start.col = 0; 2192 curwin->w_cursor.col = 0; 2193 oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum)); 2194 if (oap->end.col) 2195 --oap->end.col; 2196 } 2197 else if (!oap->inclusive) 2198 dec(&(oap->end)); 2199 2200 while (ltoreq(curwin->w_cursor, oap->end)) 2201 { 2202 n = gchar_cursor(); 2203 if (n != NUL) 2204 { 2205 #ifdef FEAT_MBYTE 2206 if ((*mb_char2len)(c) > 1 || (*mb_char2len)(n) > 1) 2207 { 2208 /* This is slow, but it handles replacing a single-byte 2209 * with a multi-byte and the other way around. */ 2210 if (curwin->w_cursor.lnum == oap->end.lnum) 2211 oap->end.col += (*mb_char2len)(c) - (*mb_char2len)(n); 2212 n = State; 2213 State = REPLACE; 2214 ins_char(c); 2215 State = n; 2216 /* Backup to the replaced character. */ 2217 dec_cursor(); 2218 } 2219 else 2220 #endif 2221 { 2222 #ifdef FEAT_VIRTUALEDIT 2223 if (n == TAB) 2224 { 2225 int end_vcol = 0; 2226 2227 if (curwin->w_cursor.lnum == oap->end.lnum) 2228 { 2229 /* oap->end has to be recalculated when 2230 * the tab breaks */ 2231 end_vcol = getviscol2(oap->end.col, 2232 oap->end.coladd); 2233 } 2234 coladvance_force(getviscol()); 2235 if (curwin->w_cursor.lnum == oap->end.lnum) 2236 getvpos(&oap->end, end_vcol); 2237 } 2238 #endif 2239 pchar(curwin->w_cursor, c); 2240 } 2241 } 2242 #ifdef FEAT_VIRTUALEDIT 2243 else if (virtual_op && curwin->w_cursor.lnum == oap->end.lnum) 2244 { 2245 int virtcols = oap->end.coladd; 2246 2247 if (curwin->w_cursor.lnum == oap->start.lnum 2248 && oap->start.col == oap->end.col && oap->start.coladd) 2249 virtcols -= oap->start.coladd; 2250 2251 /* oap->end has been trimmed so it's effectively inclusive; 2252 * as a result an extra +1 must be counted so we don't 2253 * trample the NUL byte. */ 2254 coladvance_force(getviscol2(oap->end.col, oap->end.coladd) + 1); 2255 curwin->w_cursor.col -= (virtcols + 1); 2256 for (; virtcols >= 0; virtcols--) 2257 { 2258 pchar(curwin->w_cursor, c); 2259 if (inc(&curwin->w_cursor) == -1) 2260 break; 2261 } 2262 } 2263 #endif 2264 2265 /* Advance to next character, stop at the end of the file. */ 2266 if (inc_cursor() == -1) 2267 break; 2268 } 2269 } 2270 2271 curwin->w_cursor = oap->start; 2272 check_cursor(); 2273 changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1, 0L); 2274 2275 /* Set "'[" and "']" marks. */ 2276 curbuf->b_op_start = oap->start; 2277 curbuf->b_op_end = oap->end; 2278 2279 return OK; 2280 } 2281 #endif 2282 2283 static int swapchars __ARGS((int op_type, pos_T *pos, int length)); 2284 2285 /* 2286 * Handle the (non-standard vi) tilde operator. Also for "gu", "gU" and "g?". 2287 */ 2288 void 2289 op_tilde(oap) 2290 oparg_T *oap; 2291 { 2292 pos_T pos; 2293 #ifdef FEAT_VISUAL 2294 struct block_def bd; 2295 #endif 2296 int did_change = FALSE; 2297 2298 if (u_save((linenr_T)(oap->start.lnum - 1), 2299 (linenr_T)(oap->end.lnum + 1)) == FAIL) 2300 return; 2301 2302 pos = oap->start; 2303 #ifdef FEAT_VISUAL 2304 if (oap->block_mode) /* Visual block mode */ 2305 { 2306 for (; pos.lnum <= oap->end.lnum; ++pos.lnum) 2307 { 2308 int one_change; 2309 2310 block_prep(oap, &bd, pos.lnum, FALSE); 2311 pos.col = bd.textcol; 2312 one_change = swapchars(oap->op_type, &pos, bd.textlen); 2313 did_change |= one_change; 2314 2315 # ifdef FEAT_NETBEANS_INTG 2316 if (netbeans_active() && one_change) 2317 { 2318 char_u *ptr = ml_get_buf(curbuf, pos.lnum, FALSE); 2319 2320 netbeans_removed(curbuf, pos.lnum, bd.textcol, 2321 (long)bd.textlen); 2322 netbeans_inserted(curbuf, pos.lnum, bd.textcol, 2323 &ptr[bd.textcol], bd.textlen); 2324 } 2325 # endif 2326 } 2327 if (did_change) 2328 changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L); 2329 } 2330 else /* not block mode */ 2331 #endif 2332 { 2333 if (oap->motion_type == MLINE) 2334 { 2335 oap->start.col = 0; 2336 pos.col = 0; 2337 oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum)); 2338 if (oap->end.col) 2339 --oap->end.col; 2340 } 2341 else if (!oap->inclusive) 2342 dec(&(oap->end)); 2343 2344 if (pos.lnum == oap->end.lnum) 2345 did_change = swapchars(oap->op_type, &pos, 2346 oap->end.col - pos.col + 1); 2347 else 2348 for (;;) 2349 { 2350 did_change |= swapchars(oap->op_type, &pos, 2351 pos.lnum == oap->end.lnum ? oap->end.col + 1: 2352 (int)STRLEN(ml_get_pos(&pos))); 2353 if (ltoreq(oap->end, pos) || inc(&pos) == -1) 2354 break; 2355 } 2356 if (did_change) 2357 { 2358 changed_lines(oap->start.lnum, oap->start.col, oap->end.lnum + 1, 2359 0L); 2360 #ifdef FEAT_NETBEANS_INTG 2361 if (netbeans_active() && did_change) 2362 { 2363 char_u *ptr; 2364 int count; 2365 2366 pos = oap->start; 2367 while (pos.lnum < oap->end.lnum) 2368 { 2369 ptr = ml_get_buf(curbuf, pos.lnum, FALSE); 2370 count = (int)STRLEN(ptr) - pos.col; 2371 netbeans_removed(curbuf, pos.lnum, pos.col, (long)count); 2372 netbeans_inserted(curbuf, pos.lnum, pos.col, 2373 &ptr[pos.col], count); 2374 pos.col = 0; 2375 pos.lnum++; 2376 } 2377 ptr = ml_get_buf(curbuf, pos.lnum, FALSE); 2378 count = oap->end.col - pos.col + 1; 2379 netbeans_removed(curbuf, pos.lnum, pos.col, (long)count); 2380 netbeans_inserted(curbuf, pos.lnum, pos.col, 2381 &ptr[pos.col], count); 2382 } 2383 #endif 2384 } 2385 } 2386 2387 #ifdef FEAT_VISUAL 2388 if (!did_change && oap->is_VIsual) 2389 /* No change: need to remove the Visual selection */ 2390 redraw_curbuf_later(INVERTED); 2391 #endif 2392 2393 /* 2394 * Set '[ and '] marks. 2395 */ 2396 curbuf->b_op_start = oap->start; 2397 curbuf->b_op_end = oap->end; 2398 2399 if (oap->line_count > p_report) 2400 { 2401 if (oap->line_count == 1) 2402 MSG(_("1 line changed")); 2403 else 2404 smsg((char_u *)_("%ld lines changed"), oap->line_count); 2405 } 2406 } 2407 2408 /* 2409 * Invoke swapchar() on "length" bytes at position "pos". 2410 * "pos" is advanced to just after the changed characters. 2411 * "length" is rounded up to include the whole last multi-byte character. 2412 * Also works correctly when the number of bytes changes. 2413 * Returns TRUE if some character was changed. 2414 */ 2415 static int 2416 swapchars(op_type, pos, length) 2417 int op_type; 2418 pos_T *pos; 2419 int length; 2420 { 2421 int todo; 2422 int did_change = 0; 2423 2424 for (todo = length; todo > 0; --todo) 2425 { 2426 # ifdef FEAT_MBYTE 2427 if (has_mbyte) 2428 /* we're counting bytes, not characters */ 2429 todo -= (*mb_ptr2len)(ml_get_pos(pos)) - 1; 2430 # endif 2431 did_change |= swapchar(op_type, pos); 2432 if (inc(pos) == -1) /* at end of file */ 2433 break; 2434 } 2435 return did_change; 2436 } 2437 2438 /* 2439 * If op_type == OP_UPPER: make uppercase, 2440 * if op_type == OP_LOWER: make lowercase, 2441 * if op_type == OP_ROT13: do rot13 encoding, 2442 * else swap case of character at 'pos' 2443 * returns TRUE when something actually changed. 2444 */ 2445 int 2446 swapchar(op_type, pos) 2447 int op_type; 2448 pos_T *pos; 2449 { 2450 int c; 2451 int nc; 2452 2453 c = gchar_pos(pos); 2454 2455 /* Only do rot13 encoding for ASCII characters. */ 2456 if (c >= 0x80 && op_type == OP_ROT13) 2457 return FALSE; 2458 2459 #ifdef FEAT_MBYTE 2460 if (op_type == OP_UPPER && c == 0xdf 2461 && (enc_latin1like || STRCMP(p_enc, "iso-8859-2") == 0)) 2462 { 2463 pos_T sp = curwin->w_cursor; 2464 2465 /* Special handling of German sharp s: change to "SS". */ 2466 curwin->w_cursor = *pos; 2467 del_char(FALSE); 2468 ins_char('S'); 2469 ins_char('S'); 2470 curwin->w_cursor = sp; 2471 inc(pos); 2472 } 2473 2474 if (enc_dbcs != 0 && c >= 0x100) /* No lower/uppercase letter */ 2475 return FALSE; 2476 #endif 2477 nc = c; 2478 if (MB_ISLOWER(c)) 2479 { 2480 if (op_type == OP_ROT13) 2481 nc = ROT13(c, 'a'); 2482 else if (op_type != OP_LOWER) 2483 nc = MB_TOUPPER(c); 2484 } 2485 else if (MB_ISUPPER(c)) 2486 { 2487 if (op_type == OP_ROT13) 2488 nc = ROT13(c, 'A'); 2489 else if (op_type != OP_UPPER) 2490 nc = MB_TOLOWER(c); 2491 } 2492 if (nc != c) 2493 { 2494 #ifdef FEAT_MBYTE 2495 if (enc_utf8 && (c >= 0x80 || nc >= 0x80)) 2496 { 2497 pos_T sp = curwin->w_cursor; 2498 2499 curwin->w_cursor = *pos; 2500 /* don't use del_char(), it also removes composing chars */ 2501 del_bytes(utf_ptr2len(ml_get_cursor()), FALSE, FALSE); 2502 ins_char(nc); 2503 curwin->w_cursor = sp; 2504 } 2505 else 2506 #endif 2507 pchar(*pos, nc); 2508 return TRUE; 2509 } 2510 return FALSE; 2511 } 2512 2513 #if defined(FEAT_VISUALEXTRA) || defined(PROTO) 2514 /* 2515 * op_insert - Insert and append operators for Visual mode. 2516 */ 2517 void 2518 op_insert(oap, count1) 2519 oparg_T *oap; 2520 long count1; 2521 { 2522 long ins_len, pre_textlen = 0; 2523 char_u *firstline, *ins_text; 2524 struct block_def bd; 2525 int i; 2526 2527 /* edit() changes this - record it for OP_APPEND */ 2528 bd.is_MAX = (curwin->w_curswant == MAXCOL); 2529 2530 /* vis block is still marked. Get rid of it now. */ 2531 curwin->w_cursor.lnum = oap->start.lnum; 2532 update_screen(INVERTED); 2533 2534 if (oap->block_mode) 2535 { 2536 #ifdef FEAT_VIRTUALEDIT 2537 /* When 'virtualedit' is used, need to insert the extra spaces before 2538 * doing block_prep(). When only "block" is used, virtual edit is 2539 * already disabled, but still need it when calling 2540 * coladvance_force(). */ 2541 if (curwin->w_cursor.coladd > 0) 2542 { 2543 int old_ve_flags = ve_flags; 2544 2545 ve_flags = VE_ALL; 2546 if (u_save_cursor() == FAIL) 2547 return; 2548 coladvance_force(oap->op_type == OP_APPEND 2549 ? oap->end_vcol + 1 : getviscol()); 2550 if (oap->op_type == OP_APPEND) 2551 --curwin->w_cursor.col; 2552 ve_flags = old_ve_flags; 2553 } 2554 #endif 2555 /* Get the info about the block before entering the text */ 2556 block_prep(oap, &bd, oap->start.lnum, TRUE); 2557 firstline = ml_get(oap->start.lnum) + bd.textcol; 2558 if (oap->op_type == OP_APPEND) 2559 firstline += bd.textlen; 2560 pre_textlen = (long)STRLEN(firstline); 2561 } 2562 2563 if (oap->op_type == OP_APPEND) 2564 { 2565 if (oap->block_mode 2566 #ifdef FEAT_VIRTUALEDIT 2567 && curwin->w_cursor.coladd == 0 2568 #endif 2569 ) 2570 { 2571 /* Move the cursor to the character right of the block. */ 2572 curwin->w_set_curswant = TRUE; 2573 while (*ml_get_cursor() != NUL 2574 && (curwin->w_cursor.col < bd.textcol + bd.textlen)) 2575 ++curwin->w_cursor.col; 2576 if (bd.is_short && !bd.is_MAX) 2577 { 2578 /* First line was too short, make it longer and adjust the 2579 * values in "bd". */ 2580 if (u_save_cursor() == FAIL) 2581 return; 2582 for (i = 0; i < bd.endspaces; ++i) 2583 ins_char(' '); 2584 bd.textlen += bd.endspaces; 2585 } 2586 } 2587 else 2588 { 2589 curwin->w_cursor = oap->end; 2590 check_cursor_col(); 2591 2592 /* Works just like an 'i'nsert on the next character. */ 2593 if (!lineempty(curwin->w_cursor.lnum) 2594 && oap->start_vcol != oap->end_vcol) 2595 inc_cursor(); 2596 } 2597 } 2598 2599 edit(NUL, FALSE, (linenr_T)count1); 2600 2601 /* If user has moved off this line, we don't know what to do, so do 2602 * nothing. 2603 * Also don't repeat the insert when Insert mode ended with CTRL-C. */ 2604 if (curwin->w_cursor.lnum != oap->start.lnum || got_int) 2605 return; 2606 2607 if (oap->block_mode) 2608 { 2609 struct block_def bd2; 2610 2611 /* 2612 * Spaces and tabs in the indent may have changed to other spaces and 2613 * tabs. Get the starting column again and correct the length. 2614 * Don't do this when "$" used, end-of-line will have changed. 2615 */ 2616 block_prep(oap, &bd2, oap->start.lnum, TRUE); 2617 if (!bd.is_MAX || bd2.textlen < bd.textlen) 2618 { 2619 if (oap->op_type == OP_APPEND) 2620 { 2621 pre_textlen += bd2.textlen - bd.textlen; 2622 if (bd2.endspaces) 2623 --bd2.textlen; 2624 } 2625 bd.textcol = bd2.textcol; 2626 bd.textlen = bd2.textlen; 2627 } 2628 2629 /* 2630 * Subsequent calls to ml_get() flush the firstline data - take a 2631 * copy of the required string. 2632 */ 2633 firstline = ml_get(oap->start.lnum) + bd.textcol; 2634 if (oap->op_type == OP_APPEND) 2635 firstline += bd.textlen; 2636 if (pre_textlen >= 0 2637 && (ins_len = (long)STRLEN(firstline) - pre_textlen) > 0) 2638 { 2639 ins_text = vim_strnsave(firstline, (int)ins_len); 2640 if (ins_text != NULL) 2641 { 2642 /* block handled here */ 2643 if (u_save(oap->start.lnum, 2644 (linenr_T)(oap->end.lnum + 1)) == OK) 2645 block_insert(oap, ins_text, (oap->op_type == OP_INSERT), 2646 &bd); 2647 2648 curwin->w_cursor.col = oap->start.col; 2649 check_cursor(); 2650 vim_free(ins_text); 2651 } 2652 } 2653 } 2654 } 2655 #endif 2656 2657 /* 2658 * op_change - handle a change operation 2659 * 2660 * return TRUE if edit() returns because of a CTRL-O command 2661 */ 2662 int 2663 op_change(oap) 2664 oparg_T *oap; 2665 { 2666 colnr_T l; 2667 int retval; 2668 #ifdef FEAT_VISUALEXTRA 2669 long offset; 2670 linenr_T linenr; 2671 long ins_len; 2672 long pre_textlen = 0; 2673 long pre_indent = 0; 2674 char_u *firstline; 2675 char_u *ins_text, *newp, *oldp; 2676 struct block_def bd; 2677 #endif 2678 2679 l = oap->start.col; 2680 if (oap->motion_type == MLINE) 2681 { 2682 l = 0; 2683 #ifdef FEAT_SMARTINDENT 2684 if (!p_paste && curbuf->b_p_si 2685 # ifdef FEAT_CINDENT 2686 && !curbuf->b_p_cin 2687 # endif 2688 ) 2689 can_si = TRUE; /* It's like opening a new line, do si */ 2690 #endif 2691 } 2692 2693 /* First delete the text in the region. In an empty buffer only need to 2694 * save for undo */ 2695 if (curbuf->b_ml.ml_flags & ML_EMPTY) 2696 { 2697 if (u_save_cursor() == FAIL) 2698 return FALSE; 2699 } 2700 else if (op_delete(oap) == FAIL) 2701 return FALSE; 2702 2703 if ((l > curwin->w_cursor.col) && !lineempty(curwin->w_cursor.lnum) 2704 && !virtual_op) 2705 inc_cursor(); 2706 2707 #ifdef FEAT_VISUALEXTRA 2708 /* check for still on same line (<CR> in inserted text meaningless) */ 2709 /* skip blank lines too */ 2710 if (oap->block_mode) 2711 { 2712 # ifdef FEAT_VIRTUALEDIT 2713 /* Add spaces before getting the current line length. */ 2714 if (virtual_op && (curwin->w_cursor.coladd > 0 2715 || gchar_cursor() == NUL)) 2716 coladvance_force(getviscol()); 2717 # endif 2718 firstline = ml_get(oap->start.lnum); 2719 pre_textlen = (long)STRLEN(firstline); 2720 pre_indent = (long)(skipwhite(firstline) - firstline); 2721 bd.textcol = curwin->w_cursor.col; 2722 } 2723 #endif 2724 2725 #if defined(FEAT_LISP) || defined(FEAT_CINDENT) 2726 if (oap->motion_type == MLINE) 2727 fix_indent(); 2728 #endif 2729 2730 retval = edit(NUL, FALSE, (linenr_T)1); 2731 2732 #ifdef FEAT_VISUALEXTRA 2733 /* 2734 * In Visual block mode, handle copying the new text to all lines of the 2735 * block. 2736 * Don't repeat the insert when Insert mode ended with CTRL-C. 2737 */ 2738 if (oap->block_mode && oap->start.lnum != oap->end.lnum && !got_int) 2739 { 2740 /* Auto-indenting may have changed the indent. If the cursor was past 2741 * the indent, exclude that indent change from the inserted text. */ 2742 firstline = ml_get(oap->start.lnum); 2743 if (bd.textcol > (colnr_T)pre_indent) 2744 { 2745 long new_indent = (long)(skipwhite(firstline) - firstline); 2746 2747 pre_textlen += new_indent - pre_indent; 2748 bd.textcol += new_indent - pre_indent; 2749 } 2750 2751 ins_len = (long)STRLEN(firstline) - pre_textlen; 2752 if (ins_len > 0) 2753 { 2754 /* Subsequent calls to ml_get() flush the firstline data - take a 2755 * copy of the inserted text. */ 2756 if ((ins_text = alloc_check((unsigned)(ins_len + 1))) != NULL) 2757 { 2758 vim_strncpy(ins_text, firstline + bd.textcol, (size_t)ins_len); 2759 for (linenr = oap->start.lnum + 1; linenr <= oap->end.lnum; 2760 linenr++) 2761 { 2762 block_prep(oap, &bd, linenr, TRUE); 2763 if (!bd.is_short || virtual_op) 2764 { 2765 # ifdef FEAT_VIRTUALEDIT 2766 pos_T vpos; 2767 2768 /* If the block starts in virtual space, count the 2769 * initial coladd offset as part of "startspaces" */ 2770 if (bd.is_short) 2771 { 2772 vpos.lnum = linenr; 2773 (void)getvpos(&vpos, oap->start_vcol); 2774 } 2775 else 2776 vpos.coladd = 0; 2777 # endif 2778 oldp = ml_get(linenr); 2779 newp = alloc_check((unsigned)(STRLEN(oldp) 2780 # ifdef FEAT_VIRTUALEDIT 2781 + vpos.coladd 2782 # endif 2783 + ins_len + 1)); 2784 if (newp == NULL) 2785 continue; 2786 /* copy up to block start */ 2787 mch_memmove(newp, oldp, (size_t)bd.textcol); 2788 offset = bd.textcol; 2789 # ifdef FEAT_VIRTUALEDIT 2790 copy_spaces(newp + offset, (size_t)vpos.coladd); 2791 offset += vpos.coladd; 2792 # endif 2793 mch_memmove(newp + offset, ins_text, (size_t)ins_len); 2794 offset += ins_len; 2795 oldp += bd.textcol; 2796 STRMOVE(newp + offset, oldp); 2797 ml_replace(linenr, newp, FALSE); 2798 } 2799 } 2800 check_cursor(); 2801 2802 changed_lines(oap->start.lnum + 1, 0, oap->end.lnum + 1, 0L); 2803 } 2804 vim_free(ins_text); 2805 } 2806 } 2807 #endif 2808 2809 return retval; 2810 } 2811 2812 /* 2813 * set all the yank registers to empty (called from main()) 2814 */ 2815 void 2816 init_yank() 2817 { 2818 int i; 2819 2820 for (i = 0; i < NUM_REGISTERS; ++i) 2821 y_regs[i].y_array = NULL; 2822 } 2823 2824 #if defined(EXITFREE) || defined(PROTO) 2825 void 2826 clear_registers() 2827 { 2828 int i; 2829 2830 for (i = 0; i < NUM_REGISTERS; ++i) 2831 { 2832 y_current = &y_regs[i]; 2833 if (y_current->y_array != NULL) 2834 free_yank_all(); 2835 } 2836 } 2837 #endif 2838 2839 /* 2840 * Free "n" lines from the current yank register. 2841 * Called for normal freeing and in case of error. 2842 */ 2843 static void 2844 free_yank(n) 2845 long n; 2846 { 2847 if (y_current->y_array != NULL) 2848 { 2849 long i; 2850 2851 for (i = n; --i >= 0; ) 2852 { 2853 #ifdef AMIGA /* only for very slow machines */ 2854 if ((i & 1023) == 1023) /* this may take a while */ 2855 { 2856 /* 2857 * This message should never cause a hit-return message. 2858 * Overwrite this message with any next message. 2859 */ 2860 ++no_wait_return; 2861 smsg((char_u *)_("freeing %ld lines"), i + 1); 2862 --no_wait_return; 2863 msg_didout = FALSE; 2864 msg_col = 0; 2865 } 2866 #endif 2867 vim_free(y_current->y_array[i]); 2868 } 2869 vim_free(y_current->y_array); 2870 y_current->y_array = NULL; 2871 #ifdef AMIGA 2872 if (n >= 1000) 2873 MSG(""); 2874 #endif 2875 } 2876 } 2877 2878 static void 2879 free_yank_all() 2880 { 2881 free_yank(y_current->y_size); 2882 } 2883 2884 /* 2885 * Yank the text between "oap->start" and "oap->end" into a yank register. 2886 * If we are to append (uppercase register), we first yank into a new yank 2887 * register and then concatenate the old and the new one (so we keep the old 2888 * one in case of out-of-memory). 2889 * 2890 * return FAIL for failure, OK otherwise 2891 */ 2892 int 2893 op_yank(oap, deleting, mess) 2894 oparg_T *oap; 2895 int deleting; 2896 int mess; 2897 { 2898 long y_idx; /* index in y_array[] */ 2899 struct yankreg *curr; /* copy of y_current */ 2900 struct yankreg newreg; /* new yank register when appending */ 2901 char_u **new_ptr; 2902 linenr_T lnum; /* current line number */ 2903 long j; 2904 int yanktype = oap->motion_type; 2905 long yanklines = oap->line_count; 2906 linenr_T yankendlnum = oap->end.lnum; 2907 char_u *p; 2908 char_u *pnew; 2909 struct block_def bd; 2910 #if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) 2911 int did_star = FALSE; 2912 #endif 2913 2914 /* check for read-only register */ 2915 if (oap->regname != 0 && !valid_yank_reg(oap->regname, TRUE)) 2916 { 2917 beep_flush(); 2918 return FAIL; 2919 } 2920 if (oap->regname == '_') /* black hole: nothing to do */ 2921 return OK; 2922 2923 #ifdef FEAT_CLIPBOARD 2924 if (!clip_star.available && oap->regname == '*') 2925 oap->regname = 0; 2926 else if (!clip_plus.available && oap->regname == '+') 2927 oap->regname = 0; 2928 #endif 2929 2930 if (!deleting) /* op_delete() already set y_current */ 2931 get_yank_register(oap->regname, TRUE); 2932 2933 curr = y_current; 2934 /* append to existing contents */ 2935 if (y_append && y_current->y_array != NULL) 2936 y_current = &newreg; 2937 else 2938 free_yank_all(); /* free previously yanked lines */ 2939 2940 /* 2941 * If the cursor was in column 1 before and after the movement, and the 2942 * operator is not inclusive, the yank is always linewise. 2943 */ 2944 if ( oap->motion_type == MCHAR 2945 && oap->start.col == 0 2946 && !oap->inclusive 2947 #ifdef FEAT_VISUAL 2948 && (!oap->is_VIsual || *p_sel == 'o') 2949 && !oap->block_mode 2950 #endif 2951 && oap->end.col == 0 2952 && yanklines > 1) 2953 { 2954 yanktype = MLINE; 2955 --yankendlnum; 2956 --yanklines; 2957 } 2958 2959 y_current->y_size = yanklines; 2960 y_current->y_type = yanktype; /* set the yank register type */ 2961 #ifdef FEAT_VISUAL 2962 y_current->y_width = 0; 2963 #endif 2964 y_current->y_array = (char_u **)lalloc_clear((long_u)(sizeof(char_u *) * 2965 yanklines), TRUE); 2966 2967 if (y_current->y_array == NULL) 2968 { 2969 y_current = curr; 2970 return FAIL; 2971 } 2972 2973 y_idx = 0; 2974 lnum = oap->start.lnum; 2975 2976 #ifdef FEAT_VISUAL 2977 if (oap->block_mode) 2978 { 2979 /* Visual block mode */ 2980 y_current->y_type = MBLOCK; /* set the yank register type */ 2981 y_current->y_width = oap->end_vcol - oap->start_vcol; 2982 2983 if (curwin->w_curswant == MAXCOL && y_current->y_width > 0) 2984 y_current->y_width--; 2985 } 2986 #endif 2987 2988 for ( ; lnum <= yankendlnum; lnum++, y_idx++) 2989 { 2990 switch (y_current->y_type) 2991 { 2992 #ifdef FEAT_VISUAL 2993 case MBLOCK: 2994 block_prep(oap, &bd, lnum, FALSE); 2995 if (yank_copy_line(&bd, y_idx) == FAIL) 2996 goto fail; 2997 break; 2998 #endif 2999 3000 case MLINE: 3001 if ((y_current->y_array[y_idx] = 3002 vim_strsave(ml_get(lnum))) == NULL) 3003 goto fail; 3004 break; 3005 3006 case MCHAR: 3007 { 3008 colnr_T startcol = 0, endcol = MAXCOL; 3009 #ifdef FEAT_VIRTUALEDIT 3010 int is_oneChar = FALSE; 3011 colnr_T cs, ce; 3012 #endif 3013 p = ml_get(lnum); 3014 bd.startspaces = 0; 3015 bd.endspaces = 0; 3016 3017 if (lnum == oap->start.lnum) 3018 { 3019 startcol = oap->start.col; 3020 #ifdef FEAT_VIRTUALEDIT 3021 if (virtual_op) 3022 { 3023 getvcol(curwin, &oap->start, &cs, NULL, &ce); 3024 if (ce != cs && oap->start.coladd > 0) 3025 { 3026 /* Part of a tab selected -- but don't 3027 * double-count it. */ 3028 bd.startspaces = (ce - cs + 1) 3029 - oap->start.coladd; 3030 startcol++; 3031 } 3032 } 3033 #endif 3034 } 3035 3036 if (lnum == oap->end.lnum) 3037 { 3038 endcol = oap->end.col; 3039 #ifdef FEAT_VIRTUALEDIT 3040 if (virtual_op) 3041 { 3042 getvcol(curwin, &oap->end, &cs, NULL, &ce); 3043 if (p[endcol] == NUL || (cs + oap->end.coladd < ce 3044 # ifdef FEAT_MBYTE 3045 /* Don't add space for double-wide 3046 * char; endcol will be on last byte 3047 * of multi-byte char. */ 3048 && (*mb_head_off)(p, p + endcol) == 0 3049 # endif 3050 )) 3051 { 3052 if (oap->start.lnum == oap->end.lnum 3053 && oap->start.col == oap->end.col) 3054 { 3055 /* Special case: inside a single char */ 3056 is_oneChar = TRUE; 3057 bd.startspaces = oap->end.coladd 3058 - oap->start.coladd + oap->inclusive; 3059 endcol = startcol; 3060 } 3061 else 3062 { 3063 bd.endspaces = oap->end.coladd 3064 + oap->inclusive; 3065 endcol -= oap->inclusive; 3066 } 3067 } 3068 } 3069 #endif 3070 } 3071 if (endcol == MAXCOL) 3072 endcol = (colnr_T)STRLEN(p); 3073 if (startcol > endcol 3074 #ifdef FEAT_VIRTUALEDIT 3075 || is_oneChar 3076 #endif 3077 ) 3078 bd.textlen = 0; 3079 else 3080 { 3081 bd.textlen = endcol - startcol + oap->inclusive; 3082 } 3083 bd.textstart = p + startcol; 3084 if (yank_copy_line(&bd, y_idx) == FAIL) 3085 goto fail; 3086 break; 3087 } 3088 /* NOTREACHED */ 3089 } 3090 } 3091 3092 if (curr != y_current) /* append the new block to the old block */ 3093 { 3094 new_ptr = (char_u **)lalloc((long_u)(sizeof(char_u *) * 3095 (curr->y_size + y_current->y_size)), TRUE); 3096 if (new_ptr == NULL) 3097 goto fail; 3098 for (j = 0; j < curr->y_size; ++j) 3099 new_ptr[j] = curr->y_array[j]; 3100 vim_free(curr->y_array); 3101 curr->y_array = new_ptr; 3102 3103 if (yanktype == MLINE) /* MLINE overrides MCHAR and MBLOCK */ 3104 curr->y_type = MLINE; 3105 3106 /* Concatenate the last line of the old block with the first line of 3107 * the new block, unless being Vi compatible. */ 3108 if (curr->y_type == MCHAR && vim_strchr(p_cpo, CPO_REGAPPEND) == NULL) 3109 { 3110 pnew = lalloc((long_u)(STRLEN(curr->y_array[curr->y_size - 1]) 3111 + STRLEN(y_current->y_array[0]) + 1), TRUE); 3112 if (pnew == NULL) 3113 { 3114 y_idx = y_current->y_size - 1; 3115 goto fail; 3116 } 3117 STRCPY(pnew, curr->y_array[--j]); 3118 STRCAT(pnew, y_current->y_array[0]); 3119 vim_free(curr->y_array[j]); 3120 vim_free(y_current->y_array[0]); 3121 curr->y_array[j++] = pnew; 3122 y_idx = 1; 3123 } 3124 else 3125 y_idx = 0; 3126 while (y_idx < y_current->y_size) 3127 curr->y_array[j++] = y_current->y_array[y_idx++]; 3128 curr->y_size = j; 3129 vim_free(y_current->y_array); 3130 y_current = curr; 3131 } 3132 if (mess) /* Display message about yank? */ 3133 { 3134 if (yanktype == MCHAR 3135 #ifdef FEAT_VISUAL 3136 && !oap->block_mode 3137 #endif 3138 && yanklines == 1) 3139 yanklines = 0; 3140 /* Some versions of Vi use ">=" here, some don't... */ 3141 if (yanklines > p_report) 3142 { 3143 /* redisplay now, so message is not deleted */ 3144 update_topline_redraw(); 3145 if (yanklines == 1) 3146 { 3147 #ifdef FEAT_VISUAL 3148 if (oap->block_mode) 3149 MSG(_("block of 1 line yanked")); 3150 else 3151 #endif 3152 MSG(_("1 line yanked")); 3153 } 3154 #ifdef FEAT_VISUAL 3155 else if (oap->block_mode) 3156 smsg((char_u *)_("block of %ld lines yanked"), yanklines); 3157 #endif 3158 else 3159 smsg((char_u *)_("%ld lines yanked"), yanklines); 3160 } 3161 } 3162 3163 /* 3164 * Set "'[" and "']" marks. 3165 */ 3166 curbuf->b_op_start = oap->start; 3167 curbuf->b_op_end = oap->end; 3168 if (yanktype == MLINE 3169 #ifdef FEAT_VISUAL 3170 && !oap->block_mode 3171 #endif 3172 ) 3173 { 3174 curbuf->b_op_start.col = 0; 3175 curbuf->b_op_end.col = MAXCOL; 3176 } 3177 3178 #ifdef FEAT_CLIPBOARD 3179 /* 3180 * If we were yanking to the '*' register, send result to clipboard. 3181 * If no register was specified, and "unnamed" in 'clipboard', make a copy 3182 * to the '*' register. 3183 */ 3184 if (clip_star.available 3185 && (curr == &(y_regs[STAR_REGISTER]) 3186 || (!deleting && oap->regname == 0 3187 && (clip_unnamed & CLIP_UNNAMED)))) 3188 { 3189 if (curr != &(y_regs[STAR_REGISTER])) 3190 /* Copy the text from register 0 to the clipboard register. */ 3191 copy_yank_reg(&(y_regs[STAR_REGISTER])); 3192 3193 clip_own_selection(&clip_star); 3194 clip_gen_set_selection(&clip_star); 3195 # ifdef FEAT_X11 3196 did_star = TRUE; 3197 # endif 3198 } 3199 3200 # ifdef FEAT_X11 3201 /* 3202 * If we were yanking to the '+' register, send result to selection. 3203 * Also copy to the '*' register, in case auto-select is off. 3204 */ 3205 if (clip_plus.available 3206 && (curr == &(y_regs[PLUS_REGISTER]) 3207 || (!deleting && oap->regname == 0 3208 && (clip_unnamed & CLIP_UNNAMED_PLUS)))) 3209 { 3210 if (curr != &(y_regs[PLUS_REGISTER])) 3211 /* Copy the text from register 0 to the clipboard register. */ 3212 copy_yank_reg(&(y_regs[PLUS_REGISTER])); 3213 3214 clip_own_selection(&clip_plus); 3215 clip_gen_set_selection(&clip_plus); 3216 if (!clip_isautosel_star() && !did_star 3217 && curr == &(y_regs[PLUS_REGISTER])) 3218 { 3219 copy_yank_reg(&(y_regs[STAR_REGISTER])); 3220 clip_own_selection(&clip_star); 3221 clip_gen_set_selection(&clip_star); 3222 } 3223 } 3224 # endif 3225 #endif 3226 3227 return OK; 3228 3229 fail: /* free the allocated lines */ 3230 free_yank(y_idx + 1); 3231 y_current = curr; 3232 return FAIL; 3233 } 3234 3235 static int 3236 yank_copy_line(bd, y_idx) 3237 struct block_def *bd; 3238 long y_idx; 3239 { 3240 char_u *pnew; 3241 3242 if ((pnew = alloc(bd->startspaces + bd->endspaces + bd->textlen + 1)) 3243 == NULL) 3244 return FAIL; 3245 y_current->y_array[y_idx] = pnew; 3246 copy_spaces(pnew, (size_t)bd->startspaces); 3247 pnew += bd->startspaces; 3248 mch_memmove(pnew, bd->textstart, (size_t)bd->textlen); 3249 pnew += bd->textlen; 3250 copy_spaces(pnew, (size_t)bd->endspaces); 3251 pnew += bd->endspaces; 3252 *pnew = NUL; 3253 return OK; 3254 } 3255 3256 #ifdef FEAT_CLIPBOARD 3257 /* 3258 * Make a copy of the y_current register to register "reg". 3259 */ 3260 static void 3261 copy_yank_reg(reg) 3262 struct yankreg *reg; 3263 { 3264 struct yankreg *curr = y_current; 3265 long j; 3266 3267 y_current = reg; 3268 free_yank_all(); 3269 *y_current = *curr; 3270 y_current->y_array = (char_u **)lalloc_clear( 3271 (long_u)(sizeof(char_u *) * y_current->y_size), TRUE); 3272 if (y_current->y_array == NULL) 3273 y_current->y_size = 0; 3274 else 3275 for (j = 0; j < y_current->y_size; ++j) 3276 if ((y_current->y_array[j] = vim_strsave(curr->y_array[j])) == NULL) 3277 { 3278 free_yank(j); 3279 y_current->y_size = 0; 3280 break; 3281 } 3282 y_current = curr; 3283 } 3284 #endif 3285 3286 /* 3287 * Put contents of register "regname" into the text. 3288 * Caller must check "regname" to be valid! 3289 * "flags": PUT_FIXINDENT make indent look nice 3290 * PUT_CURSEND leave cursor after end of new text 3291 * PUT_LINE force linewise put (":put") 3292 */ 3293 void 3294 do_put(regname, dir, count, flags) 3295 int regname; 3296 int dir; /* BACKWARD for 'P', FORWARD for 'p' */ 3297 long count; 3298 int flags; 3299 { 3300 char_u *ptr; 3301 char_u *newp, *oldp; 3302 int yanklen; 3303 int totlen = 0; /* init for gcc */ 3304 linenr_T lnum; 3305 colnr_T col; 3306 long i; /* index in y_array[] */ 3307 int y_type; 3308 long y_size; 3309 #ifdef FEAT_VISUAL 3310 int oldlen; 3311 long y_width = 0; 3312 colnr_T vcol; 3313 int delcount; 3314 int incr = 0; 3315 long j; 3316 struct block_def bd; 3317 #endif 3318 char_u **y_array = NULL; 3319 long nr_lines = 0; 3320 pos_T new_cursor; 3321 int indent; 3322 int orig_indent = 0; /* init for gcc */ 3323 int indent_diff = 0; /* init for gcc */ 3324 int first_indent = TRUE; 3325 int lendiff = 0; 3326 pos_T old_pos; 3327 char_u *insert_string = NULL; 3328 int allocated = FALSE; 3329 long cnt; 3330 3331 #ifdef FEAT_CLIPBOARD 3332 /* Adjust register name for "unnamed" in 'clipboard'. */ 3333 adjust_clip_reg(®name); 3334 (void)may_get_selection(regname); 3335 #endif 3336 3337 if (flags & PUT_FIXINDENT) 3338 orig_indent = get_indent(); 3339 3340 curbuf->b_op_start = curwin->w_cursor; /* default for '[ mark */ 3341 curbuf->b_op_end = curwin->w_cursor; /* default for '] mark */ 3342 3343 /* 3344 * Using inserted text works differently, because the register includes 3345 * special characters (newlines, etc.). 3346 */ 3347 if (regname == '.') 3348 { 3349 (void)stuff_inserted((dir == FORWARD ? (count == -1 ? 'o' : 'a') : 3350 (count == -1 ? 'O' : 'i')), count, FALSE); 3351 /* Putting the text is done later, so can't really move the cursor to 3352 * the next character. Use "l" to simulate it. */ 3353 if ((flags & PUT_CURSEND) && gchar_cursor() != NUL) 3354 stuffcharReadbuff('l'); 3355 return; 3356 } 3357 3358 /* 3359 * For special registers '%' (file name), '#' (alternate file name) and 3360 * ':' (last command line), etc. we have to create a fake yank register. 3361 */ 3362 if (get_spec_reg(regname, &insert_string, &allocated, TRUE)) 3363 { 3364 if (insert_string == NULL) 3365 return; 3366 } 3367 3368 #ifdef FEAT_AUTOCMD 3369 /* Autocommands may be executed when saving lines for undo, which may make 3370 * y_array invalid. Start undo now to avoid that. */ 3371 u_save(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1); 3372 #endif 3373 3374 if (insert_string != NULL) 3375 { 3376 y_type = MCHAR; 3377 #ifdef FEAT_EVAL 3378 if (regname == '=') 3379 { 3380 /* For the = register we need to split the string at NL 3381 * characters. 3382 * Loop twice: count the number of lines and save them. */ 3383 for (;;) 3384 { 3385 y_size = 0; 3386 ptr = insert_string; 3387 while (ptr != NULL) 3388 { 3389 if (y_array != NULL) 3390 y_array[y_size] = ptr; 3391 ++y_size; 3392 ptr = vim_strchr(ptr, '\n'); 3393 if (ptr != NULL) 3394 { 3395 if (y_array != NULL) 3396 *ptr = NUL; 3397 ++ptr; 3398 /* A trailing '\n' makes the register linewise. */ 3399 if (*ptr == NUL) 3400 { 3401 y_type = MLINE; 3402 break; 3403 } 3404 } 3405 } 3406 if (y_array != NULL) 3407 break; 3408 y_array = (char_u **)alloc((unsigned) 3409 (y_size * sizeof(char_u *))); 3410 if (y_array == NULL) 3411 goto end; 3412 } 3413 } 3414 else 3415 #endif 3416 { 3417 y_size = 1; /* use fake one-line yank register */ 3418 y_array = &insert_string; 3419 } 3420 } 3421 else 3422 { 3423 get_yank_register(regname, FALSE); 3424 3425 y_type = y_current->y_type; 3426 #ifdef FEAT_VISUAL 3427 y_width = y_current->y_width; 3428 #endif 3429 y_size = y_current->y_size; 3430 y_array = y_current->y_array; 3431 } 3432 3433 #ifdef FEAT_VISUAL 3434 if (y_type == MLINE) 3435 { 3436 if (flags & PUT_LINE_SPLIT) 3437 { 3438 /* "p" or "P" in Visual mode: split the lines to put the text in 3439 * between. */ 3440 if (u_save_cursor() == FAIL) 3441 goto end; 3442 ptr = vim_strsave(ml_get_cursor()); 3443 if (ptr == NULL) 3444 goto end; 3445 ml_append(curwin->w_cursor.lnum, ptr, (colnr_T)0, FALSE); 3446 vim_free(ptr); 3447 3448 ptr = vim_strnsave(ml_get_curline(), curwin->w_cursor.col); 3449 if (ptr == NULL) 3450 goto end; 3451 ml_replace(curwin->w_cursor.lnum, ptr, FALSE); 3452 ++nr_lines; 3453 dir = FORWARD; 3454 } 3455 if (flags & PUT_LINE_FORWARD) 3456 { 3457 /* Must be "p" for a Visual block, put lines below the block. */ 3458 curwin->w_cursor = curbuf->b_visual.vi_end; 3459 dir = FORWARD; 3460 } 3461 curbuf->b_op_start = curwin->w_cursor; /* default for '[ mark */ 3462 curbuf->b_op_end = curwin->w_cursor; /* default for '] mark */ 3463 } 3464 #endif 3465 3466 if (flags & PUT_LINE) /* :put command or "p" in Visual line mode. */ 3467 y_type = MLINE; 3468 3469 if (y_size == 0 || y_array == NULL) 3470 { 3471 EMSG2(_("E353: Nothing in register %s"), 3472 regname == 0 ? (char_u *)"\"" : transchar(regname)); 3473 goto end; 3474 } 3475 3476 #ifdef FEAT_VISUAL 3477 if (y_type == MBLOCK) 3478 { 3479 lnum = curwin->w_cursor.lnum + y_size + 1; 3480 if (lnum > curbuf->b_ml.ml_line_count) 3481 lnum = curbuf->b_ml.ml_line_count + 1; 3482 if (u_save(curwin->w_cursor.lnum - 1, lnum) == FAIL) 3483 goto end; 3484 } 3485 else 3486 #endif 3487 if (y_type == MLINE) 3488 { 3489 lnum = curwin->w_cursor.lnum; 3490 #ifdef FEAT_FOLDING 3491 /* Correct line number for closed fold. Don't move the cursor yet, 3492 * u_save() uses it. */ 3493 if (dir == BACKWARD) 3494 (void)hasFolding(lnum, &lnum, NULL); 3495 else 3496 (void)hasFolding(lnum, NULL, &lnum); 3497 #endif 3498 if (dir == FORWARD) 3499 ++lnum; 3500 if (u_save(lnum - 1, lnum) == FAIL) 3501 goto end; 3502 #ifdef FEAT_FOLDING 3503 if (dir == FORWARD) 3504 curwin->w_cursor.lnum = lnum - 1; 3505 else 3506 curwin->w_cursor.lnum = lnum; 3507 curbuf->b_op_start = curwin->w_cursor; /* for mark_adjust() */ 3508 #endif 3509 } 3510 else if (u_save_cursor() == FAIL) 3511 goto end; 3512 3513 yanklen = (int)STRLEN(y_array[0]); 3514 3515 #ifdef FEAT_VIRTUALEDIT 3516 if (ve_flags == VE_ALL && y_type == MCHAR) 3517 { 3518 if (gchar_cursor() == TAB) 3519 { 3520 /* Don't need to insert spaces when "p" on the last position of a 3521 * tab or "P" on the first position. */ 3522 if (dir == FORWARD 3523 ? (int)curwin->w_cursor.coladd < curbuf->b_p_ts - 1 3524 : curwin->w_cursor.coladd > 0) 3525 coladvance_force(getviscol()); 3526 else 3527 curwin->w_cursor.coladd = 0; 3528 } 3529 else if (curwin->w_cursor.coladd > 0 || gchar_cursor() == NUL) 3530 coladvance_force(getviscol() + (dir == FORWARD)); 3531 } 3532 #endif 3533 3534 lnum = curwin->w_cursor.lnum; 3535 col = curwin->w_cursor.col; 3536 3537 #ifdef FEAT_VISUAL 3538 /* 3539 * Block mode 3540 */ 3541 if (y_type == MBLOCK) 3542 { 3543 char c = gchar_cursor(); 3544 colnr_T endcol2 = 0; 3545 3546 if (dir == FORWARD && c != NUL) 3547 { 3548 #ifdef FEAT_VIRTUALEDIT 3549 if (ve_flags == VE_ALL) 3550 getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2); 3551 else 3552 #endif 3553 getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col); 3554 3555 #ifdef FEAT_MBYTE 3556 if (has_mbyte) 3557 /* move to start of next multi-byte character */ 3558 curwin->w_cursor.col += (*mb_ptr2len)(ml_get_cursor()); 3559 else 3560 #endif 3561 #ifdef FEAT_VIRTUALEDIT 3562 if (c != TAB || ve_flags != VE_ALL) 3563 #endif 3564 ++curwin->w_cursor.col; 3565 ++col; 3566 } 3567 else 3568 getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2); 3569 3570 #ifdef FEAT_VIRTUALEDIT 3571 col += curwin->w_cursor.coladd; 3572 if (ve_flags == VE_ALL 3573 && (curwin->w_cursor.coladd > 0 3574 || endcol2 == curwin->w_cursor.col)) 3575 { 3576 if (dir == FORWARD && c == NUL) 3577 ++col; 3578 if (dir != FORWARD && c != NUL) 3579 ++curwin->w_cursor.col; 3580 if (c == TAB) 3581 { 3582 if (dir == BACKWARD && curwin->w_cursor.col) 3583 curwin->w_cursor.col--; 3584 if (dir == FORWARD && col - 1 == endcol2) 3585 curwin->w_cursor.col++; 3586 } 3587 } 3588 curwin->w_cursor.coladd = 0; 3589 #endif 3590 bd.textcol = 0; 3591 for (i = 0; i < y_size; ++i) 3592 { 3593 int spaces; 3594 char shortline; 3595 3596 bd.startspaces = 0; 3597 bd.endspaces = 0; 3598 vcol = 0; 3599 delcount = 0; 3600 3601 /* add a new line */ 3602 if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) 3603 { 3604 if (ml_append(curbuf->b_ml.ml_line_count, (char_u *)"", 3605 (colnr_T)1, FALSE) == FAIL) 3606 break; 3607 ++nr_lines; 3608 } 3609 /* get the old line and advance to the position to insert at */ 3610 oldp = ml_get_curline(); 3611 oldlen = (int)STRLEN(oldp); 3612 for (ptr = oldp; vcol < col && *ptr; ) 3613 { 3614 /* Count a tab for what it's worth (if list mode not on) */ 3615 incr = lbr_chartabsize_adv(&ptr, (colnr_T)vcol); 3616 vcol += incr; 3617 } 3618 bd.textcol = (colnr_T)(ptr - oldp); 3619 3620 shortline = (vcol < col) || (vcol == col && !*ptr) ; 3621 3622 if (vcol < col) /* line too short, padd with spaces */ 3623 bd.startspaces = col - vcol; 3624 else if (vcol > col) 3625 { 3626 bd.endspaces = vcol - col; 3627 bd.startspaces = incr - bd.endspaces; 3628 --bd.textcol; 3629 delcount = 1; 3630 #ifdef FEAT_MBYTE 3631 if (has_mbyte) 3632 bd.textcol -= (*mb_head_off)(oldp, oldp + bd.textcol); 3633 #endif 3634 if (oldp[bd.textcol] != TAB) 3635 { 3636 /* Only a Tab can be split into spaces. Other 3637 * characters will have to be moved to after the 3638 * block, causing misalignment. */ 3639 delcount = 0; 3640 bd.endspaces = 0; 3641 } 3642 } 3643 3644 yanklen = (int)STRLEN(y_array[i]); 3645 3646 /* calculate number of spaces required to fill right side of block*/ 3647 spaces = y_width + 1; 3648 for (j = 0; j < yanklen; j++) 3649 spaces -= lbr_chartabsize(&y_array[i][j], 0); 3650 if (spaces < 0) 3651 spaces = 0; 3652 3653 /* insert the new text */ 3654 totlen = count * (yanklen + spaces) + bd.startspaces + bd.endspaces; 3655 newp = alloc_check((unsigned)totlen + oldlen + 1); 3656 if (newp == NULL) 3657 break; 3658 /* copy part up to cursor to new line */ 3659 ptr = newp; 3660 mch_memmove(ptr, oldp, (size_t)bd.textcol); 3661 ptr += bd.textcol; 3662 /* may insert some spaces before the new text */ 3663 copy_spaces(ptr, (size_t)bd.startspaces); 3664 ptr += bd.startspaces; 3665 /* insert the new text */ 3666 for (j = 0; j < count; ++j) 3667 { 3668 mch_memmove(ptr, y_array[i], (size_t)yanklen); 3669 ptr += yanklen; 3670 3671 /* insert block's trailing spaces only if there's text behind */ 3672 if ((j < count - 1 || !shortline) && spaces) 3673 { 3674 copy_spaces(ptr, (size_t)spaces); 3675 ptr += spaces; 3676 } 3677 } 3678 /* may insert some spaces after the new text */ 3679 copy_spaces(ptr, (size_t)bd.endspaces); 3680 ptr += bd.endspaces; 3681 /* move the text after the cursor to the end of the line. */ 3682 mch_memmove(ptr, oldp + bd.textcol + delcount, 3683 (size_t)(oldlen - bd.textcol - delcount + 1)); 3684 ml_replace(curwin->w_cursor.lnum, newp, FALSE); 3685 3686 ++curwin->w_cursor.lnum; 3687 if (i == 0) 3688 curwin->w_cursor.col += bd.startspaces; 3689 } 3690 3691 changed_lines(lnum, 0, curwin->w_cursor.lnum, nr_lines); 3692 3693 /* Set '[ mark. */ 3694 curbuf->b_op_start = curwin->w_cursor; 3695 curbuf->b_op_start.lnum = lnum; 3696 3697 /* adjust '] mark */ 3698 curbuf->b_op_end.lnum = curwin->w_cursor.lnum - 1; 3699 curbuf->b_op_end.col = bd.textcol + totlen - 1; 3700 # ifdef FEAT_VIRTUALEDIT 3701 curbuf->b_op_end.coladd = 0; 3702 # endif 3703 if (flags & PUT_CURSEND) 3704 { 3705 colnr_T len; 3706 3707 curwin->w_cursor = curbuf->b_op_end; 3708 curwin->w_cursor.col++; 3709 3710 /* in Insert mode we might be after the NUL, correct for that */ 3711 len = (colnr_T)STRLEN(ml_get_curline()); 3712 if (curwin->w_cursor.col > len) 3713 curwin->w_cursor.col = len; 3714 } 3715 else 3716 curwin->w_cursor.lnum = lnum; 3717 } 3718 else 3719 #endif 3720 { 3721 /* 3722 * Character or Line mode 3723 */ 3724 if (y_type == MCHAR) 3725 { 3726 /* if type is MCHAR, FORWARD is the same as BACKWARD on the next 3727 * char */ 3728 if (dir == FORWARD && gchar_cursor() != NUL) 3729 { 3730 #ifdef FEAT_MBYTE 3731 if (has_mbyte) 3732 { 3733 int bytelen = (*mb_ptr2len)(ml_get_cursor()); 3734 3735 /* put it on the next of the multi-byte character. */ 3736 col += bytelen; 3737 if (yanklen) 3738 { 3739 curwin->w_cursor.col += bytelen; 3740 curbuf->b_op_end.col += bytelen; 3741 } 3742 } 3743 else 3744 #endif 3745 { 3746 ++col; 3747 if (yanklen) 3748 { 3749 ++curwin->w_cursor.col; 3750 ++curbuf->b_op_end.col; 3751 } 3752 } 3753 } 3754 curbuf->b_op_start = curwin->w_cursor; 3755 } 3756 /* 3757 * Line mode: BACKWARD is the same as FORWARD on the previous line 3758 */ 3759 else if (dir == BACKWARD) 3760 --lnum; 3761 new_cursor = curwin->w_cursor; 3762 3763 /* 3764 * simple case: insert into current line 3765 */ 3766 if (y_type == MCHAR && y_size == 1) 3767 { 3768 totlen = count * yanklen; 3769 if (totlen) 3770 { 3771 oldp = ml_get(lnum); 3772 newp = alloc_check((unsigned)(STRLEN(oldp) + totlen + 1)); 3773 if (newp == NULL) 3774 goto end; /* alloc() will give error message */ 3775 mch_memmove(newp, oldp, (size_t)col); 3776 ptr = newp + col; 3777 for (i = 0; i < count; ++i) 3778 { 3779 mch_memmove(ptr, y_array[0], (size_t)yanklen); 3780 ptr += yanklen; 3781 } 3782 STRMOVE(ptr, oldp + col); 3783 ml_replace(lnum, newp, FALSE); 3784 /* Put cursor on last putted char. */ 3785 curwin->w_cursor.col += (colnr_T)(totlen - 1); 3786 } 3787 curbuf->b_op_end = curwin->w_cursor; 3788 /* For "CTRL-O p" in Insert mode, put cursor after last char */ 3789 if (totlen && (restart_edit != 0 || (flags & PUT_CURSEND))) 3790 ++curwin->w_cursor.col; 3791 changed_bytes(lnum, col); 3792 } 3793 else 3794 { 3795 /* 3796 * Insert at least one line. When y_type is MCHAR, break the first 3797 * line in two. 3798 */ 3799 for (cnt = 1; cnt <= count; ++cnt) 3800 { 3801 i = 0; 3802 if (y_type == MCHAR) 3803 { 3804 /* 3805 * Split the current line in two at the insert position. 3806 * First insert y_array[size - 1] in front of second line. 3807 * Then append y_array[0] to first line. 3808 */ 3809 lnum = new_cursor.lnum; 3810 ptr = ml_get(lnum) + col; 3811 totlen = (int)STRLEN(y_array[y_size - 1]); 3812 newp = alloc_check((unsigned)(STRLEN(ptr) + totlen + 1)); 3813 if (newp == NULL) 3814 goto error; 3815 STRCPY(newp, y_array[y_size - 1]); 3816 STRCAT(newp, ptr); 3817 /* insert second line */ 3818 ml_append(lnum, newp, (colnr_T)0, FALSE); 3819 vim_free(newp); 3820 3821 oldp = ml_get(lnum); 3822 newp = alloc_check((unsigned)(col + yanklen + 1)); 3823 if (newp == NULL) 3824 goto error; 3825 /* copy first part of line */ 3826 mch_memmove(newp, oldp, (size_t)col); 3827 /* append to first line */ 3828 mch_memmove(newp + col, y_array[0], (size_t)(yanklen + 1)); 3829 ml_replace(lnum, newp, FALSE); 3830 3831 curwin->w_cursor.lnum = lnum; 3832 i = 1; 3833 } 3834 3835 for (; i < y_size; ++i) 3836 { 3837 if ((y_type != MCHAR || i < y_size - 1) 3838 && ml_append(lnum, y_array[i], (colnr_T)0, FALSE) 3839 == FAIL) 3840 goto error; 3841 lnum++; 3842 ++nr_lines; 3843 if (flags & PUT_FIXINDENT) 3844 { 3845 old_pos = curwin->w_cursor; 3846 curwin->w_cursor.lnum = lnum; 3847 ptr = ml_get(lnum); 3848 if (cnt == count && i == y_size - 1) 3849 lendiff = (int)STRLEN(ptr); 3850 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) 3851 if (*ptr == '#' && preprocs_left()) 3852 indent = 0; /* Leave # lines at start */ 3853 else 3854 #endif 3855 if (*ptr == NUL) 3856 indent = 0; /* Ignore empty lines */ 3857 else if (first_indent) 3858 { 3859 indent_diff = orig_indent - get_indent(); 3860 indent = orig_indent; 3861 first_indent = FALSE; 3862 } 3863 else if ((indent = get_indent() + indent_diff) < 0) 3864 indent = 0; 3865 (void)set_indent(indent, 0); 3866 curwin->w_cursor = old_pos; 3867 /* remember how many chars were removed */ 3868 if (cnt == count && i == y_size - 1) 3869 lendiff -= (int)STRLEN(ml_get(lnum)); 3870 } 3871 } 3872 } 3873 3874 error: 3875 /* Adjust marks. */ 3876 if (y_type == MLINE) 3877 { 3878 curbuf->b_op_start.col = 0; 3879 if (dir == FORWARD) 3880 curbuf->b_op_start.lnum++; 3881 } 3882 mark_adjust(curbuf->b_op_start.lnum + (y_type == MCHAR), 3883 (linenr_T)MAXLNUM, nr_lines, 0L); 3884 3885 /* note changed text for displaying and folding */ 3886 if (y_type == MCHAR) 3887 changed_lines(curwin->w_cursor.lnum, col, 3888 curwin->w_cursor.lnum + 1, nr_lines); 3889 else 3890 changed_lines(curbuf->b_op_start.lnum, 0, 3891 curbuf->b_op_start.lnum, nr_lines); 3892 3893 /* put '] mark at last inserted character */ 3894 curbuf->b_op_end.lnum = lnum; 3895 /* correct length for change in indent */ 3896 col = (colnr_T)STRLEN(y_array[y_size - 1]) - lendiff; 3897 if (col > 1) 3898 curbuf->b_op_end.col = col - 1; 3899 else 3900 curbuf->b_op_end.col = 0; 3901 3902 if (flags & PUT_CURSLINE) 3903 { 3904 /* ":put": put cursor on last inserted line */ 3905 curwin->w_cursor.lnum = lnum; 3906 beginline(BL_WHITE | BL_FIX); 3907 } 3908 else if (flags & PUT_CURSEND) 3909 { 3910 /* put cursor after inserted text */ 3911 if (y_type == MLINE) 3912 { 3913 if (lnum >= curbuf->b_ml.ml_line_count) 3914 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 3915 else 3916 curwin->w_cursor.lnum = lnum + 1; 3917 curwin->w_cursor.col = 0; 3918 } 3919 else 3920 { 3921 curwin->w_cursor.lnum = lnum; 3922 curwin->w_cursor.col = col; 3923 } 3924 } 3925 else if (y_type == MLINE) 3926 { 3927 /* put cursor on first non-blank in first inserted line */ 3928 curwin->w_cursor.col = 0; 3929 if (dir == FORWARD) 3930 ++curwin->w_cursor.lnum; 3931 beginline(BL_WHITE | BL_FIX); 3932 } 3933 else /* put cursor on first inserted character */ 3934 curwin->w_cursor = new_cursor; 3935 } 3936 } 3937 3938 msgmore(nr_lines); 3939 curwin->w_set_curswant = TRUE; 3940 3941 end: 3942 if (allocated) 3943 vim_free(insert_string); 3944 if (regname == '=') 3945 vim_free(y_array); 3946 3947 /* If the cursor is past the end of the line put it at the end. */ 3948 adjust_cursor_eol(); 3949 } 3950 3951 /* 3952 * When the cursor is on the NUL past the end of the line and it should not be 3953 * there move it left. 3954 */ 3955 void 3956 adjust_cursor_eol() 3957 { 3958 if (curwin->w_cursor.col > 0 3959 && gchar_cursor() == NUL 3960 #ifdef FEAT_VIRTUALEDIT 3961 && (ve_flags & VE_ONEMORE) == 0 3962 #endif 3963 && !(restart_edit || (State & INSERT))) 3964 { 3965 /* Put the cursor on the last character in the line. */ 3966 dec_cursor(); 3967 3968 #ifdef FEAT_VIRTUALEDIT 3969 if (ve_flags == VE_ALL) 3970 { 3971 colnr_T scol, ecol; 3972 3973 /* Coladd is set to the width of the last character. */ 3974 getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol); 3975 curwin->w_cursor.coladd = ecol - scol + 1; 3976 } 3977 #endif 3978 } 3979 } 3980 3981 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT) || defined(PROTO) 3982 /* 3983 * Return TRUE if lines starting with '#' should be left aligned. 3984 */ 3985 int 3986 preprocs_left() 3987 { 3988 return 3989 # ifdef FEAT_SMARTINDENT 3990 # ifdef FEAT_CINDENT 3991 (curbuf->b_p_si && !curbuf->b_p_cin) || 3992 # else 3993 curbuf->b_p_si 3994 # endif 3995 # endif 3996 # ifdef FEAT_CINDENT 3997 (curbuf->b_p_cin && in_cinkeys('#', ' ', TRUE)) 3998 # endif 3999 ; 4000 } 4001 #endif 4002 4003 /* Return the character name of the register with the given number */ 4004 int 4005 get_register_name(num) 4006 int num; 4007 { 4008 if (num == -1) 4009 return '"'; 4010 else if (num < 10) 4011 return num + '0'; 4012 else if (num == DELETION_REGISTER) 4013 return '-'; 4014 #ifdef FEAT_CLIPBOARD 4015 else if (num == STAR_REGISTER) 4016 return '*'; 4017 else if (num == PLUS_REGISTER) 4018 return '+'; 4019 #endif 4020 else 4021 { 4022 #ifdef EBCDIC 4023 int i; 4024 4025 /* EBCDIC is really braindead ... */ 4026 i = 'a' + (num - 10); 4027 if (i > 'i') 4028 i += 7; 4029 if (i > 'r') 4030 i += 8; 4031 return i; 4032 #else 4033 return num + 'a' - 10; 4034 #endif 4035 } 4036 } 4037 4038 /* 4039 * ":dis" and ":registers": Display the contents of the yank registers. 4040 */ 4041 void 4042 ex_display(eap) 4043 exarg_T *eap; 4044 { 4045 int i, n; 4046 long j; 4047 char_u *p; 4048 struct yankreg *yb; 4049 int name; 4050 int attr; 4051 char_u *arg = eap->arg; 4052 #ifdef FEAT_MBYTE 4053 int clen; 4054 #else 4055 # define clen 1 4056 #endif 4057 4058 if (arg != NULL && *arg == NUL) 4059 arg = NULL; 4060 attr = hl_attr(HLF_8); 4061 4062 /* Highlight title */ 4063 MSG_PUTS_TITLE(_("\n--- Registers ---")); 4064 for (i = -1; i < NUM_REGISTERS && !got_int; ++i) 4065 { 4066 name = get_register_name(i); 4067 if (arg != NULL && vim_strchr(arg, name) == NULL 4068 #ifdef ONE_CLIPBOARD 4069 /* Star register and plus register contain the same thing. */ 4070 && (name != '*' || vim_strchr(arg, '+') == NULL) 4071 #endif 4072 ) 4073 continue; /* did not ask for this register */ 4074 4075 #ifdef FEAT_CLIPBOARD 4076 /* Adjust register name for "unnamed" in 'clipboard'. 4077 * When it's a clipboard register, fill it with the current contents 4078 * of the clipboard. */ 4079 adjust_clip_reg(&name); 4080 (void)may_get_selection(name); 4081 #endif 4082 4083 if (i == -1) 4084 { 4085 if (y_previous != NULL) 4086 yb = y_previous; 4087 else 4088 yb = &(y_regs[0]); 4089 } 4090 else 4091 yb = &(y_regs[i]); 4092 4093 #ifdef FEAT_EVAL 4094 if (name == MB_TOLOWER(redir_reg) 4095 || (redir_reg == '"' && yb == y_previous)) 4096 continue; /* do not list register being written to, the 4097 * pointer can be freed */ 4098 #endif 4099 4100 if (yb->y_array != NULL) 4101 { 4102 msg_putchar('\n'); 4103 msg_putchar('"'); 4104 msg_putchar(name); 4105 MSG_PUTS(" "); 4106 4107 n = (int)Columns - 6; 4108 for (j = 0; j < yb->y_size && n > 1; ++j) 4109 { 4110 if (j) 4111 { 4112 MSG_PUTS_ATTR("^J", attr); 4113 n -= 2; 4114 } 4115 for (p = yb->y_array[j]; *p && (n -= ptr2cells(p)) >= 0; ++p) 4116 { 4117 #ifdef FEAT_MBYTE 4118 clen = (*mb_ptr2len)(p); 4119 #endif 4120 msg_outtrans_len(p, clen); 4121 #ifdef FEAT_MBYTE 4122 p += clen - 1; 4123 #endif 4124 } 4125 } 4126 if (n > 1 && yb->y_type == MLINE) 4127 MSG_PUTS_ATTR("^J", attr); 4128 out_flush(); /* show one line at a time */ 4129 } 4130 ui_breakcheck(); 4131 } 4132 4133 /* 4134 * display last inserted text 4135 */ 4136 if ((p = get_last_insert()) != NULL 4137 && (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int) 4138 { 4139 MSG_PUTS("\n\". "); 4140 dis_msg(p, TRUE); 4141 } 4142 4143 /* 4144 * display last command line 4145 */ 4146 if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL) 4147 && !got_int) 4148 { 4149 MSG_PUTS("\n\": "); 4150 dis_msg(last_cmdline, FALSE); 4151 } 4152 4153 /* 4154 * display current file name 4155 */ 4156 if (curbuf->b_fname != NULL 4157 && (arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int) 4158 { 4159 MSG_PUTS("\n\"% "); 4160 dis_msg(curbuf->b_fname, FALSE); 4161 } 4162 4163 /* 4164 * display alternate file name 4165 */ 4166 if ((arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int) 4167 { 4168 char_u *fname; 4169 linenr_T dummy; 4170 4171 if (buflist_name_nr(0, &fname, &dummy) != FAIL) 4172 { 4173 MSG_PUTS("\n\"# "); 4174 dis_msg(fname, FALSE); 4175 } 4176 } 4177 4178 /* 4179 * display last search pattern 4180 */ 4181 if (last_search_pat() != NULL 4182 && (arg == NULL || vim_strchr(arg, '/') != NULL) && !got_int) 4183 { 4184 MSG_PUTS("\n\"/ "); 4185 dis_msg(last_search_pat(), FALSE); 4186 } 4187 4188 #ifdef FEAT_EVAL 4189 /* 4190 * display last used expression 4191 */ 4192 if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL) 4193 && !got_int) 4194 { 4195 MSG_PUTS("\n\"= "); 4196 dis_msg(expr_line, FALSE); 4197 } 4198 #endif 4199 } 4200 4201 /* 4202 * display a string for do_dis() 4203 * truncate at end of screen line 4204 */ 4205 static void 4206 dis_msg(p, skip_esc) 4207 char_u *p; 4208 int skip_esc; /* if TRUE, ignore trailing ESC */ 4209 { 4210 int n; 4211 #ifdef FEAT_MBYTE 4212 int l; 4213 #endif 4214 4215 n = (int)Columns - 6; 4216 while (*p != NUL 4217 && !(*p == ESC && skip_esc && *(p + 1) == NUL) 4218 && (n -= ptr2cells(p)) >= 0) 4219 { 4220 #ifdef FEAT_MBYTE 4221 if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) 4222 { 4223 msg_outtrans_len(p, l); 4224 p += l; 4225 } 4226 else 4227 #endif 4228 msg_outtrans_len(p++, 1); 4229 } 4230 ui_breakcheck(); 4231 } 4232 4233 #if defined(FEAT_COMMENTS) || defined(PROTO) 4234 /* 4235 * If "process" is TRUE and the line begins with a comment leader (possibly 4236 * after some white space), return a pointer to the text after it. Put a boolean 4237 * value indicating whether the line ends with an unclosed comment in 4238 * "is_comment". 4239 * line - line to be processed, 4240 * process - if FALSE, will only check whether the line ends with an unclosed 4241 * comment, 4242 * include_space - whether to also skip space following the comment leader, 4243 * is_comment - will indicate whether the current line ends with an unclosed 4244 * comment. 4245 */ 4246 static char_u * 4247 skip_comment(line, process, include_space, is_comment) 4248 char_u *line; 4249 int process; 4250 int include_space; 4251 int *is_comment; 4252 { 4253 char_u *comment_flags = NULL; 4254 int lead_len; 4255 int leader_offset = get_last_leader_offset(line, &comment_flags); 4256 4257 *is_comment = FALSE; 4258 if (leader_offset != -1) 4259 { 4260 /* Let's check whether the line ends with an unclosed comment. 4261 * If the last comment leader has COM_END in flags, there's no comment. 4262 */ 4263 while (*comment_flags) 4264 { 4265 if (*comment_flags == COM_END 4266 || *comment_flags == ':') 4267 break; 4268 ++comment_flags; 4269 } 4270 if (*comment_flags != COM_END) 4271 *is_comment = TRUE; 4272 } 4273 4274 if (process == FALSE) 4275 return line; 4276 4277 lead_len = get_leader_len(line, &comment_flags, FALSE, include_space); 4278 4279 if (lead_len == 0) 4280 return line; 4281 4282 /* Find: 4283 * - COM_END, 4284 * - colon, 4285 * whichever comes first. 4286 */ 4287 while (*comment_flags) 4288 { 4289 if (*comment_flags == COM_END 4290 || *comment_flags == ':') 4291 { 4292 break; 4293 } 4294 ++comment_flags; 4295 } 4296 4297 /* If we found a colon, it means that we are not processing a line 4298 * starting with a closing part of a three-part comment. That's good, 4299 * because we don't want to remove those as this would be annoying. 4300 */ 4301 if (*comment_flags == ':' || *comment_flags == NUL) 4302 line += lead_len; 4303 4304 return line; 4305 } 4306 #endif 4307 4308 /* 4309 * Join 'count' lines (minimal 2) at cursor position. 4310 * When "save_undo" is TRUE save lines for undo first. 4311 * Set "use_formatoptions" to FALSE when e.g. processing 4312 * backspace and comment leaders should not be removed. 4313 * 4314 * return FAIL for failure, OK otherwise 4315 */ 4316 int 4317 do_join(count, insert_space, save_undo, use_formatoptions) 4318 long count; 4319 int insert_space; 4320 int save_undo; 4321 int use_formatoptions UNUSED; 4322 { 4323 char_u *curr = NULL; 4324 char_u *curr_start = NULL; 4325 char_u *cend; 4326 char_u *newp; 4327 char_u *spaces; /* number of spaces inserted before a line */ 4328 int endcurr1 = NUL; 4329 int endcurr2 = NUL; 4330 int currsize = 0; /* size of the current line */ 4331 int sumsize = 0; /* size of the long new line */ 4332 linenr_T t; 4333 colnr_T col = 0; 4334 int ret = OK; 4335 #if defined(FEAT_COMMENTS) || defined(PROTO) 4336 int *comments = NULL; 4337 int remove_comments = (use_formatoptions == TRUE) 4338 && has_format_option(FO_REMOVE_COMS); 4339 int prev_was_comment; 4340 #endif 4341 4342 4343 if (save_undo && u_save((linenr_T)(curwin->w_cursor.lnum - 1), 4344 (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL) 4345 return FAIL; 4346 4347 /* Allocate an array to store the number of spaces inserted before each 4348 * line. We will use it to pre-compute the length of the new line and the 4349 * proper placement of each original line in the new one. */ 4350 spaces = lalloc_clear((long_u)count, TRUE); 4351 if (spaces == NULL) 4352 return FAIL; 4353 #if defined(FEAT_COMMENTS) || defined(PROTO) 4354 if (remove_comments) 4355 { 4356 comments = (int *)lalloc_clear((long_u)count * sizeof(int), TRUE); 4357 if (comments == NULL) 4358 { 4359 vim_free(spaces); 4360 return FAIL; 4361 } 4362 } 4363 #endif 4364 4365 /* 4366 * Don't move anything, just compute the final line length 4367 * and setup the array of space strings lengths 4368 */ 4369 for (t = 0; t < count; ++t) 4370 { 4371 curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t)); 4372 #if defined(FEAT_COMMENTS) || defined(PROTO) 4373 if (remove_comments) 4374 { 4375 /* We don't want to remove the comment leader if the 4376 * previous line is not a comment. */ 4377 if (t > 0 && prev_was_comment) 4378 { 4379 4380 char_u *new_curr = skip_comment(curr, TRUE, insert_space, 4381 &prev_was_comment); 4382 comments[t] = (int)(new_curr - curr); 4383 curr = new_curr; 4384 } 4385 else 4386 curr = skip_comment(curr, FALSE, insert_space, 4387 &prev_was_comment); 4388 } 4389 #endif 4390 4391 if (insert_space && t > 0) 4392 { 4393 curr = skipwhite(curr); 4394 if (*curr != ')' && currsize != 0 && endcurr1 != TAB 4395 #ifdef FEAT_MBYTE 4396 && (!has_format_option(FO_MBYTE_JOIN) 4397 || (mb_ptr2char(curr) < 0x100 && endcurr1 < 0x100)) 4398 && (!has_format_option(FO_MBYTE_JOIN2) 4399 || mb_ptr2char(curr) < 0x100 || endcurr1 < 0x100) 4400 #endif 4401 ) 4402 { 4403 /* don't add a space if the line is ending in a space */ 4404 if (endcurr1 == ' ') 4405 endcurr1 = endcurr2; 4406 else 4407 ++spaces[t]; 4408 /* extra space when 'joinspaces' set and line ends in '.' */ 4409 if ( p_js 4410 && (endcurr1 == '.' 4411 || (vim_strchr(p_cpo, CPO_JOINSP) == NULL 4412 && (endcurr1 == '?' || endcurr1 == '!')))) 4413 ++spaces[t]; 4414 } 4415 } 4416 currsize = (int)STRLEN(curr); 4417 sumsize += currsize + spaces[t]; 4418 endcurr1 = endcurr2 = NUL; 4419 if (insert_space && currsize > 0) 4420 { 4421 #ifdef FEAT_MBYTE 4422 if (has_mbyte) 4423 { 4424 cend = curr + currsize; 4425 mb_ptr_back(curr, cend); 4426 endcurr1 = (*mb_ptr2char)(cend); 4427 if (cend > curr) 4428 { 4429 mb_ptr_back(curr, cend); 4430 endcurr2 = (*mb_ptr2char)(cend); 4431 } 4432 } 4433 else 4434 #endif 4435 { 4436 endcurr1 = *(curr + currsize - 1); 4437 if (currsize > 1) 4438 endcurr2 = *(curr + currsize - 2); 4439 } 4440 } 4441 line_breakcheck(); 4442 if (got_int) 4443 { 4444 ret = FAIL; 4445 goto theend; 4446 } 4447 } 4448 4449 /* store the column position before last line */ 4450 col = sumsize - currsize - spaces[count - 1]; 4451 4452 /* allocate the space for the new line */ 4453 newp = alloc_check((unsigned)(sumsize + 1)); 4454 cend = newp + sumsize; 4455 *cend = 0; 4456 4457 /* 4458 * Move affected lines to the new long one. 4459 * 4460 * Move marks from each deleted line to the joined line, adjusting the 4461 * column. This is not Vi compatible, but Vi deletes the marks, thus that 4462 * should not really be a problem. 4463 */ 4464 for (t = count - 1; ; --t) 4465 { 4466 cend -= currsize; 4467 mch_memmove(cend, curr, (size_t)currsize); 4468 if (spaces[t] > 0) 4469 { 4470 cend -= spaces[t]; 4471 copy_spaces(cend, (size_t)(spaces[t])); 4472 } 4473 mark_col_adjust(curwin->w_cursor.lnum + t, (colnr_T)0, (linenr_T)-t, 4474 (long)(cend - newp + spaces[t] - (curr - curr_start))); 4475 if (t == 0) 4476 break; 4477 curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1)); 4478 #if defined(FEAT_COMMENTS) || defined(PROTO) 4479 if (remove_comments) 4480 curr += comments[t - 1]; 4481 #endif 4482 if (insert_space && t > 1) 4483 curr = skipwhite(curr); 4484 currsize = (int)STRLEN(curr); 4485 } 4486 ml_replace(curwin->w_cursor.lnum, newp, FALSE); 4487 4488 /* Only report the change in the first line here, del_lines() will report 4489 * the deleted line. */ 4490 changed_lines(curwin->w_cursor.lnum, currsize, 4491 curwin->w_cursor.lnum + 1, 0L); 4492 4493 /* 4494 * Delete following lines. To do this we move the cursor there 4495 * briefly, and then move it back. After del_lines() the cursor may 4496 * have moved up (last line deleted), so the current lnum is kept in t. 4497 */ 4498 t = curwin->w_cursor.lnum; 4499 ++curwin->w_cursor.lnum; 4500 del_lines(count - 1, FALSE); 4501 curwin->w_cursor.lnum = t; 4502 4503 /* 4504 * Set the cursor column: 4505 * Vi compatible: use the column of the first join 4506 * vim: use the column of the last join 4507 */ 4508 curwin->w_cursor.col = 4509 (vim_strchr(p_cpo, CPO_JOINCOL) != NULL ? currsize : col); 4510 check_cursor_col(); 4511 4512 #ifdef FEAT_VIRTUALEDIT 4513 curwin->w_cursor.coladd = 0; 4514 #endif 4515 curwin->w_set_curswant = TRUE; 4516 4517 theend: 4518 vim_free(spaces); 4519 #if defined(FEAT_COMMENTS) || defined(PROTO) 4520 if (remove_comments) 4521 vim_free(comments); 4522 #endif 4523 return ret; 4524 } 4525 4526 #ifdef FEAT_COMMENTS 4527 /* 4528 * Return TRUE if the two comment leaders given are the same. "lnum" is 4529 * the first line. White-space is ignored. Note that the whole of 4530 * 'leader1' must match 'leader2_len' characters from 'leader2' -- webb 4531 */ 4532 static int 4533 same_leader(lnum, leader1_len, leader1_flags, leader2_len, leader2_flags) 4534 linenr_T lnum; 4535 int leader1_len; 4536 char_u *leader1_flags; 4537 int leader2_len; 4538 char_u *leader2_flags; 4539 { 4540 int idx1 = 0, idx2 = 0; 4541 char_u *p; 4542 char_u *line1; 4543 char_u *line2; 4544 4545 if (leader1_len == 0) 4546 return (leader2_len == 0); 4547 4548 /* 4549 * If first leader has 'f' flag, the lines can be joined only if the 4550 * second line does not have a leader. 4551 * If first leader has 'e' flag, the lines can never be joined. 4552 * If fist leader has 's' flag, the lines can only be joined if there is 4553 * some text after it and the second line has the 'm' flag. 4554 */ 4555 if (leader1_flags != NULL) 4556 { 4557 for (p = leader1_flags; *p && *p != ':'; ++p) 4558 { 4559 if (*p == COM_FIRST) 4560 return (leader2_len == 0); 4561 if (*p == COM_END) 4562 return FALSE; 4563 if (*p == COM_START) 4564 { 4565 if (*(ml_get(lnum) + leader1_len) == NUL) 4566 return FALSE; 4567 if (leader2_flags == NULL || leader2_len == 0) 4568 return FALSE; 4569 for (p = leader2_flags; *p && *p != ':'; ++p) 4570 if (*p == COM_MIDDLE) 4571 return TRUE; 4572 return FALSE; 4573 } 4574 } 4575 } 4576 4577 /* 4578 * Get current line and next line, compare the leaders. 4579 * The first line has to be saved, only one line can be locked at a time. 4580 */ 4581 line1 = vim_strsave(ml_get(lnum)); 4582 if (line1 != NULL) 4583 { 4584 for (idx1 = 0; vim_iswhite(line1[idx1]); ++idx1) 4585 ; 4586 line2 = ml_get(lnum + 1); 4587 for (idx2 = 0; idx2 < leader2_len; ++idx2) 4588 { 4589 if (!vim_iswhite(line2[idx2])) 4590 { 4591 if (line1[idx1++] != line2[idx2]) 4592 break; 4593 } 4594 else 4595 while (vim_iswhite(line1[idx1])) 4596 ++idx1; 4597 } 4598 vim_free(line1); 4599 } 4600 return (idx2 == leader2_len && idx1 == leader1_len); 4601 } 4602 #endif 4603 4604 /* 4605 * Implementation of the format operator 'gq'. 4606 */ 4607 void 4608 op_format(oap, keep_cursor) 4609 oparg_T *oap; 4610 int keep_cursor; /* keep cursor on same text char */ 4611 { 4612 long old_line_count = curbuf->b_ml.ml_line_count; 4613 4614 /* Place the cursor where the "gq" or "gw" command was given, so that "u" 4615 * can put it back there. */ 4616 curwin->w_cursor = oap->cursor_start; 4617 4618 if (u_save((linenr_T)(oap->start.lnum - 1), 4619 (linenr_T)(oap->end.lnum + 1)) == FAIL) 4620 return; 4621 curwin->w_cursor = oap->start; 4622 4623 #ifdef FEAT_VISUAL 4624 if (oap->is_VIsual) 4625 /* When there is no change: need to remove the Visual selection */ 4626 redraw_curbuf_later(INVERTED); 4627 #endif 4628 4629 /* Set '[ mark at the start of the formatted area */ 4630 curbuf->b_op_start = oap->start; 4631 4632 /* For "gw" remember the cursor position and put it back below (adjusted 4633 * for joined and split lines). */ 4634 if (keep_cursor) 4635 saved_cursor = oap->cursor_start; 4636 4637 format_lines(oap->line_count, keep_cursor); 4638 4639 /* 4640 * Leave the cursor at the first non-blank of the last formatted line. 4641 * If the cursor was moved one line back (e.g. with "Q}") go to the next 4642 * line, so "." will do the next lines. 4643 */ 4644 if (oap->end_adjusted && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) 4645 ++curwin->w_cursor.lnum; 4646 beginline(BL_WHITE | BL_FIX); 4647 old_line_count = curbuf->b_ml.ml_line_count - old_line_count; 4648 msgmore(old_line_count); 4649 4650 /* put '] mark on the end of the formatted area */ 4651 curbuf->b_op_end = curwin->w_cursor; 4652 4653 if (keep_cursor) 4654 { 4655 curwin->w_cursor = saved_cursor; 4656 saved_cursor.lnum = 0; 4657 } 4658 4659 #ifdef FEAT_VISUAL 4660 if (oap->is_VIsual) 4661 { 4662 win_T *wp; 4663 4664 FOR_ALL_WINDOWS(wp) 4665 { 4666 if (wp->w_old_cursor_lnum != 0) 4667 { 4668 /* When lines have been inserted or deleted, adjust the end of 4669 * the Visual area to be redrawn. */ 4670 if (wp->w_old_cursor_lnum > wp->w_old_visual_lnum) 4671 wp->w_old_cursor_lnum += old_line_count; 4672 else 4673 wp->w_old_visual_lnum += old_line_count; 4674 } 4675 } 4676 } 4677 #endif 4678 } 4679 4680 #if defined(FEAT_EVAL) || defined(PROTO) 4681 /* 4682 * Implementation of the format operator 'gq' for when using 'formatexpr'. 4683 */ 4684 void 4685 op_formatexpr(oap) 4686 oparg_T *oap; 4687 { 4688 # ifdef FEAT_VISUAL 4689 if (oap->is_VIsual) 4690 /* When there is no change: need to remove the Visual selection */ 4691 redraw_curbuf_later(INVERTED); 4692 # endif 4693 4694 if (fex_format(oap->start.lnum, oap->line_count, NUL) != 0) 4695 /* As documented: when 'formatexpr' returns non-zero fall back to 4696 * internal formatting. */ 4697 op_format(oap, FALSE); 4698 } 4699 4700 int 4701 fex_format(lnum, count, c) 4702 linenr_T lnum; 4703 long count; 4704 int c; /* character to be inserted */ 4705 { 4706 int use_sandbox = was_set_insecurely((char_u *)"formatexpr", 4707 OPT_LOCAL); 4708 int r; 4709 4710 /* 4711 * Set v:lnum to the first line number and v:count to the number of lines. 4712 * Set v:char to the character to be inserted (can be NUL). 4713 */ 4714 set_vim_var_nr(VV_LNUM, lnum); 4715 set_vim_var_nr(VV_COUNT, count); 4716 set_vim_var_char(c); 4717 4718 /* 4719 * Evaluate the function. 4720 */ 4721 if (use_sandbox) 4722 ++sandbox; 4723 r = eval_to_number(curbuf->b_p_fex); 4724 if (use_sandbox) 4725 --sandbox; 4726 4727 set_vim_var_string(VV_CHAR, NULL, -1); 4728 4729 return r; 4730 } 4731 #endif 4732 4733 /* 4734 * Format "line_count" lines, starting at the cursor position. 4735 * When "line_count" is negative, format until the end of the paragraph. 4736 * Lines after the cursor line are saved for undo, caller must have saved the 4737 * first line. 4738 */ 4739 void 4740 format_lines(line_count, avoid_fex) 4741 linenr_T line_count; 4742 int avoid_fex; /* don't use 'formatexpr' */ 4743 { 4744 int max_len; 4745 int is_not_par; /* current line not part of parag. */ 4746 int next_is_not_par; /* next line not part of paragraph */ 4747 int is_end_par; /* at end of paragraph */ 4748 int prev_is_end_par = FALSE;/* prev. line not part of parag. */ 4749 int next_is_start_par = FALSE; 4750 #ifdef FEAT_COMMENTS 4751 int leader_len = 0; /* leader len of current line */ 4752 int next_leader_len; /* leader len of next line */ 4753 char_u *leader_flags = NULL; /* flags for leader of current line */ 4754 char_u *next_leader_flags; /* flags for leader of next line */ 4755 int do_comments; /* format comments */ 4756 int do_comments_list = 0; /* format comments with 'n' or '2' */ 4757 #endif 4758 int advance = TRUE; 4759 int second_indent = -1; /* indent for second line (comment 4760 * aware) */ 4761 int do_second_indent; 4762 int do_number_indent; 4763 int do_trail_white; 4764 int first_par_line = TRUE; 4765 int smd_save; 4766 long count; 4767 int need_set_indent = TRUE; /* set indent of next paragraph */ 4768 int force_format = FALSE; 4769 int old_State = State; 4770 4771 /* length of a line to force formatting: 3 * 'tw' */ 4772 max_len = comp_textwidth(TRUE) * 3; 4773 4774 /* check for 'q', '2' and '1' in 'formatoptions' */ 4775 #ifdef FEAT_COMMENTS 4776 do_comments = has_format_option(FO_Q_COMS); 4777 #endif 4778 do_second_indent = has_format_option(FO_Q_SECOND); 4779 do_number_indent = has_format_option(FO_Q_NUMBER); 4780 do_trail_white = has_format_option(FO_WHITE_PAR); 4781 4782 /* 4783 * Get info about the previous and current line. 4784 */ 4785 if (curwin->w_cursor.lnum > 1) 4786 is_not_par = fmt_check_par(curwin->w_cursor.lnum - 1 4787 #ifdef FEAT_COMMENTS 4788 , &leader_len, &leader_flags, do_comments 4789 #endif 4790 ); 4791 else 4792 is_not_par = TRUE; 4793 next_is_not_par = fmt_check_par(curwin->w_cursor.lnum 4794 #ifdef FEAT_COMMENTS 4795 , &next_leader_len, &next_leader_flags, do_comments 4796 #endif 4797 ); 4798 is_end_par = (is_not_par || next_is_not_par); 4799 if (!is_end_par && do_trail_white) 4800 is_end_par = !ends_in_white(curwin->w_cursor.lnum - 1); 4801 4802 curwin->w_cursor.lnum--; 4803 for (count = line_count; count != 0 && !got_int; --count) 4804 { 4805 /* 4806 * Advance to next paragraph. 4807 */ 4808 if (advance) 4809 { 4810 curwin->w_cursor.lnum++; 4811 prev_is_end_par = is_end_par; 4812 is_not_par = next_is_not_par; 4813 #ifdef FEAT_COMMENTS 4814 leader_len = next_leader_len; 4815 leader_flags = next_leader_flags; 4816 #endif 4817 } 4818 4819 /* 4820 * The last line to be formatted. 4821 */ 4822 if (count == 1 || curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count) 4823 { 4824 next_is_not_par = TRUE; 4825 #ifdef FEAT_COMMENTS 4826 next_leader_len = 0; 4827 next_leader_flags = NULL; 4828 #endif 4829 } 4830 else 4831 { 4832 next_is_not_par = fmt_check_par(curwin->w_cursor.lnum + 1 4833 #ifdef FEAT_COMMENTS 4834 , &next_leader_len, &next_leader_flags, do_comments 4835 #endif 4836 ); 4837 if (do_number_indent) 4838 next_is_start_par = 4839 (get_number_indent(curwin->w_cursor.lnum + 1) > 0); 4840 } 4841 advance = TRUE; 4842 is_end_par = (is_not_par || next_is_not_par || next_is_start_par); 4843 if (!is_end_par && do_trail_white) 4844 is_end_par = !ends_in_white(curwin->w_cursor.lnum); 4845 4846 /* 4847 * Skip lines that are not in a paragraph. 4848 */ 4849 if (is_not_par) 4850 { 4851 if (line_count < 0) 4852 break; 4853 } 4854 else 4855 { 4856 /* 4857 * For the first line of a paragraph, check indent of second line. 4858 * Don't do this for comments and empty lines. 4859 */ 4860 if (first_par_line 4861 && (do_second_indent || do_number_indent) 4862 && prev_is_end_par 4863 && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) 4864 { 4865 if (do_second_indent && !lineempty(curwin->w_cursor.lnum + 1)) 4866 { 4867 #ifdef FEAT_COMMENTS 4868 if (leader_len == 0 && next_leader_len == 0) 4869 { 4870 /* no comment found */ 4871 #endif 4872 second_indent = 4873 get_indent_lnum(curwin->w_cursor.lnum + 1); 4874 #ifdef FEAT_COMMENTS 4875 } 4876 else 4877 { 4878 second_indent = next_leader_len; 4879 do_comments_list = 1; 4880 } 4881 #endif 4882 } 4883 else if (do_number_indent) 4884 { 4885 #ifdef FEAT_COMMENTS 4886 if (leader_len == 0 && next_leader_len == 0) 4887 { 4888 /* no comment found */ 4889 #endif 4890 second_indent = 4891 get_number_indent(curwin->w_cursor.lnum); 4892 #ifdef FEAT_COMMENTS 4893 } 4894 else 4895 { 4896 /* get_number_indent() is now "comment aware"... */ 4897 second_indent = 4898 get_number_indent(curwin->w_cursor.lnum); 4899 do_comments_list = 1; 4900 } 4901 #endif 4902 } 4903 } 4904 4905 /* 4906 * When the comment leader changes, it's the end of the paragraph. 4907 */ 4908 if (curwin->w_cursor.lnum >= curbuf->b_ml.ml_line_count 4909 #ifdef FEAT_COMMENTS 4910 || !same_leader(curwin->w_cursor.lnum, 4911 leader_len, leader_flags, 4912 next_leader_len, next_leader_flags) 4913 #endif 4914 ) 4915 is_end_par = TRUE; 4916 4917 /* 4918 * If we have got to the end of a paragraph, or the line is 4919 * getting long, format it. 4920 */ 4921 if (is_end_par || force_format) 4922 { 4923 if (need_set_indent) 4924 /* replace indent in first line with minimal number of 4925 * tabs and spaces, according to current options */ 4926 (void)set_indent(get_indent(), SIN_CHANGED); 4927 4928 /* put cursor on last non-space */ 4929 State = NORMAL; /* don't go past end-of-line */ 4930 coladvance((colnr_T)MAXCOL); 4931 while (curwin->w_cursor.col && vim_isspace(gchar_cursor())) 4932 dec_cursor(); 4933 4934 /* do the formatting, without 'showmode' */ 4935 State = INSERT; /* for open_line() */ 4936 smd_save = p_smd; 4937 p_smd = FALSE; 4938 insertchar(NUL, INSCHAR_FORMAT 4939 #ifdef FEAT_COMMENTS 4940 + (do_comments ? INSCHAR_DO_COM : 0) 4941 + (do_comments && do_comments_list 4942 ? INSCHAR_COM_LIST : 0) 4943 #endif 4944 + (avoid_fex ? INSCHAR_NO_FEX : 0), second_indent); 4945 State = old_State; 4946 p_smd = smd_save; 4947 second_indent = -1; 4948 /* at end of par.: need to set indent of next par. */ 4949 need_set_indent = is_end_par; 4950 if (is_end_par) 4951 { 4952 /* When called with a negative line count, break at the 4953 * end of the paragraph. */ 4954 if (line_count < 0) 4955 break; 4956 first_par_line = TRUE; 4957 } 4958 force_format = FALSE; 4959 } 4960 4961 /* 4962 * When still in same paragraph, join the lines together. But 4963 * first delete the comment leader from the second line. 4964 */ 4965 if (!is_end_par) 4966 { 4967 advance = FALSE; 4968 curwin->w_cursor.lnum++; 4969 curwin->w_cursor.col = 0; 4970 if (line_count < 0 && u_save_cursor() == FAIL) 4971 break; 4972 #ifdef FEAT_COMMENTS 4973 (void)del_bytes((long)next_leader_len, FALSE, FALSE); 4974 if (next_leader_len > 0) 4975 mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L, 4976 (long)-next_leader_len); 4977 #endif 4978 curwin->w_cursor.lnum--; 4979 if (do_join(2, TRUE, FALSE, FALSE) == FAIL) 4980 { 4981 beep_flush(); 4982 break; 4983 } 4984 first_par_line = FALSE; 4985 /* If the line is getting long, format it next time */ 4986 if (STRLEN(ml_get_curline()) > (size_t)max_len) 4987 force_format = TRUE; 4988 else 4989 force_format = FALSE; 4990 } 4991 } 4992 line_breakcheck(); 4993 } 4994 } 4995 4996 /* 4997 * Return TRUE if line "lnum" ends in a white character. 4998 */ 4999 static int 5000 ends_in_white(lnum) 5001 linenr_T lnum; 5002 { 5003 char_u *s = ml_get(lnum); 5004 size_t l; 5005 5006 if (*s == NUL) 5007 return FALSE; 5008 /* Don't use STRLEN() inside vim_iswhite(), SAS/C complains: "macro 5009 * invocation may call function multiple times". */ 5010 l = STRLEN(s) - 1; 5011 return vim_iswhite(s[l]); 5012 } 5013 5014 /* 5015 * Blank lines, and lines containing only the comment leader, are left 5016 * untouched by the formatting. The function returns TRUE in this 5017 * case. It also returns TRUE when a line starts with the end of a comment 5018 * ('e' in comment flags), so that this line is skipped, and not joined to the 5019 * previous line. A new paragraph starts after a blank line, or when the 5020 * comment leader changes -- webb. 5021 */ 5022 #ifdef FEAT_COMMENTS 5023 static int 5024 fmt_check_par(lnum, leader_len, leader_flags, do_comments) 5025 linenr_T lnum; 5026 int *leader_len; 5027 char_u **leader_flags; 5028 int do_comments; 5029 { 5030 char_u *flags = NULL; /* init for GCC */ 5031 char_u *ptr; 5032 5033 ptr = ml_get(lnum); 5034 if (do_comments) 5035 *leader_len = get_leader_len(ptr, leader_flags, FALSE, TRUE); 5036 else 5037 *leader_len = 0; 5038 5039 if (*leader_len > 0) 5040 { 5041 /* 5042 * Search for 'e' flag in comment leader flags. 5043 */ 5044 flags = *leader_flags; 5045 while (*flags && *flags != ':' && *flags != COM_END) 5046 ++flags; 5047 } 5048 5049 return (*skipwhite(ptr + *leader_len) == NUL 5050 || (*leader_len > 0 && *flags == COM_END) 5051 || startPS(lnum, NUL, FALSE)); 5052 } 5053 #else 5054 static int 5055 fmt_check_par(lnum) 5056 linenr_T lnum; 5057 { 5058 return (*skipwhite(ml_get(lnum)) == NUL || startPS(lnum, NUL, FALSE)); 5059 } 5060 #endif 5061 5062 /* 5063 * Return TRUE when a paragraph starts in line "lnum". Return FALSE when the 5064 * previous line is in the same paragraph. Used for auto-formatting. 5065 */ 5066 int 5067 paragraph_start(lnum) 5068 linenr_T lnum; 5069 { 5070 char_u *p; 5071 #ifdef FEAT_COMMENTS 5072 int leader_len = 0; /* leader len of current line */ 5073 char_u *leader_flags = NULL; /* flags for leader of current line */ 5074 int next_leader_len; /* leader len of next line */ 5075 char_u *next_leader_flags; /* flags for leader of next line */ 5076 int do_comments; /* format comments */ 5077 #endif 5078 5079 if (lnum <= 1) 5080 return TRUE; /* start of the file */ 5081 5082 p = ml_get(lnum - 1); 5083 if (*p == NUL) 5084 return TRUE; /* after empty line */ 5085 5086 #ifdef FEAT_COMMENTS 5087 do_comments = has_format_option(FO_Q_COMS); 5088 #endif 5089 if (fmt_check_par(lnum - 1 5090 #ifdef FEAT_COMMENTS 5091 , &leader_len, &leader_flags, do_comments 5092 #endif 5093 )) 5094 return TRUE; /* after non-paragraph line */ 5095 5096 if (fmt_check_par(lnum 5097 #ifdef FEAT_COMMENTS 5098 , &next_leader_len, &next_leader_flags, do_comments 5099 #endif 5100 )) 5101 return TRUE; /* "lnum" is not a paragraph line */ 5102 5103 if (has_format_option(FO_WHITE_PAR) && !ends_in_white(lnum - 1)) 5104 return TRUE; /* missing trailing space in previous line. */ 5105 5106 if (has_format_option(FO_Q_NUMBER) && (get_number_indent(lnum) > 0)) 5107 return TRUE; /* numbered item starts in "lnum". */ 5108 5109 #ifdef FEAT_COMMENTS 5110 if (!same_leader(lnum - 1, leader_len, leader_flags, 5111 next_leader_len, next_leader_flags)) 5112 return TRUE; /* change of comment leader. */ 5113 #endif 5114 5115 return FALSE; 5116 } 5117 5118 #ifdef FEAT_VISUAL 5119 /* 5120 * prepare a few things for block mode yank/delete/tilde 5121 * 5122 * for delete: 5123 * - textlen includes the first/last char to be (partly) deleted 5124 * - start/endspaces is the number of columns that are taken by the 5125 * first/last deleted char minus the number of columns that have to be 5126 * deleted. 5127 * for yank and tilde: 5128 * - textlen includes the first/last char to be wholly yanked 5129 * - start/endspaces is the number of columns of the first/last yanked char 5130 * that are to be yanked. 5131 */ 5132 static void 5133 block_prep(oap, bdp, lnum, is_del) 5134 oparg_T *oap; 5135 struct block_def *bdp; 5136 linenr_T lnum; 5137 int is_del; 5138 { 5139 int incr = 0; 5140 char_u *pend; 5141 char_u *pstart; 5142 char_u *line; 5143 char_u *prev_pstart; 5144 char_u *prev_pend; 5145 5146 bdp->startspaces = 0; 5147 bdp->endspaces = 0; 5148 bdp->textlen = 0; 5149 bdp->start_vcol = 0; 5150 bdp->end_vcol = 0; 5151 #ifdef FEAT_VISUALEXTRA 5152 bdp->is_short = FALSE; 5153 bdp->is_oneChar = FALSE; 5154 bdp->pre_whitesp = 0; 5155 bdp->pre_whitesp_c = 0; 5156 bdp->end_char_vcols = 0; 5157 #endif 5158 bdp->start_char_vcols = 0; 5159 5160 line = ml_get(lnum); 5161 pstart = line; 5162 prev_pstart = line; 5163 while (bdp->start_vcol < oap->start_vcol && *pstart) 5164 { 5165 /* Count a tab for what it's worth (if list mode not on) */ 5166 incr = lbr_chartabsize(pstart, (colnr_T)bdp->start_vcol); 5167 bdp->start_vcol += incr; 5168 #ifdef FEAT_VISUALEXTRA 5169 if (vim_iswhite(*pstart)) 5170 { 5171 bdp->pre_whitesp += incr; 5172 bdp->pre_whitesp_c++; 5173 } 5174 else 5175 { 5176 bdp->pre_whitesp = 0; 5177 bdp->pre_whitesp_c = 0; 5178 } 5179 #endif 5180 prev_pstart = pstart; 5181 mb_ptr_adv(pstart); 5182 } 5183 bdp->start_char_vcols = incr; 5184 if (bdp->start_vcol < oap->start_vcol) /* line too short */ 5185 { 5186 bdp->end_vcol = bdp->start_vcol; 5187 #ifdef FEAT_VISUALEXTRA 5188 bdp->is_short = TRUE; 5189 #endif 5190 if (!is_del || oap->op_type == OP_APPEND) 5191 bdp->endspaces = oap->end_vcol - oap->start_vcol + 1; 5192 } 5193 else 5194 { 5195 /* notice: this converts partly selected Multibyte characters to 5196 * spaces, too. */ 5197 bdp->startspaces = bdp->start_vcol - oap->start_vcol; 5198 if (is_del && bdp->startspaces) 5199 bdp->startspaces = bdp->start_char_vcols - bdp->startspaces; 5200 pend = pstart; 5201 bdp->end_vcol = bdp->start_vcol; 5202 if (bdp->end_vcol > oap->end_vcol) /* it's all in one character */ 5203 { 5204 #ifdef FEAT_VISUALEXTRA 5205 bdp->is_oneChar = TRUE; 5206 #endif 5207 if (oap->op_type == OP_INSERT) 5208 bdp->endspaces = bdp->start_char_vcols - bdp->startspaces; 5209 else if (oap->op_type == OP_APPEND) 5210 { 5211 bdp->startspaces += oap->end_vcol - oap->start_vcol + 1; 5212 bdp->endspaces = bdp->start_char_vcols - bdp->startspaces; 5213 } 5214 else 5215 { 5216 bdp->startspaces = oap->end_vcol - oap->start_vcol + 1; 5217 if (is_del && oap->op_type != OP_LSHIFT) 5218 { 5219 /* just putting the sum of those two into 5220 * bdp->startspaces doesn't work for Visual replace, 5221 * so we have to split the tab in two */ 5222 bdp->startspaces = bdp->start_char_vcols 5223 - (bdp->start_vcol - oap->start_vcol); 5224 bdp->endspaces = bdp->end_vcol - oap->end_vcol - 1; 5225 } 5226 } 5227 } 5228 else 5229 { 5230 prev_pend = pend; 5231 while (bdp->end_vcol <= oap->end_vcol && *pend != NUL) 5232 { 5233 /* Count a tab for what it's worth (if list mode not on) */ 5234 prev_pend = pend; 5235 incr = lbr_chartabsize_adv(&pend, (colnr_T)bdp->end_vcol); 5236 bdp->end_vcol += incr; 5237 } 5238 if (bdp->end_vcol <= oap->end_vcol 5239 && (!is_del 5240 || oap->op_type == OP_APPEND 5241 || oap->op_type == OP_REPLACE)) /* line too short */ 5242 { 5243 #ifdef FEAT_VISUALEXTRA 5244 bdp->is_short = TRUE; 5245 #endif 5246 /* Alternative: include spaces to fill up the block. 5247 * Disadvantage: can lead to trailing spaces when the line is 5248 * short where the text is put */ 5249 /* if (!is_del || oap->op_type == OP_APPEND) */ 5250 if (oap->op_type == OP_APPEND || virtual_op) 5251 bdp->endspaces = oap->end_vcol - bdp->end_vcol 5252 + oap->inclusive; 5253 else 5254 bdp->endspaces = 0; /* replace doesn't add characters */ 5255 } 5256 else if (bdp->end_vcol > oap->end_vcol) 5257 { 5258 bdp->endspaces = bdp->end_vcol - oap->end_vcol - 1; 5259 if (!is_del && bdp->endspaces) 5260 { 5261 bdp->endspaces = incr - bdp->endspaces; 5262 if (pend != pstart) 5263 pend = prev_pend; 5264 } 5265 } 5266 } 5267 #ifdef FEAT_VISUALEXTRA 5268 bdp->end_char_vcols = incr; 5269 #endif 5270 if (is_del && bdp->startspaces) 5271 pstart = prev_pstart; 5272 bdp->textlen = (int)(pend - pstart); 5273 } 5274 bdp->textcol = (colnr_T) (pstart - line); 5275 bdp->textstart = pstart; 5276 } 5277 #endif /* FEAT_VISUAL */ 5278 5279 #ifdef FEAT_RIGHTLEFT 5280 static void reverse_line __ARGS((char_u *s)); 5281 5282 static void 5283 reverse_line(s) 5284 char_u *s; 5285 { 5286 int i, j; 5287 char_u c; 5288 5289 if ((i = (int)STRLEN(s) - 1) <= 0) 5290 return; 5291 5292 curwin->w_cursor.col = i - curwin->w_cursor.col; 5293 for (j = 0; j < i; j++, i--) 5294 { 5295 c = s[i]; s[i] = s[j]; s[j] = c; 5296 } 5297 } 5298 5299 # define RLADDSUBFIX(ptr) if (curwin->w_p_rl) reverse_line(ptr); 5300 #else 5301 # define RLADDSUBFIX(ptr) 5302 #endif 5303 5304 /* 5305 * add or subtract 'Prenum1' from a number in a line 5306 * 'command' is CTRL-A for add, CTRL-X for subtract 5307 * 5308 * return FAIL for failure, OK otherwise 5309 */ 5310 int 5311 do_addsub(command, Prenum1) 5312 int command; 5313 linenr_T Prenum1; 5314 { 5315 int col; 5316 char_u *buf1; 5317 char_u buf2[NUMBUFLEN]; 5318 int hex; /* 'X' or 'x': hex; '0': octal */ 5319 static int hexupper = FALSE; /* 0xABC */ 5320 unsigned long n; 5321 long_u oldn; 5322 char_u *ptr; 5323 int c; 5324 int length = 0; /* character length of the number */ 5325 int todel; 5326 int dohex; 5327 int dooct; 5328 int doalp; 5329 int firstdigit; 5330 int negative; 5331 int subtract; 5332 5333 dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL); /* "heX" */ 5334 dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL); /* "Octal" */ 5335 doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL); /* "alPha" */ 5336 5337 ptr = ml_get_curline(); 5338 RLADDSUBFIX(ptr); 5339 5340 /* 5341 * First check if we are on a hexadecimal number, after the "0x". 5342 */ 5343 col = curwin->w_cursor.col; 5344 if (dohex) 5345 while (col > 0 && vim_isxdigit(ptr[col])) 5346 --col; 5347 if ( dohex 5348 && col > 0 5349 && (ptr[col] == 'X' 5350 || ptr[col] == 'x') 5351 && ptr[col - 1] == '0' 5352 && vim_isxdigit(ptr[col + 1])) 5353 { 5354 /* 5355 * Found hexadecimal number, move to its start. 5356 */ 5357 --col; 5358 } 5359 else 5360 { 5361 /* 5362 * Search forward and then backward to find the start of number. 5363 */ 5364 col = curwin->w_cursor.col; 5365 5366 while (ptr[col] != NUL 5367 && !vim_isdigit(ptr[col]) 5368 && !(doalp && ASCII_ISALPHA(ptr[col]))) 5369 ++col; 5370 5371 while (col > 0 5372 && vim_isdigit(ptr[col - 1]) 5373 && !(doalp && ASCII_ISALPHA(ptr[col]))) 5374 --col; 5375 } 5376 5377 /* 5378 * If a number was found, and saving for undo works, replace the number. 5379 */ 5380 firstdigit = ptr[col]; 5381 RLADDSUBFIX(ptr); 5382 if ((!VIM_ISDIGIT(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit))) 5383 || u_save_cursor() != OK) 5384 { 5385 beep_flush(); 5386 return FAIL; 5387 } 5388 5389 /* get ptr again, because u_save() may have changed it */ 5390 ptr = ml_get_curline(); 5391 RLADDSUBFIX(ptr); 5392 5393 if (doalp && ASCII_ISALPHA(firstdigit)) 5394 { 5395 /* decrement or increment alphabetic character */ 5396 if (command == Ctrl_X) 5397 { 5398 if (CharOrd(firstdigit) < Prenum1) 5399 { 5400 if (isupper(firstdigit)) 5401 firstdigit = 'A'; 5402 else 5403 firstdigit = 'a'; 5404 } 5405 else 5406 #ifdef EBCDIC 5407 firstdigit = EBCDIC_CHAR_ADD(firstdigit, -Prenum1); 5408 #else 5409 firstdigit -= Prenum1; 5410 #endif 5411 } 5412 else 5413 { 5414 if (26 - CharOrd(firstdigit) - 1 < Prenum1) 5415 { 5416 if (isupper(firstdigit)) 5417 firstdigit = 'Z'; 5418 else 5419 firstdigit = 'z'; 5420 } 5421 else 5422 #ifdef EBCDIC 5423 firstdigit = EBCDIC_CHAR_ADD(firstdigit, Prenum1); 5424 #else 5425 firstdigit += Prenum1; 5426 #endif 5427 } 5428 curwin->w_cursor.col = col; 5429 (void)del_char(FALSE); 5430 ins_char(firstdigit); 5431 } 5432 else 5433 { 5434 negative = FALSE; 5435 if (col > 0 && ptr[col - 1] == '-') /* negative number */ 5436 { 5437 --col; 5438 negative = TRUE; 5439 } 5440 5441 /* get the number value (unsigned) */ 5442 vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n); 5443 5444 /* ignore leading '-' for hex and octal numbers */ 5445 if (hex && negative) 5446 { 5447 ++col; 5448 --length; 5449 negative = FALSE; 5450 } 5451 5452 /* add or subtract */ 5453 subtract = FALSE; 5454 if (command == Ctrl_X) 5455 subtract ^= TRUE; 5456 if (negative) 5457 subtract ^= TRUE; 5458 5459 oldn = n; 5460 if (subtract) 5461 n -= (unsigned long)Prenum1; 5462 else 5463 n += (unsigned long)Prenum1; 5464 5465 /* handle wraparound for decimal numbers */ 5466 if (!hex) 5467 { 5468 if (subtract) 5469 { 5470 if (n > oldn) 5471 { 5472 n = 1 + (n ^ (unsigned long)-1); 5473 negative ^= TRUE; 5474 } 5475 } 5476 else /* add */ 5477 { 5478 if (n < oldn) 5479 { 5480 n = (n ^ (unsigned long)-1); 5481 negative ^= TRUE; 5482 } 5483 } 5484 if (n == 0) 5485 negative = FALSE; 5486 } 5487 5488 /* 5489 * Delete the old number. 5490 */ 5491 curwin->w_cursor.col = col; 5492 todel = length; 5493 c = gchar_cursor(); 5494 /* 5495 * Don't include the '-' in the length, only the length of the part 5496 * after it is kept the same. 5497 */ 5498 if (c == '-') 5499 --length; 5500 while (todel-- > 0) 5501 { 5502 if (c < 0x100 && isalpha(c)) 5503 { 5504 if (isupper(c)) 5505 hexupper = TRUE; 5506 else 5507 hexupper = FALSE; 5508 } 5509 /* del_char() will mark line needing displaying */ 5510 (void)del_char(FALSE); 5511 c = gchar_cursor(); 5512 } 5513 5514 /* 5515 * Prepare the leading characters in buf1[]. 5516 * When there are many leading zeros it could be very long. Allocate 5517 * a bit too much. 5518 */ 5519 buf1 = alloc((unsigned)length + NUMBUFLEN); 5520 if (buf1 == NULL) 5521 return FAIL; 5522 ptr = buf1; 5523 if (negative) 5524 { 5525 *ptr++ = '-'; 5526 } 5527 if (hex) 5528 { 5529 *ptr++ = '0'; 5530 --length; 5531 } 5532 if (hex == 'x' || hex == 'X') 5533 { 5534 *ptr++ = hex; 5535 --length; 5536 } 5537 5538 /* 5539 * Put the number characters in buf2[]. 5540 */ 5541 if (hex == 0) 5542 sprintf((char *)buf2, "%lu", n); 5543 else if (hex == '0') 5544 sprintf((char *)buf2, "%lo", n); 5545 else if (hex && hexupper) 5546 sprintf((char *)buf2, "%lX", n); 5547 else 5548 sprintf((char *)buf2, "%lx", n); 5549 length -= (int)STRLEN(buf2); 5550 5551 /* 5552 * Adjust number of zeros to the new number of digits, so the 5553 * total length of the number remains the same. 5554 * Don't do this when 5555 * the result may look like an octal number. 5556 */ 5557 if (firstdigit == '0' && !(dooct && hex == 0)) 5558 while (length-- > 0) 5559 *ptr++ = '0'; 5560 *ptr = NUL; 5561 STRCAT(buf1, buf2); 5562 ins_str(buf1); /* insert the new number */ 5563 vim_free(buf1); 5564 } 5565 --curwin->w_cursor.col; 5566 curwin->w_set_curswant = TRUE; 5567 #ifdef FEAT_RIGHTLEFT 5568 ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE); 5569 RLADDSUBFIX(ptr); 5570 #endif 5571 return OK; 5572 } 5573 5574 #ifdef FEAT_VIMINFO 5575 int 5576 read_viminfo_register(virp, force) 5577 vir_T *virp; 5578 int force; 5579 { 5580 int eof; 5581 int do_it = TRUE; 5582 int size; 5583 int limit; 5584 int i; 5585 int set_prev = FALSE; 5586 char_u *str; 5587 char_u **array = NULL; 5588 5589 /* We only get here (hopefully) if line[0] == '"' */ 5590 str = virp->vir_line + 1; 5591 5592 /* If the line starts with "" this is the y_previous register. */ 5593 if (*str == '"') 5594 { 5595 set_prev = TRUE; 5596 str++; 5597 } 5598 5599 if (!ASCII_ISALNUM(*str) && *str != '-') 5600 { 5601 if (viminfo_error("E577: ", _("Illegal register name"), virp->vir_line)) 5602 return TRUE; /* too many errors, pretend end-of-file */ 5603 do_it = FALSE; 5604 } 5605 get_yank_register(*str++, FALSE); 5606 if (!force && y_current->y_array != NULL) 5607 do_it = FALSE; 5608 5609 if (*str == '@') 5610 { 5611 /* "x@: register x used for @@ */ 5612 if (force || execreg_lastc == NUL) 5613 execreg_lastc = str[-1]; 5614 } 5615 5616 size = 0; 5617 limit = 100; /* Optimized for registers containing <= 100 lines */ 5618 if (do_it) 5619 { 5620 if (set_prev) 5621 y_previous = y_current; 5622 vim_free(y_current->y_array); 5623 array = y_current->y_array = 5624 (char_u **)alloc((unsigned)(limit * sizeof(char_u *))); 5625 str = skipwhite(skiptowhite(str)); 5626 if (STRNCMP(str, "CHAR", 4) == 0) 5627 y_current->y_type = MCHAR; 5628 #ifdef FEAT_VISUAL 5629 else if (STRNCMP(str, "BLOCK", 5) == 0) 5630 y_current->y_type = MBLOCK; 5631 #endif 5632 else 5633 y_current->y_type = MLINE; 5634 /* get the block width; if it's missing we get a zero, which is OK */ 5635 str = skipwhite(skiptowhite(str)); 5636 #ifdef FEAT_VISUAL 5637 y_current->y_width = getdigits(&str); 5638 #else 5639 (void)getdigits(&str); 5640 #endif 5641 } 5642 5643 while (!(eof = viminfo_readline(virp)) 5644 && (virp->vir_line[0] == TAB || virp->vir_line[0] == '<')) 5645 { 5646 if (do_it) 5647 { 5648 if (size >= limit) 5649 { 5650 y_current->y_array = (char_u **) 5651 alloc((unsigned)(limit * 2 * sizeof(char_u *))); 5652 for (i = 0; i < limit; i++) 5653 y_current->y_array[i] = array[i]; 5654 vim_free(array); 5655 limit *= 2; 5656 array = y_current->y_array; 5657 } 5658 str = viminfo_readstring(virp, 1, TRUE); 5659 if (str != NULL) 5660 array[size++] = str; 5661 else 5662 do_it = FALSE; 5663 } 5664 } 5665 if (do_it) 5666 { 5667 if (size == 0) 5668 { 5669 vim_free(array); 5670 y_current->y_array = NULL; 5671 } 5672 else if (size < limit) 5673 { 5674 y_current->y_array = 5675 (char_u **)alloc((unsigned)(size * sizeof(char_u *))); 5676 for (i = 0; i < size; i++) 5677 y_current->y_array[i] = array[i]; 5678 vim_free(array); 5679 } 5680 y_current->y_size = size; 5681 } 5682 return eof; 5683 } 5684 5685 void 5686 write_viminfo_registers(fp) 5687 FILE *fp; 5688 { 5689 int i, j; 5690 char_u *type; 5691 char_u c; 5692 int num_lines; 5693 int max_num_lines; 5694 int max_kbyte; 5695 long len; 5696 5697 fputs(_("\n# Registers:\n"), fp); 5698 5699 /* Get '<' value, use old '"' value if '<' is not found. */ 5700 max_num_lines = get_viminfo_parameter('<'); 5701 if (max_num_lines < 0) 5702 max_num_lines = get_viminfo_parameter('"'); 5703 if (max_num_lines == 0) 5704 return; 5705 max_kbyte = get_viminfo_parameter('s'); 5706 if (max_kbyte == 0) 5707 return; 5708 5709 for (i = 0; i < NUM_REGISTERS; i++) 5710 { 5711 if (y_regs[i].y_array == NULL) 5712 continue; 5713 #ifdef FEAT_CLIPBOARD 5714 /* Skip '*'/'+' register, we don't want them back next time */ 5715 if (i == STAR_REGISTER || i == PLUS_REGISTER) 5716 continue; 5717 #endif 5718 #ifdef FEAT_DND 5719 /* Neither do we want the '~' register */ 5720 if (i == TILDE_REGISTER) 5721 continue; 5722 #endif 5723 /* Skip empty registers. */ 5724 num_lines = y_regs[i].y_size; 5725 if (num_lines == 0 5726 || (num_lines == 1 && y_regs[i].y_type == MCHAR 5727 && *y_regs[i].y_array[0] == NUL)) 5728 continue; 5729 5730 if (max_kbyte > 0) 5731 { 5732 /* Skip register if there is more text than the maximum size. */ 5733 len = 0; 5734 for (j = 0; j < num_lines; j++) 5735 len += (long)STRLEN(y_regs[i].y_array[j]) + 1L; 5736 if (len > (long)max_kbyte * 1024L) 5737 continue; 5738 } 5739 5740 switch (y_regs[i].y_type) 5741 { 5742 case MLINE: 5743 type = (char_u *)"LINE"; 5744 break; 5745 case MCHAR: 5746 type = (char_u *)"CHAR"; 5747 break; 5748 #ifdef FEAT_VISUAL 5749 case MBLOCK: 5750 type = (char_u *)"BLOCK"; 5751 break; 5752 #endif 5753 default: 5754 sprintf((char *)IObuff, _("E574: Unknown register type %d"), 5755 y_regs[i].y_type); 5756 emsg(IObuff); 5757 type = (char_u *)"LINE"; 5758 break; 5759 } 5760 if (y_previous == &y_regs[i]) 5761 fprintf(fp, "\""); 5762 c = get_register_name(i); 5763 fprintf(fp, "\"%c", c); 5764 if (c == execreg_lastc) 5765 fprintf(fp, "@"); 5766 fprintf(fp, "\t%s\t%d\n", type, 5767 #ifdef FEAT_VISUAL 5768 (int)y_regs[i].y_width 5769 #else 5770 0 5771 #endif 5772 ); 5773 5774 /* If max_num_lines < 0, then we save ALL the lines in the register */ 5775 if (max_num_lines > 0 && num_lines > max_num_lines) 5776 num_lines = max_num_lines; 5777 for (j = 0; j < num_lines; j++) 5778 { 5779 putc('\t', fp); 5780 viminfo_writestring(fp, y_regs[i].y_array[j]); 5781 } 5782 } 5783 } 5784 #endif /* FEAT_VIMINFO */ 5785 5786 #if defined(FEAT_CLIPBOARD) || defined(PROTO) 5787 /* 5788 * SELECTION / PRIMARY ('*') 5789 * 5790 * Text selection stuff that uses the GUI selection register '*'. When using a 5791 * GUI this may be text from another window, otherwise it is the last text we 5792 * had highlighted with VIsual mode. With mouse support, clicking the middle 5793 * button performs the paste, otherwise you will need to do <"*p>. " 5794 * If not under X, it is synonymous with the clipboard register '+'. 5795 * 5796 * X CLIPBOARD ('+') 5797 * 5798 * Text selection stuff that uses the GUI clipboard register '+'. 5799 * Under X, this matches the standard cut/paste buffer CLIPBOARD selection. 5800 * It will be used for unnamed cut/pasting is 'clipboard' contains "unnamed", 5801 * otherwise you will need to do <"+p>. " 5802 * If not under X, it is synonymous with the selection register '*'. 5803 */ 5804 5805 /* 5806 * Routine to export any final X selection we had to the environment 5807 * so that the text is still available after vim has exited. X selections 5808 * only exist while the owning application exists, so we write to the 5809 * permanent (while X runs) store CUT_BUFFER0. 5810 * Dump the CLIPBOARD selection if we own it (it's logically the more 5811 * 'permanent' of the two), otherwise the PRIMARY one. 5812 * For now, use a hard-coded sanity limit of 1Mb of data. 5813 */ 5814 #if defined(FEAT_X11) && defined(FEAT_CLIPBOARD) 5815 void 5816 x11_export_final_selection() 5817 { 5818 Display *dpy; 5819 char_u *str = NULL; 5820 long_u len = 0; 5821 int motion_type = -1; 5822 5823 # ifdef FEAT_GUI 5824 if (gui.in_use) 5825 dpy = X_DISPLAY; 5826 else 5827 # endif 5828 # ifdef FEAT_XCLIPBOARD 5829 dpy = xterm_dpy; 5830 # else 5831 return; 5832 # endif 5833 5834 /* Get selection to export */ 5835 if (clip_plus.owned) 5836 motion_type = clip_convert_selection(&str, &len, &clip_plus); 5837 else if (clip_star.owned) 5838 motion_type = clip_convert_selection(&str, &len, &clip_star); 5839 5840 /* Check it's OK */ 5841 if (dpy != NULL && str != NULL && motion_type >= 0 5842 && len < 1024*1024 && len > 0) 5843 { 5844 #ifdef FEAT_MBYTE 5845 int ok = TRUE; 5846 5847 /* The CUT_BUFFER0 is supposed to always contain latin1. Convert from 5848 * 'enc' when it is a multi-byte encoding. When 'enc' is an 8-bit 5849 * encoding conversion usually doesn't work, so keep the text as-is. 5850 */ 5851 if (has_mbyte) 5852 { 5853 vimconv_T vc; 5854 5855 vc.vc_type = CONV_NONE; 5856 if (convert_setup(&vc, p_enc, (char_u *)"latin1") == OK) 5857 { 5858 int intlen = len; 5859 char_u *conv_str; 5860 5861 vc.vc_fail = TRUE; 5862 conv_str = string_convert(&vc, str, &intlen); 5863 len = intlen; 5864 if (conv_str != NULL) 5865 { 5866 vim_free(str); 5867 str = conv_str; 5868 } 5869 else 5870 { 5871 ok = FALSE; 5872 } 5873 convert_setup(&vc, NULL, NULL); 5874 } 5875 else 5876 { 5877 ok = FALSE; 5878 } 5879 } 5880 5881 /* Do not store the string if conversion failed. Better to use any 5882 * other selection than garbled text. */ 5883 if (ok) 5884 #endif 5885 { 5886 XStoreBuffer(dpy, (char *)str, (int)len, 0); 5887 XFlush(dpy); 5888 } 5889 } 5890 5891 vim_free(str); 5892 } 5893 #endif 5894 5895 void 5896 clip_free_selection(cbd) 5897 VimClipboard *cbd; 5898 { 5899 struct yankreg *y_ptr = y_current; 5900 5901 if (cbd == &clip_plus) 5902 y_current = &y_regs[PLUS_REGISTER]; 5903 else 5904 y_current = &y_regs[STAR_REGISTER]; 5905 free_yank_all(); 5906 y_current->y_size = 0; 5907 y_current = y_ptr; 5908 } 5909 5910 /* 5911 * Get the selected text and put it in the gui selection register '*' or '+'. 5912 */ 5913 void 5914 clip_get_selection(cbd) 5915 VimClipboard *cbd; 5916 { 5917 struct yankreg *old_y_previous, *old_y_current; 5918 pos_T old_cursor; 5919 #ifdef FEAT_VISUAL 5920 pos_T old_visual; 5921 int old_visual_mode; 5922 #endif 5923 colnr_T old_curswant; 5924 int old_set_curswant; 5925 pos_T old_op_start, old_op_end; 5926 oparg_T oa; 5927 cmdarg_T ca; 5928 5929 if (cbd->owned) 5930 { 5931 if ((cbd == &clip_plus && y_regs[PLUS_REGISTER].y_array != NULL) 5932 || (cbd == &clip_star && y_regs[STAR_REGISTER].y_array != NULL)) 5933 return; 5934 5935 /* Get the text between clip_star.start & clip_star.end */ 5936 old_y_previous = y_previous; 5937 old_y_current = y_current; 5938 old_cursor = curwin->w_cursor; 5939 old_curswant = curwin->w_curswant; 5940 old_set_curswant = curwin->w_set_curswant; 5941 old_op_start = curbuf->b_op_start; 5942 old_op_end = curbuf->b_op_end; 5943 #ifdef FEAT_VISUAL 5944 old_visual = VIsual; 5945 old_visual_mode = VIsual_mode; 5946 #endif 5947 clear_oparg(&oa); 5948 oa.regname = (cbd == &clip_plus ? '+' : '*'); 5949 oa.op_type = OP_YANK; 5950 vim_memset(&ca, 0, sizeof(ca)); 5951 ca.oap = &oa; 5952 ca.cmdchar = 'y'; 5953 ca.count1 = 1; 5954 ca.retval = CA_NO_ADJ_OP_END; 5955 do_pending_operator(&ca, 0, TRUE); 5956 y_previous = old_y_previous; 5957 y_current = old_y_current; 5958 curwin->w_cursor = old_cursor; 5959 changed_cline_bef_curs(); /* need to update w_virtcol et al */ 5960 curwin->w_curswant = old_curswant; 5961 curwin->w_set_curswant = old_set_curswant; 5962 curbuf->b_op_start = old_op_start; 5963 curbuf->b_op_end = old_op_end; 5964 #ifdef FEAT_VISUAL 5965 VIsual = old_visual; 5966 VIsual_mode = old_visual_mode; 5967 #endif 5968 } 5969 else 5970 { 5971 clip_free_selection(cbd); 5972 5973 /* Try to get selected text from another window */ 5974 clip_gen_request_selection(cbd); 5975 } 5976 } 5977 5978 /* 5979 * Convert from the GUI selection string into the '*'/'+' register. 5980 */ 5981 void 5982 clip_yank_selection(type, str, len, cbd) 5983 int type; 5984 char_u *str; 5985 long len; 5986 VimClipboard *cbd; 5987 { 5988 struct yankreg *y_ptr; 5989 5990 if (cbd == &clip_plus) 5991 y_ptr = &y_regs[PLUS_REGISTER]; 5992 else 5993 y_ptr = &y_regs[STAR_REGISTER]; 5994 5995 clip_free_selection(cbd); 5996 5997 str_to_reg(y_ptr, type, str, len, 0L); 5998 } 5999 6000 /* 6001 * Convert the '*'/'+' register into a GUI selection string returned in *str 6002 * with length *len. 6003 * Returns the motion type, or -1 for failure. 6004 */ 6005 int 6006 clip_convert_selection(str, len, cbd) 6007 char_u **str; 6008 long_u *len; 6009 VimClipboard *cbd; 6010 { 6011 char_u *p; 6012 int lnum; 6013 int i, j; 6014 int_u eolsize; 6015 struct yankreg *y_ptr; 6016 6017 if (cbd == &clip_plus) 6018 y_ptr = &y_regs[PLUS_REGISTER]; 6019 else 6020 y_ptr = &y_regs[STAR_REGISTER]; 6021 6022 #ifdef USE_CRNL 6023 eolsize = 2; 6024 #else 6025 eolsize = 1; 6026 #endif 6027 6028 *str = NULL; 6029 *len = 0; 6030 if (y_ptr->y_array == NULL) 6031 return -1; 6032 6033 for (i = 0; i < y_ptr->y_size; i++) 6034 *len += (long_u)STRLEN(y_ptr->y_array[i]) + eolsize; 6035 6036 /* 6037 * Don't want newline character at end of last line if we're in MCHAR mode. 6038 */ 6039 if (y_ptr->y_type == MCHAR && *len >= eolsize) 6040 *len -= eolsize; 6041 6042 p = *str = lalloc(*len + 1, TRUE); /* add one to avoid zero */ 6043 if (p == NULL) 6044 return -1; 6045 lnum = 0; 6046 for (i = 0, j = 0; i < (int)*len; i++, j++) 6047 { 6048 if (y_ptr->y_array[lnum][j] == '\n') 6049 p[i] = NUL; 6050 else if (y_ptr->y_array[lnum][j] == NUL) 6051 { 6052 #ifdef USE_CRNL 6053 p[i++] = '\r'; 6054 #endif 6055 #ifdef USE_CR 6056 p[i] = '\r'; 6057 #else 6058 p[i] = '\n'; 6059 #endif 6060 lnum++; 6061 j = -1; 6062 } 6063 else 6064 p[i] = y_ptr->y_array[lnum][j]; 6065 } 6066 return y_ptr->y_type; 6067 } 6068 6069 6070 # if defined(FEAT_VISUAL) || defined(FEAT_EVAL) 6071 /* 6072 * If we have written to a clipboard register, send the text to the clipboard. 6073 */ 6074 static void 6075 may_set_selection() 6076 { 6077 if (y_current == &(y_regs[STAR_REGISTER]) && clip_star.available) 6078 { 6079 clip_own_selection(&clip_star); 6080 clip_gen_set_selection(&clip_star); 6081 } 6082 else if (y_current == &(y_regs[PLUS_REGISTER]) && clip_plus.available) 6083 { 6084 clip_own_selection(&clip_plus); 6085 clip_gen_set_selection(&clip_plus); 6086 } 6087 } 6088 # endif 6089 6090 #endif /* FEAT_CLIPBOARD || PROTO */ 6091 6092 6093 #if defined(FEAT_DND) || defined(PROTO) 6094 /* 6095 * Replace the contents of the '~' register with str. 6096 */ 6097 void 6098 dnd_yank_drag_data(str, len) 6099 char_u *str; 6100 long len; 6101 { 6102 struct yankreg *curr; 6103 6104 curr = y_current; 6105 y_current = &y_regs[TILDE_REGISTER]; 6106 free_yank_all(); 6107 str_to_reg(y_current, MCHAR, str, len, 0L); 6108 y_current = curr; 6109 } 6110 #endif 6111 6112 6113 #if defined(FEAT_EVAL) || defined(PROTO) 6114 /* 6115 * Return the type of a register. 6116 * Used for getregtype() 6117 * Returns MAUTO for error. 6118 */ 6119 char_u 6120 get_reg_type(regname, reglen) 6121 int regname; 6122 long *reglen; 6123 { 6124 switch (regname) 6125 { 6126 case '%': /* file name */ 6127 case '#': /* alternate file name */ 6128 case '=': /* expression */ 6129 case ':': /* last command line */ 6130 case '/': /* last search-pattern */ 6131 case '.': /* last inserted text */ 6132 #ifdef FEAT_SEARCHPATH 6133 case Ctrl_F: /* Filename under cursor */ 6134 case Ctrl_P: /* Path under cursor, expand via "path" */ 6135 #endif 6136 case Ctrl_W: /* word under cursor */ 6137 case Ctrl_A: /* WORD (mnemonic All) under cursor */ 6138 case '_': /* black hole: always empty */ 6139 return MCHAR; 6140 } 6141 6142 #ifdef FEAT_CLIPBOARD 6143 regname = may_get_selection(regname); 6144 #endif 6145 6146 /* Should we check for a valid name? */ 6147 get_yank_register(regname, FALSE); 6148 6149 if (y_current->y_array != NULL) 6150 { 6151 #ifdef FEAT_VISUAL 6152 if (reglen != NULL && y_current->y_type == MBLOCK) 6153 *reglen = y_current->y_width; 6154 #endif 6155 return y_current->y_type; 6156 } 6157 return MAUTO; 6158 } 6159 6160 /* 6161 * Return the contents of a register as a single allocated string. 6162 * Used for "@r" in expressions and for getreg(). 6163 * Returns NULL for error. 6164 */ 6165 char_u * 6166 get_reg_contents(regname, allowexpr, expr_src) 6167 int regname; 6168 int allowexpr; /* allow "=" register */ 6169 int expr_src; /* get expression for "=" register */ 6170 { 6171 long i; 6172 char_u *retval; 6173 int allocated; 6174 long len; 6175 6176 /* Don't allow using an expression register inside an expression */ 6177 if (regname == '=') 6178 { 6179 if (allowexpr) 6180 { 6181 if (expr_src) 6182 return get_expr_line_src(); 6183 return get_expr_line(); 6184 } 6185 return NULL; 6186 } 6187 6188 if (regname == '@') /* "@@" is used for unnamed register */ 6189 regname = '"'; 6190 6191 /* check for valid regname */ 6192 if (regname != NUL && !valid_yank_reg(regname, FALSE)) 6193 return NULL; 6194 6195 #ifdef FEAT_CLIPBOARD 6196 regname = may_get_selection(regname); 6197 #endif 6198 6199 if (get_spec_reg(regname, &retval, &allocated, FALSE)) 6200 { 6201 if (retval == NULL) 6202 return NULL; 6203 if (!allocated) 6204 retval = vim_strsave(retval); 6205 return retval; 6206 } 6207 6208 get_yank_register(regname, FALSE); 6209 if (y_current->y_array == NULL) 6210 return NULL; 6211 6212 /* 6213 * Compute length of resulting string. 6214 */ 6215 len = 0; 6216 for (i = 0; i < y_current->y_size; ++i) 6217 { 6218 len += (long)STRLEN(y_current->y_array[i]); 6219 /* 6220 * Insert a newline between lines and after last line if 6221 * y_type is MLINE. 6222 */ 6223 if (y_current->y_type == MLINE || i < y_current->y_size - 1) 6224 ++len; 6225 } 6226 6227 retval = lalloc(len + 1, TRUE); 6228 6229 /* 6230 * Copy the lines of the yank register into the string. 6231 */ 6232 if (retval != NULL) 6233 { 6234 len = 0; 6235 for (i = 0; i < y_current->y_size; ++i) 6236 { 6237 STRCPY(retval + len, y_current->y_array[i]); 6238 len += (long)STRLEN(retval + len); 6239 6240 /* 6241 * Insert a NL between lines and after the last line if y_type is 6242 * MLINE. 6243 */ 6244 if (y_current->y_type == MLINE || i < y_current->y_size - 1) 6245 retval[len++] = '\n'; 6246 } 6247 retval[len] = NUL; 6248 } 6249 6250 return retval; 6251 } 6252 6253 /* 6254 * Store string "str" in register "name". 6255 * "maxlen" is the maximum number of bytes to use, -1 for all bytes. 6256 * If "must_append" is TRUE, always append to the register. Otherwise append 6257 * if "name" is an uppercase letter. 6258 * Note: "maxlen" and "must_append" don't work for the "/" register. 6259 * Careful: 'str' is modified, you may have to use a copy! 6260 * If "str" ends in '\n' or '\r', use linewise, otherwise use characterwise. 6261 */ 6262 void 6263 write_reg_contents(name, str, maxlen, must_append) 6264 int name; 6265 char_u *str; 6266 int maxlen; 6267 int must_append; 6268 { 6269 write_reg_contents_ex(name, str, maxlen, must_append, MAUTO, 0L); 6270 } 6271 6272 void 6273 write_reg_contents_ex(name, str, maxlen, must_append, yank_type, block_len) 6274 int name; 6275 char_u *str; 6276 int maxlen; 6277 int must_append; 6278 int yank_type; 6279 long block_len; 6280 { 6281 struct yankreg *old_y_previous, *old_y_current; 6282 long len; 6283 6284 if (maxlen >= 0) 6285 len = maxlen; 6286 else 6287 len = (long)STRLEN(str); 6288 6289 /* Special case: '/' search pattern */ 6290 if (name == '/') 6291 { 6292 set_last_search_pat(str, RE_SEARCH, TRUE, TRUE); 6293 return; 6294 } 6295 6296 #ifdef FEAT_EVAL 6297 if (name == '=') 6298 { 6299 char_u *p, *s; 6300 6301 p = vim_strnsave(str, (int)len); 6302 if (p == NULL) 6303 return; 6304 if (must_append) 6305 { 6306 s = concat_str(get_expr_line_src(), p); 6307 vim_free(p); 6308 p = s; 6309 6310 } 6311 set_expr_line(p); 6312 return; 6313 } 6314 #endif 6315 6316 if (!valid_yank_reg(name, TRUE)) /* check for valid reg name */ 6317 { 6318 emsg_invreg(name); 6319 return; 6320 } 6321 6322 if (name == '_') /* black hole: nothing to do */ 6323 return; 6324 6325 /* Don't want to change the current (unnamed) register */ 6326 old_y_previous = y_previous; 6327 old_y_current = y_current; 6328 6329 get_yank_register(name, TRUE); 6330 if (!y_append && !must_append) 6331 free_yank_all(); 6332 #ifndef FEAT_VISUAL 6333 /* Just in case - make sure we don't use MBLOCK */ 6334 if (yank_type == MBLOCK) 6335 yank_type = MAUTO; 6336 #endif 6337 str_to_reg(y_current, yank_type, str, len, block_len); 6338 6339 # ifdef FEAT_CLIPBOARD 6340 /* Send text of clipboard register to the clipboard. */ 6341 may_set_selection(); 6342 # endif 6343 6344 /* ':let @" = "val"' should change the meaning of the "" register */ 6345 if (name != '"') 6346 y_previous = old_y_previous; 6347 y_current = old_y_current; 6348 } 6349 #endif /* FEAT_EVAL */ 6350 6351 #if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL) 6352 /* 6353 * Put a string into a register. When the register is not empty, the string 6354 * is appended. 6355 */ 6356 static void 6357 str_to_reg(y_ptr, yank_type, str, len, blocklen) 6358 struct yankreg *y_ptr; /* pointer to yank register */ 6359 int yank_type; /* MCHAR, MLINE, MBLOCK, MAUTO */ 6360 char_u *str; /* string to put in register */ 6361 long len; /* length of string */ 6362 long blocklen; /* width of Visual block */ 6363 { 6364 int type; /* MCHAR, MLINE or MBLOCK */ 6365 int lnum; 6366 long start; 6367 long i; 6368 int extra; 6369 int newlines; /* number of lines added */ 6370 int extraline = 0; /* extra line at the end */ 6371 int append = FALSE; /* append to last line in register */ 6372 char_u *s; 6373 char_u **pp; 6374 #ifdef FEAT_VISUAL 6375 long maxlen; 6376 #endif 6377 6378 if (y_ptr->y_array == NULL) /* NULL means empty register */ 6379 y_ptr->y_size = 0; 6380 6381 if (yank_type == MAUTO) 6382 type = ((len > 0 && (str[len - 1] == NL || str[len - 1] == CAR)) 6383 ? MLINE : MCHAR); 6384 else 6385 type = yank_type; 6386 6387 /* 6388 * Count the number of lines within the string 6389 */ 6390 newlines = 0; 6391 for (i = 0; i < len; i++) 6392 if (str[i] == '\n') 6393 ++newlines; 6394 if (type == MCHAR || len == 0 || str[len - 1] != '\n') 6395 { 6396 extraline = 1; 6397 ++newlines; /* count extra newline at the end */ 6398 } 6399 if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR) 6400 { 6401 append = TRUE; 6402 --newlines; /* uncount newline when appending first line */ 6403 } 6404 6405 /* 6406 * Allocate an array to hold the pointers to the new register lines. 6407 * If the register was not empty, move the existing lines to the new array. 6408 */ 6409 pp = (char_u **)lalloc_clear((y_ptr->y_size + newlines) 6410 * sizeof(char_u *), TRUE); 6411 if (pp == NULL) /* out of memory */ 6412 return; 6413 for (lnum = 0; lnum < y_ptr->y_size; ++lnum) 6414 pp[lnum] = y_ptr->y_array[lnum]; 6415 vim_free(y_ptr->y_array); 6416 y_ptr->y_array = pp; 6417 #ifdef FEAT_VISUAL 6418 maxlen = 0; 6419 #endif 6420 6421 /* 6422 * Find the end of each line and save it into the array. 6423 */ 6424 for (start = 0; start < len + extraline; start += i + 1) 6425 { 6426 for (i = start; i < len; ++i) /* find the end of the line */ 6427 if (str[i] == '\n') 6428 break; 6429 i -= start; /* i is now length of line */ 6430 #ifdef FEAT_VISUAL 6431 if (i > maxlen) 6432 maxlen = i; 6433 #endif 6434 if (append) 6435 { 6436 --lnum; 6437 extra = (int)STRLEN(y_ptr->y_array[lnum]); 6438 } 6439 else 6440 extra = 0; 6441 s = alloc((unsigned)(i + extra + 1)); 6442 if (s == NULL) 6443 break; 6444 if (extra) 6445 mch_memmove(s, y_ptr->y_array[lnum], (size_t)extra); 6446 if (append) 6447 vim_free(y_ptr->y_array[lnum]); 6448 if (i) 6449 mch_memmove(s + extra, str + start, (size_t)i); 6450 extra += i; 6451 s[extra] = NUL; 6452 y_ptr->y_array[lnum++] = s; 6453 while (--extra >= 0) 6454 { 6455 if (*s == NUL) 6456 *s = '\n'; /* replace NUL with newline */ 6457 ++s; 6458 } 6459 append = FALSE; /* only first line is appended */ 6460 } 6461 y_ptr->y_type = type; 6462 y_ptr->y_size = lnum; 6463 # ifdef FEAT_VISUAL 6464 if (type == MBLOCK) 6465 y_ptr->y_width = (blocklen < 0 ? maxlen - 1 : blocklen); 6466 else 6467 y_ptr->y_width = 0; 6468 # endif 6469 } 6470 #endif /* FEAT_CLIPBOARD || FEAT_EVAL || PROTO */ 6471 6472 void 6473 clear_oparg(oap) 6474 oparg_T *oap; 6475 { 6476 vim_memset(oap, 0, sizeof(oparg_T)); 6477 } 6478 6479 static long line_count_info __ARGS((char_u *line, long *wc, long *cc, long limit, int eol_size)); 6480 6481 /* 6482 * Count the number of bytes, characters and "words" in a line. 6483 * 6484 * "Words" are counted by looking for boundaries between non-space and 6485 * space characters. (it seems to produce results that match 'wc'.) 6486 * 6487 * Return value is byte count; word count for the line is added to "*wc". 6488 * Char count is added to "*cc". 6489 * 6490 * The function will only examine the first "limit" characters in the 6491 * line, stopping if it encounters an end-of-line (NUL byte). In that 6492 * case, eol_size will be added to the character count to account for 6493 * the size of the EOL character. 6494 */ 6495 static long 6496 line_count_info(line, wc, cc, limit, eol_size) 6497 char_u *line; 6498 long *wc; 6499 long *cc; 6500 long limit; 6501 int eol_size; 6502 { 6503 long i; 6504 long words = 0; 6505 long chars = 0; 6506 int is_word = 0; 6507 6508 for (i = 0; i < limit && line[i] != NUL; ) 6509 { 6510 if (is_word) 6511 { 6512 if (vim_isspace(line[i])) 6513 { 6514 words++; 6515 is_word = 0; 6516 } 6517 } 6518 else if (!vim_isspace(line[i])) 6519 is_word = 1; 6520 ++chars; 6521 #ifdef FEAT_MBYTE 6522 i += (*mb_ptr2len)(line + i); 6523 #else 6524 ++i; 6525 #endif 6526 } 6527 6528 if (is_word) 6529 words++; 6530 *wc += words; 6531 6532 /* Add eol_size if the end of line was reached before hitting limit. */ 6533 if (i < limit && line[i] == NUL) 6534 { 6535 i += eol_size; 6536 chars += eol_size; 6537 } 6538 *cc += chars; 6539 return i; 6540 } 6541 6542 /* 6543 * Give some info about the position of the cursor (for "g CTRL-G"). 6544 * In Visual mode, give some info about the selected region. (In this case, 6545 * the *_count_cursor variables store running totals for the selection.) 6546 */ 6547 void 6548 cursor_pos_info() 6549 { 6550 char_u *p; 6551 char_u buf1[50]; 6552 char_u buf2[40]; 6553 linenr_T lnum; 6554 long byte_count = 0; 6555 long byte_count_cursor = 0; 6556 long char_count = 0; 6557 long char_count_cursor = 0; 6558 long word_count = 0; 6559 long word_count_cursor = 0; 6560 int eol_size; 6561 long last_check = 100000L; 6562 #ifdef FEAT_VISUAL 6563 long line_count_selected = 0; 6564 pos_T min_pos, max_pos; 6565 oparg_T oparg; 6566 struct block_def bd; 6567 #endif 6568 6569 /* 6570 * Compute the length of the file in characters. 6571 */ 6572 if (curbuf->b_ml.ml_flags & ML_EMPTY) 6573 { 6574 MSG(_(no_lines_msg)); 6575 } 6576 else 6577 { 6578 if (get_fileformat(curbuf) == EOL_DOS) 6579 eol_size = 2; 6580 else 6581 eol_size = 1; 6582 6583 #ifdef FEAT_VISUAL 6584 if (VIsual_active) 6585 { 6586 if (lt(VIsual, curwin->w_cursor)) 6587 { 6588 min_pos = VIsual; 6589 max_pos = curwin->w_cursor; 6590 } 6591 else 6592 { 6593 min_pos = curwin->w_cursor; 6594 max_pos = VIsual; 6595 } 6596 if (*p_sel == 'e' && max_pos.col > 0) 6597 --max_pos.col; 6598 6599 if (VIsual_mode == Ctrl_V) 6600 { 6601 #ifdef FEAT_LINEBREAK 6602 char_u * saved_sbr = p_sbr; 6603 6604 /* Make 'sbr' empty for a moment to get the correct size. */ 6605 p_sbr = empty_option; 6606 #endif 6607 oparg.is_VIsual = 1; 6608 oparg.block_mode = TRUE; 6609 oparg.op_type = OP_NOP; 6610 getvcols(curwin, &min_pos, &max_pos, 6611 &oparg.start_vcol, &oparg.end_vcol); 6612 #ifdef FEAT_LINEBREAK 6613 p_sbr = saved_sbr; 6614 #endif 6615 if (curwin->w_curswant == MAXCOL) 6616 oparg.end_vcol = MAXCOL; 6617 /* Swap the start, end vcol if needed */ 6618 if (oparg.end_vcol < oparg.start_vcol) 6619 { 6620 oparg.end_vcol += oparg.start_vcol; 6621 oparg.start_vcol = oparg.end_vcol - oparg.start_vcol; 6622 oparg.end_vcol -= oparg.start_vcol; 6623 } 6624 } 6625 line_count_selected = max_pos.lnum - min_pos.lnum + 1; 6626 } 6627 #endif 6628 6629 for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) 6630 { 6631 /* Check for a CTRL-C every 100000 characters. */ 6632 if (byte_count > last_check) 6633 { 6634 ui_breakcheck(); 6635 if (got_int) 6636 return; 6637 last_check = byte_count + 100000L; 6638 } 6639 6640 #ifdef FEAT_VISUAL 6641 /* Do extra processing for VIsual mode. */ 6642 if (VIsual_active 6643 && lnum >= min_pos.lnum && lnum <= max_pos.lnum) 6644 { 6645 char_u *s = NULL; 6646 long len = 0L; 6647 6648 switch (VIsual_mode) 6649 { 6650 case Ctrl_V: 6651 # ifdef FEAT_VIRTUALEDIT 6652 virtual_op = virtual_active(); 6653 # endif 6654 block_prep(&oparg, &bd, lnum, 0); 6655 # ifdef FEAT_VIRTUALEDIT 6656 virtual_op = MAYBE; 6657 # endif 6658 s = bd.textstart; 6659 len = (long)bd.textlen; 6660 break; 6661 case 'V': 6662 s = ml_get(lnum); 6663 len = MAXCOL; 6664 break; 6665 case 'v': 6666 { 6667 colnr_T start_col = (lnum == min_pos.lnum) 6668 ? min_pos.col : 0; 6669 colnr_T end_col = (lnum == max_pos.lnum) 6670 ? max_pos.col - start_col + 1 : MAXCOL; 6671 6672 s = ml_get(lnum) + start_col; 6673 len = end_col; 6674 } 6675 break; 6676 } 6677 if (s != NULL) 6678 { 6679 byte_count_cursor += line_count_info(s, &word_count_cursor, 6680 &char_count_cursor, len, eol_size); 6681 if (lnum == curbuf->b_ml.ml_line_count 6682 && !curbuf->b_p_eol 6683 && curbuf->b_p_bin 6684 && (long)STRLEN(s) < len) 6685 byte_count_cursor -= eol_size; 6686 } 6687 } 6688 else 6689 #endif 6690 { 6691 /* In non-visual mode, check for the line the cursor is on */ 6692 if (lnum == curwin->w_cursor.lnum) 6693 { 6694 word_count_cursor += word_count; 6695 char_count_cursor += char_count; 6696 byte_count_cursor = byte_count + 6697 line_count_info(ml_get(lnum), 6698 &word_count_cursor, &char_count_cursor, 6699 (long)(curwin->w_cursor.col + 1), eol_size); 6700 } 6701 } 6702 /* Add to the running totals */ 6703 byte_count += line_count_info(ml_get(lnum), &word_count, 6704 &char_count, (long)MAXCOL, eol_size); 6705 } 6706 6707 /* Correction for when last line doesn't have an EOL. */ 6708 if (!curbuf->b_p_eol && curbuf->b_p_bin) 6709 byte_count -= eol_size; 6710 6711 #ifdef FEAT_VISUAL 6712 if (VIsual_active) 6713 { 6714 if (VIsual_mode == Ctrl_V && curwin->w_curswant < MAXCOL) 6715 { 6716 getvcols(curwin, &min_pos, &max_pos, &min_pos.col, 6717 &max_pos.col); 6718 vim_snprintf((char *)buf1, sizeof(buf1), _("%ld Cols; "), 6719 (long)(oparg.end_vcol - oparg.start_vcol + 1)); 6720 } 6721 else 6722 buf1[0] = NUL; 6723 6724 if (char_count_cursor == byte_count_cursor 6725 && char_count == byte_count) 6726 vim_snprintf((char *)IObuff, IOSIZE, 6727 _("Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Bytes"), 6728 buf1, line_count_selected, 6729 (long)curbuf->b_ml.ml_line_count, 6730 word_count_cursor, word_count, 6731 byte_count_cursor, byte_count); 6732 else 6733 vim_snprintf((char *)IObuff, IOSIZE, 6734 _("Selected %s%ld of %ld Lines; %ld of %ld Words; %ld of %ld Chars; %ld of %ld Bytes"), 6735 buf1, line_count_selected, 6736 (long)curbuf->b_ml.ml_line_count, 6737 word_count_cursor, word_count, 6738 char_count_cursor, char_count, 6739 byte_count_cursor, byte_count); 6740 } 6741 else 6742 #endif 6743 { 6744 p = ml_get_curline(); 6745 validate_virtcol(); 6746 col_print(buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1, 6747 (int)curwin->w_virtcol + 1); 6748 col_print(buf2, sizeof(buf2), (int)STRLEN(p), linetabsize(p)); 6749 6750 if (char_count_cursor == byte_count_cursor 6751 && char_count == byte_count) 6752 vim_snprintf((char *)IObuff, IOSIZE, 6753 _("Col %s of %s; Line %ld of %ld; Word %ld of %ld; Byte %ld of %ld"), 6754 (char *)buf1, (char *)buf2, 6755 (long)curwin->w_cursor.lnum, 6756 (long)curbuf->b_ml.ml_line_count, 6757 word_count_cursor, word_count, 6758 byte_count_cursor, byte_count); 6759 else 6760 vim_snprintf((char *)IObuff, IOSIZE, 6761 _("Col %s of %s; Line %ld of %ld; Word %ld of %ld; Char %ld of %ld; Byte %ld of %ld"), 6762 (char *)buf1, (char *)buf2, 6763 (long)curwin->w_cursor.lnum, 6764 (long)curbuf->b_ml.ml_line_count, 6765 word_count_cursor, word_count, 6766 char_count_cursor, char_count, 6767 byte_count_cursor, byte_count); 6768 } 6769 6770 #ifdef FEAT_MBYTE 6771 byte_count = bomb_size(); 6772 if (byte_count > 0) 6773 sprintf((char *)IObuff + STRLEN(IObuff), _("(+%ld for BOM)"), 6774 byte_count); 6775 #endif 6776 /* Don't shorten this message, the user asked for it. */ 6777 p = p_shm; 6778 p_shm = (char_u *)""; 6779 msg(IObuff); 6780 p_shm = p; 6781 } 6782 } 6783