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