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