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