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