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