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