register.c (82436B)
1 // register.c: functions for managing registers 2 3 #include "nvim/api/private/helpers.h" 4 #include "nvim/autocmd.h" 5 #include "nvim/buffer.h" 6 #include "nvim/buffer_defs.h" 7 #include "nvim/buffer_updates.h" 8 #include "nvim/change.h" 9 #include "nvim/charset.h" 10 #include "nvim/clipboard.h" 11 #include "nvim/cursor.h" 12 #include "nvim/drawscreen.h" 13 #include "nvim/edit.h" 14 #include "nvim/errors.h" 15 #include "nvim/eval.h" 16 #include "nvim/eval/typval.h" 17 #include "nvim/ex_cmds2.h" 18 #include "nvim/ex_getln.h" 19 #include "nvim/extmark.h" 20 #include "nvim/file_search.h" 21 #include "nvim/fold.h" 22 #include "nvim/garray.h" 23 #include "nvim/getchar.h" 24 #include "nvim/globals.h" 25 #include "nvim/indent.h" 26 #include "nvim/insexpand.h" 27 #include "nvim/keycodes.h" 28 #include "nvim/mark.h" 29 #include "nvim/mbyte.h" 30 #include "nvim/memline.h" 31 #include "nvim/message.h" 32 #include "nvim/move.h" 33 #include "nvim/normal.h" 34 #include "nvim/ops.h" 35 #include "nvim/option.h" 36 #include "nvim/option_vars.h" 37 #include "nvim/os/input.h" 38 #include "nvim/os/time.h" 39 #include "nvim/plines.h" 40 #include "nvim/register.h" 41 #include "nvim/search.h" 42 #include "nvim/strings.h" 43 #include "nvim/terminal.h" 44 #include "nvim/types_defs.h" 45 #include "nvim/ui.h" 46 #include "nvim/undo.h" 47 48 #include "register.c.generated.h" 49 50 // Keep the last expression line here, for repeating. 51 static char *expr_line = NULL; 52 53 static int execreg_lastc = NUL; 54 55 static yankreg_T y_regs[NUM_REGISTERS] = { 0 }; 56 57 static yankreg_T *y_previous = NULL; // ptr to last written yankreg 58 59 static const char e_search_pattern_and_expression_register_may_not_contain_two_or_more_lines[] 60 = N_("E883: Search pattern and expression register may not contain two or more lines"); 61 62 /// @return the index of the register "" points to. 63 int get_unname_register(void) 64 { 65 return y_previous == NULL ? -1 : (int)(y_previous - &y_regs[0]); 66 } 67 68 yankreg_T *get_y_register(int reg) 69 { 70 return &y_regs[reg]; 71 } 72 73 yankreg_T *get_y_previous(void) 74 FUNC_ATTR_PURE 75 { 76 return y_previous; 77 } 78 79 /// Get an expression for the "\"=expr1" or "CTRL-R =expr1" 80 /// 81 /// @return '=' when OK, NUL otherwise. 82 int get_expr_register(void) 83 { 84 char *new_line = getcmdline('=', 0, 0, true); 85 if (new_line == NULL) { 86 return NUL; 87 } 88 if (*new_line == NUL) { // use previous line 89 xfree(new_line); 90 } else { 91 set_expr_line(new_line); 92 } 93 return '='; 94 } 95 96 /// Set the expression for the '=' register. 97 /// Argument must be an allocated string. 98 void set_expr_line(char *new_line) 99 { 100 xfree(expr_line); 101 expr_line = new_line; 102 } 103 104 /// Get the result of the '=' register expression. 105 /// 106 /// @return a pointer to allocated memory, or NULL for failure. 107 char *get_expr_line(void) 108 { 109 static int nested = 0; 110 111 if (expr_line == NULL) { 112 return NULL; 113 } 114 115 // Make a copy of the expression, because evaluating it may cause it to be 116 // changed. 117 char *expr_copy = xstrdup(expr_line); 118 119 // When we are invoked recursively limit the evaluation to 10 levels. 120 // Then return the string as-is. 121 if (nested >= 10) { 122 return expr_copy; 123 } 124 125 nested++; 126 char *rv = eval_to_string(expr_copy, true, false); 127 nested--; 128 xfree(expr_copy); 129 return rv; 130 } 131 132 /// Get the '=' register expression itself, without evaluating it. 133 char *get_expr_line_src(void) 134 { 135 if (expr_line == NULL) { 136 return NULL; 137 } 138 return xstrdup(expr_line); 139 } 140 141 /// @return whether `regname` is a valid name of a yank register. 142 /// 143 /// @note: There is no check for 0 (default register), caller should do this. 144 /// The black hole register '_' is regarded as valid. 145 /// 146 /// @param regname name of register 147 /// @param writing allow only writable registers 148 bool valid_yank_reg(int regname, bool writing) 149 { 150 if ((regname > 0 && ASCII_ISALNUM(regname)) 151 || (!writing && vim_strchr("/.%:=", regname) != NULL) 152 || regname == '#' 153 || regname == '"' 154 || regname == '-' 155 || regname == '_' 156 || regname == '*' 157 || regname == '+') { 158 return true; 159 } 160 return false; 161 } 162 163 /// Check if the default register (used in an unnamed paste) should be a 164 /// clipboard register. This happens when `clipboard=unnamed[plus]` is set 165 /// and a provider is available. 166 /// 167 /// @returns the name of of a clipboard register that should be used, or `NUL` if none. 168 int get_default_register_name(void) 169 { 170 int name = NUL; 171 adjust_clipboard_name(&name, true, false); 172 return name; 173 } 174 175 /// Iterate over registers `regs`. 176 /// 177 /// @param[in] iter Iterator. Pass NULL to start iteration. 178 /// @param[in] regs Registers list to be iterated. 179 /// @param[out] name Register name. 180 /// @param[out] reg Register contents. 181 /// 182 /// @return Pointer that must be passed to next `op_register_iter` call or 183 /// NULL if iteration is over. 184 const void *op_reg_iter(const void *const iter, const yankreg_T *const regs, char *const name, 185 yankreg_T *const reg, bool *is_unnamed) 186 FUNC_ATTR_NONNULL_ARG(3, 4, 5) FUNC_ATTR_WARN_UNUSED_RESULT 187 { 188 *name = NUL; 189 const yankreg_T *iter_reg = (iter == NULL 190 ? &(regs[0]) 191 : (const yankreg_T *const)iter); 192 while (iter_reg - &(regs[0]) < NUM_SAVED_REGISTERS && reg_empty(iter_reg)) { 193 iter_reg++; 194 } 195 if (iter_reg - &(regs[0]) == NUM_SAVED_REGISTERS || reg_empty(iter_reg)) { 196 return NULL; 197 } 198 int iter_off = (int)(iter_reg - &(regs[0])); 199 *name = (char)get_register_name(iter_off); 200 *reg = *iter_reg; 201 *is_unnamed = (iter_reg == y_previous); 202 while (++iter_reg - &(regs[0]) < NUM_SAVED_REGISTERS) { 203 if (!reg_empty(iter_reg)) { 204 return (void *)iter_reg; 205 } 206 } 207 return NULL; 208 } 209 210 /// Iterate over global registers. 211 /// 212 /// @see op_register_iter 213 const void *op_global_reg_iter(const void *const iter, char *const name, yankreg_T *const reg, 214 bool *is_unnamed) 215 FUNC_ATTR_NONNULL_ARG(2, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT 216 { 217 return op_reg_iter(iter, y_regs, name, reg, is_unnamed); 218 } 219 220 /// Get a number of non-empty registers 221 size_t op_reg_amount(void) 222 FUNC_ATTR_WARN_UNUSED_RESULT 223 { 224 size_t ret = 0; 225 for (size_t i = 0; i < NUM_SAVED_REGISTERS; i++) { 226 if (!reg_empty(y_regs + i)) { 227 ret++; 228 } 229 } 230 return ret; 231 } 232 233 /// Set register to a given value 234 /// 235 /// @param[in] name Register name. 236 /// @param[in] reg Register value. 237 /// @param[in] is_unnamed Whether to set the unnamed regiseter to reg 238 /// 239 /// @return true on success, false on failure. 240 bool op_reg_set(const char name, const yankreg_T reg, bool is_unnamed) 241 { 242 int i = op_reg_index(name); 243 if (i == -1) { 244 return false; 245 } 246 free_register(&y_regs[i]); 247 y_regs[i] = reg; 248 249 if (is_unnamed) { 250 y_previous = &y_regs[i]; 251 } 252 return true; 253 } 254 255 /// Get register with the given name 256 /// 257 /// @param[in] name Register name. 258 /// 259 /// @return Pointer to the register contents or NULL. 260 const yankreg_T *op_reg_get(const char name) 261 { 262 int i = op_reg_index(name); 263 if (i == -1) { 264 return NULL; 265 } 266 return &y_regs[i]; 267 } 268 269 /// Set the previous yank register 270 /// 271 /// @param[in] name Register name. 272 /// 273 /// @return true on success, false on failure. 274 bool op_reg_set_previous(const char name) 275 { 276 int i = op_reg_index(name); 277 if (i == -1) { 278 return false; 279 } 280 281 y_previous = &y_regs[i]; 282 return true; 283 } 284 285 /// Updates the "y_width" of a blockwise register based on its contents. 286 /// Do nothing on a non-blockwise register. 287 void update_yankreg_width(yankreg_T *reg) 288 { 289 if (reg->y_type == kMTBlockWise) { 290 size_t maxlen = 0; 291 for (size_t i = 0; i < reg->y_size; i++) { 292 size_t rowlen = mb_string2cells_len(reg->y_array[i].data, reg->y_array[i].size); 293 maxlen = MAX(maxlen, rowlen); 294 } 295 assert(maxlen <= INT_MAX); 296 reg->y_width = MAX(reg->y_width, (int)maxlen - 1); 297 } 298 } 299 300 /// @return yankreg_T to use, according to the value of `regname`. 301 /// Cannot handle the '_' (black hole) register. 302 /// Must only be called with a valid register name! 303 /// 304 /// @param regname The name of the register used or 0 for the unnamed register 305 /// @param mode One of the following three flags: 306 /// 307 /// `YREG_PASTE`: 308 /// Prepare for pasting the register `regname`. With no regname specified, 309 /// read from last written register, or from unnamed clipboard (depending on the 310 /// `clipboard=unnamed` option). Queries the clipboard provider if necessary. 311 /// 312 /// `YREG_YANK`: 313 /// Preparare for yanking into `regname`. With no regname specified, 314 /// yank into `"0` register. Update `y_previous` for next unnamed paste. 315 /// 316 /// `YREG_PUT`: 317 /// Obtain the location that would be read when pasting `regname`. 318 yankreg_T *get_yank_register(int regname, int mode) 319 { 320 yankreg_T *reg; 321 322 if ((mode == YREG_PASTE || mode == YREG_PUT) 323 && get_clipboard(regname, ®, false)) { 324 // reg is set to clipboard contents. 325 return reg; 326 } else if (mode == YREG_PUT && (regname == '*' || regname == '+')) { 327 // in case clipboard not available and we aren't actually pasting, 328 // return an empty register 329 static yankreg_T empty_reg = { .y_array = NULL }; 330 return &empty_reg; 331 } else if (mode != YREG_YANK 332 && (regname == 0 || regname == '"' || regname == '*' || regname == '+') 333 && y_previous != NULL) { 334 // in case clipboard not available, paste from previous used register 335 return y_previous; 336 } 337 338 int i = op_reg_index(regname); 339 // when not 0-9, a-z, A-Z or '-'/'+'/'*': use register 0 340 if (i == -1) { 341 i = 0; 342 } 343 reg = &y_regs[i]; 344 345 if (mode == YREG_YANK) { 346 // remember the written register for unnamed paste 347 y_previous = reg; 348 } 349 return reg; 350 } 351 352 /// Check if the current yank register has kMTLineWise register type 353 /// For valid, non-blackhole registers also provides pointer to the register 354 /// structure prepared for pasting. 355 /// 356 /// @param regname The name of the register used or 0 for the unnamed register 357 /// @param reg Pointer to store yankreg_T* for the requested register. Will be 358 /// set to NULL for invalid or blackhole registers. 359 bool yank_register_mline(int regname, yankreg_T **reg) 360 { 361 *reg = NULL; 362 if (regname != 0 && !valid_yank_reg(regname, false)) { 363 return false; 364 } 365 if (regname == '_') { // black hole is always empty 366 return false; 367 } 368 *reg = get_yank_register(regname, YREG_PASTE); 369 return (*reg)->y_type == kMTLineWise; 370 } 371 372 /// @return a copy of contents in register `name` for use in do_put. Should be 373 /// freed by caller. 374 yankreg_T *copy_register(int name) 375 FUNC_ATTR_NONNULL_RET 376 { 377 yankreg_T *reg = get_yank_register(name, YREG_PASTE); 378 379 yankreg_T *copy = xmalloc(sizeof(yankreg_T)); 380 *copy = *reg; 381 if (copy->y_size == 0) { 382 copy->y_array = NULL; 383 } else { 384 copy->y_array = xcalloc(copy->y_size, sizeof(String)); 385 for (size_t i = 0; i < copy->y_size; i++) { 386 copy->y_array[i] = copy_string(reg->y_array[i], NULL); 387 } 388 } 389 return copy; 390 } 391 392 /// Stuff string "p" into yank register "regname" as a single line (append if 393 /// uppercase). "p" must have been allocated. 394 /// 395 /// @return FAIL for failure, OK otherwise 396 static int stuff_yank(int regname, char *p) 397 { 398 // check for read-only register 399 if (regname != 0 && !valid_yank_reg(regname, true)) { 400 xfree(p); 401 return FAIL; 402 } 403 if (regname == '_') { // black hole: don't do anything 404 xfree(p); 405 return OK; 406 } 407 408 const size_t plen = strlen(p); 409 yankreg_T *reg = get_yank_register(regname, YREG_YANK); 410 if (is_append_register(regname) && reg->y_array != NULL) { 411 String *pp = &(reg->y_array[reg->y_size - 1]); 412 const size_t tmplen = pp->size + plen; 413 char *tmp = xmalloc(tmplen + 1); 414 memcpy(tmp, pp->data, pp->size); 415 memcpy(tmp + pp->size, p, plen); 416 *(tmp + tmplen) = NUL; 417 xfree(p); 418 xfree(pp->data); 419 *pp = cbuf_as_string(tmp, tmplen); 420 } else { 421 free_register(reg); 422 reg->additional_data = NULL; 423 reg->y_array = xmalloc(sizeof(String)); 424 reg->y_array[0] = cbuf_as_string(p, plen); 425 reg->y_size = 1; 426 reg->y_type = kMTCharWise; 427 } 428 reg->timestamp = os_time(); 429 return OK; 430 } 431 432 /// Start or stop recording into a yank register. 433 /// 434 /// @return FAIL for failure, OK otherwise. 435 int do_record(int c) 436 { 437 static int regname; 438 int retval; 439 440 if (reg_recording == 0) { 441 // start recording 442 // registers 0-9, a-z and " are allowed 443 if (c < 0 || (!ASCII_ISALNUM(c) && c != '"')) { 444 retval = FAIL; 445 } else { 446 reg_recording = c; 447 // TODO(bfredl): showmode based messaging is currently missing with cmdheight=0 448 showmode(); 449 regname = c; 450 retval = OK; 451 452 apply_autocmds(EVENT_RECORDINGENTER, NULL, NULL, false, curbuf); 453 } 454 } else { // stop recording 455 save_v_event_T save_v_event; 456 // Set the v:event dictionary with information about the recording. 457 dict_T *dict = get_v_event(&save_v_event); 458 459 // The recorded text contents. 460 char *p = get_recorded(); 461 if (p != NULL) { 462 // Remove escaping for K_SPECIAL in multi-byte chars. 463 vim_unescape_ks(p); 464 tv_dict_add_str(dict, S_LEN("regcontents"), p); 465 } 466 467 // Name of requested register, or empty string for unnamed operation. 468 char buf[NUMBUFLEN + 2]; 469 buf[0] = (char)regname; 470 buf[1] = NUL; 471 tv_dict_add_str(dict, S_LEN("regname"), buf); 472 tv_dict_set_keys_readonly(dict); 473 474 // Get the recorded key hits. K_SPECIAL will be escaped, this 475 // needs to be removed again to put it in a register. exec_reg then 476 // adds the escaping back later. 477 apply_autocmds(EVENT_RECORDINGLEAVE, NULL, NULL, false, curbuf); 478 restore_v_event(dict, &save_v_event); 479 reg_recorded = reg_recording; 480 reg_recording = 0; 481 if (p_ch == 0 || ui_has(kUIMessages)) { 482 showmode(); 483 } else { 484 msg("", 0); 485 } 486 if (p == NULL) { 487 retval = FAIL; 488 } else { 489 // We don't want to change the default register here, so save and 490 // restore the current register name. 491 yankreg_T *old_y_previous = y_previous; 492 493 retval = stuff_yank(regname, p); 494 495 y_previous = old_y_previous; 496 } 497 } 498 return retval; 499 } 500 501 /// Insert register contents "s" into the typeahead buffer, so that it will be 502 /// executed again. 503 /// 504 /// @param esc when true then it is to be taken literally: Escape K_SPECIAL 505 /// characters and no remapping. 506 /// @param colon add ':' before the line 507 static int put_in_typebuf(char *s, bool esc, bool colon, int silent) 508 { 509 int retval = OK; 510 511 put_reedit_in_typebuf(silent); 512 if (colon) { 513 retval = ins_typebuf("\n", REMAP_NONE, 0, true, silent); 514 } 515 if (retval == OK) { 516 char *p; 517 518 if (esc) { 519 p = vim_strsave_escape_ks(s); 520 } else { 521 p = s; 522 } 523 if (p == NULL) { 524 retval = FAIL; 525 } else { 526 retval = ins_typebuf(p, esc ? REMAP_NONE : REMAP_YES, 0, true, silent); 527 } 528 if (esc) { 529 xfree(p); 530 } 531 } 532 if (colon && retval == OK) { 533 retval = ins_typebuf(":", REMAP_NONE, 0, true, silent); 534 } 535 return retval; 536 } 537 538 /// If "restart_edit" is not zero, put it in the typeahead buffer, so that it's 539 /// used only after other typeahead has been processed. 540 static void put_reedit_in_typebuf(int silent) 541 { 542 uint8_t buf[3]; 543 544 if (restart_edit == NUL) { 545 return; 546 } 547 548 if (restart_edit == 'V') { 549 buf[0] = 'g'; 550 buf[1] = 'R'; 551 buf[2] = NUL; 552 } else { 553 buf[0] = (uint8_t)(restart_edit == 'I' ? 'i' : restart_edit); 554 buf[1] = NUL; 555 } 556 if (ins_typebuf((char *)buf, REMAP_NONE, 0, true, silent) == OK) { 557 restart_edit = NUL; 558 } 559 } 560 561 /// When executing a register as a series of ex-commands, if the 562 /// line-continuation character is used for a line, then join it with one or 563 /// more previous lines. Note that lines are processed backwards starting from 564 /// the last line in the register. 565 /// 566 /// @param lines list of lines in the register 567 /// @param idx index of the line starting with \ or "\. Join this line with all the immediate 568 /// predecessor lines that start with a \ and the first line that doesn't start 569 /// with a \. Lines that start with a comment "\ character are ignored. 570 /// @returns the concatenated line. The index of the line that should be 571 /// processed next is returned in idx. 572 static char *execreg_line_continuation(String *lines, size_t *idx) 573 { 574 size_t cmd_start = *idx; 575 assert(cmd_start > 0); 576 const size_t cmd_end = cmd_start; 577 578 garray_T ga; 579 ga_init(&ga, (int)sizeof(char), 400); 580 581 // search backwards to find the first line of this command. 582 // Any line not starting with \ or "\ is the start of the 583 // command. 584 while (--cmd_start > 0) { 585 char *p = skipwhite(lines[cmd_start].data); 586 if (*p != '\\' && (p[0] != '"' || p[1] != '\\' || p[2] != ' ')) { 587 break; 588 } 589 } 590 591 // join all the lines 592 String *tmp = &lines[cmd_start]; 593 ga_concat_len(&ga, tmp->data, tmp->size); 594 for (size_t j = cmd_start + 1; j <= cmd_end; j++) { 595 tmp = &lines[j]; 596 char *p = skipwhite(tmp->data); 597 if (*p == '\\') { 598 // Adjust the growsize to the current length to 599 // speed up concatenating many lines. 600 if (ga.ga_len > 400) { 601 ga_set_growsize(&ga, MIN(ga.ga_len, 8000)); 602 } 603 p++; 604 ga_concat_len(&ga, p, (size_t)(tmp->data + tmp->size - p)); 605 } 606 } 607 ga_append(&ga, NUL); 608 char *str = xmemdupz(ga.ga_data, (size_t)ga.ga_len); 609 ga_clear(&ga); 610 611 *idx = cmd_start; 612 return str; 613 } 614 615 /// Execute a yank register: copy it into the stuff buffer 616 /// 617 /// @param colon insert ':' before each line 618 /// @param addcr always add '\n' to end of line 619 /// @param silent set "silent" flag in typeahead buffer 620 /// 621 /// @return FAIL for failure, OK otherwise 622 int do_execreg(int regname, int colon, int addcr, int silent) 623 { 624 int retval = OK; 625 626 if (regname == '@') { // repeat previous one 627 if (execreg_lastc == NUL) { 628 emsg(_("E748: No previously used register")); 629 return FAIL; 630 } 631 regname = execreg_lastc; 632 } 633 // check for valid regname 634 if (regname == '%' || regname == '#' || !valid_yank_reg(regname, false)) { 635 emsg_invreg(regname); 636 return FAIL; 637 } 638 execreg_lastc = regname; 639 640 if (regname == '_') { // black hole: don't stuff anything 641 return OK; 642 } 643 644 if (regname == ':') { // use last command line 645 if (last_cmdline == NULL) { 646 emsg(_(e_nolastcmd)); 647 return FAIL; 648 } 649 // don't keep the cmdline containing @: 650 XFREE_CLEAR(new_last_cmdline); 651 // Escape all control characters with a CTRL-V 652 char *p = vim_strsave_escaped_ext(last_cmdline, 653 "\001\002\003\004\005\006\007" 654 "\010\011\012\013\014\015\016\017" 655 "\020\021\022\023\024\025\026\027" 656 "\030\031\032\033\034\035\036\037", 657 Ctrl_V, false); 658 // When in Visual mode "'<,'>" will be prepended to the command. 659 // Remove it when it's already there. 660 if (VIsual_active && strncmp(p, "'<,'>", 5) == 0) { 661 retval = put_in_typebuf(p + 5, true, true, silent); 662 } else { 663 retval = put_in_typebuf(p, true, true, silent); 664 } 665 xfree(p); 666 } else if (regname == '=') { 667 char *p = get_expr_line(); 668 if (p == NULL) { 669 return FAIL; 670 } 671 retval = put_in_typebuf(p, true, colon, silent); 672 xfree(p); 673 } else if (regname == '.') { // use last inserted text 674 char *p = get_last_insert_save(); 675 if (p == NULL) { 676 emsg(_(e_noinstext)); 677 return FAIL; 678 } 679 retval = put_in_typebuf(p, false, colon, silent); 680 xfree(p); 681 } else { 682 yankreg_T *reg = get_yank_register(regname, YREG_PASTE); 683 if (reg->y_array == NULL) { 684 return FAIL; 685 } 686 687 // Disallow remapping for ":@r". 688 int remap = colon ? REMAP_NONE : REMAP_YES; 689 690 // Insert lines into typeahead buffer, from last one to first one. 691 put_reedit_in_typebuf(silent); 692 for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included 693 // insert NL between lines and after last line if type is kMTLineWise 694 if (reg->y_type == kMTLineWise || i < reg->y_size - 1 || addcr) { 695 if (ins_typebuf("\n", remap, 0, true, silent) == FAIL) { 696 return FAIL; 697 } 698 } 699 700 // Handle line-continuation for :@<register> 701 char *str = reg->y_array[i].data; 702 bool free_str = false; 703 if (colon && i > 0) { 704 char *p = skipwhite(str); 705 if (*p == '\\' || (p[0] == '"' && p[1] == '\\' && p[2] == ' ')) { 706 str = execreg_line_continuation(reg->y_array, &i); 707 free_str = true; 708 } 709 } 710 char *escaped = vim_strsave_escape_ks(str); 711 if (free_str) { 712 xfree(str); 713 } 714 retval = ins_typebuf(escaped, remap, 0, true, silent); 715 xfree(escaped); 716 if (retval == FAIL) { 717 return FAIL; 718 } 719 if (colon 720 && ins_typebuf(":", remap, 0, true, silent) == FAIL) { 721 return FAIL; 722 } 723 } 724 reg_executing = regname == 0 ? '"' : regname; // disable the 'q' command 725 pending_end_reg_executing = false; 726 } 727 return retval; 728 } 729 730 /// Insert a yank register: copy it into the Read buffer. 731 /// Used by CTRL-R command and middle mouse button in insert mode. 732 /// 733 /// @param literally_arg insert literally, not as if typed 734 /// 735 /// @return FAIL for failure, OK otherwise 736 int insert_reg(int regname, yankreg_T *reg, bool literally_arg) 737 { 738 int retval = OK; 739 bool allocated; 740 const bool literally = literally_arg || is_literal_register(regname); 741 742 // It is possible to get into an endless loop by having CTRL-R a in 743 // register a and then, in insert mode, doing CTRL-R a. 744 // If you hit CTRL-C, the loop will be broken here. 745 os_breakcheck(); 746 if (got_int) { 747 return FAIL; 748 } 749 750 // check for valid regname 751 if (regname != NUL && !valid_yank_reg(regname, false)) { 752 return FAIL; 753 } 754 755 char *arg; 756 if (regname == '.') { // Insert last inserted text. 757 retval = stuff_inserted(NUL, 1, true); 758 } else if (get_spec_reg(regname, &arg, &allocated, true)) { 759 if (arg == NULL) { 760 return FAIL; 761 } 762 stuffescaped(arg, literally); 763 if (allocated) { 764 xfree(arg); 765 } 766 } else { // Name or number register. 767 if (reg == NULL) { 768 reg = get_yank_register(regname, YREG_PASTE); 769 } 770 if (reg->y_array == NULL) { 771 retval = FAIL; 772 } else { 773 for (size_t i = 0; i < reg->y_size; i++) { 774 if (regname == '-' && reg->y_type == kMTCharWise) { 775 Direction dir = BACKWARD; 776 if ((State & REPLACE_FLAG) != 0) { 777 pos_T curpos; 778 if (u_save_cursor() == FAIL) { 779 return FAIL; 780 } 781 del_chars(mb_charlen(reg->y_array[0].data), true); 782 curpos = curwin->w_cursor; 783 if (oneright() == FAIL) { 784 // hit end of line, need to put forward (after the current position) 785 dir = FORWARD; 786 } 787 curwin->w_cursor = curpos; 788 } 789 790 AppendCharToRedobuff(Ctrl_R); 791 AppendCharToRedobuff(regname); 792 do_put(regname, NULL, dir, 1, PUT_CURSEND); 793 } else { 794 stuffescaped(reg->y_array[i].data, literally); 795 // Insert a newline between lines and after last line if 796 // y_type is kMTLineWise. 797 if (reg->y_type == kMTLineWise || i < reg->y_size - 1) { 798 stuffcharReadbuff('\n'); 799 } 800 } 801 } 802 } 803 } 804 805 return retval; 806 } 807 808 /// If "regname" is a special register, return true and store a pointer to its 809 /// value in "argp". 810 /// 811 /// @param allocated return: true when value was allocated 812 /// @param errmsg give error message when failing 813 /// 814 /// @return true if "regname" is a special register, 815 bool get_spec_reg(int regname, char **argp, bool *allocated, bool errmsg) 816 { 817 *argp = NULL; 818 *allocated = false; 819 switch (regname) { 820 case '%': // file name 821 if (errmsg) { 822 check_fname(); // will give emsg if not set 823 } 824 *argp = curbuf->b_fname; 825 return true; 826 827 case '#': // alternate file name 828 *argp = getaltfname(errmsg); // may give emsg if not set 829 return true; 830 831 case '=': // result of expression 832 *argp = get_expr_line(); 833 *allocated = true; 834 return true; 835 836 case ':': // last command line 837 if (last_cmdline == NULL && errmsg) { 838 emsg(_(e_nolastcmd)); 839 } 840 *argp = last_cmdline; 841 return true; 842 843 case '/': // last search-pattern 844 if (last_search_pat() == NULL && errmsg) { 845 emsg(_(e_noprevre)); 846 } 847 *argp = last_search_pat(); 848 return true; 849 850 case '.': // last inserted text 851 *argp = get_last_insert_save(); 852 *allocated = true; 853 if (*argp == NULL && errmsg) { 854 emsg(_(e_noinstext)); 855 } 856 return true; 857 858 case Ctrl_F: // Filename under cursor 859 case Ctrl_P: // Path under cursor, expand via "path" 860 if (!errmsg) { 861 return false; 862 } 863 *argp = file_name_at_cursor(FNAME_MESS | FNAME_HYP | (regname == Ctrl_P ? FNAME_EXP : 0), 864 1, NULL); 865 *allocated = true; 866 return true; 867 868 case Ctrl_W: // word under cursor 869 case Ctrl_A: // WORD (mnemonic All) under cursor 870 if (!errmsg) { 871 return false; 872 } 873 size_t cnt = find_ident_under_cursor(argp, (regname == Ctrl_W 874 ? (FIND_IDENT|FIND_STRING) 875 : FIND_STRING)); 876 *argp = cnt ? xmemdupz(*argp, cnt) : NULL; 877 *allocated = true; 878 return true; 879 880 case Ctrl_L: // Line under cursor 881 if (!errmsg) { 882 return false; 883 } 884 885 *argp = ml_get_buf(curwin->w_buffer, curwin->w_cursor.lnum); 886 return true; 887 888 case '_': // black hole: always empty 889 *argp = ""; 890 return true; 891 } 892 893 return false; 894 } 895 896 /// Paste a yank register into the command line. 897 /// Only for non-special registers. 898 /// Used by CTRL-R in command-line mode. 899 /// insert_reg() can't be used here, because special characters from the 900 /// register contents will be interpreted as commands. 901 /// 902 /// @param regname Register name. 903 /// @param literally_arg Insert text literally instead of "as typed". 904 /// @param remcr When true, don't add CR characters. 905 /// 906 /// @returns FAIL for failure, OK otherwise 907 bool cmdline_paste_reg(int regname, bool literally_arg, bool remcr) 908 { 909 const bool literally = literally_arg || is_literal_register(regname); 910 911 yankreg_T *reg = get_yank_register(regname, YREG_PASTE); 912 if (reg->y_array == NULL) { 913 return FAIL; 914 } 915 916 for (size_t i = 0; i < reg->y_size; i++) { 917 cmdline_paste_str(reg->y_array[i].data, literally); 918 919 // Insert ^M between lines, unless `remcr` is true. 920 if (i < reg->y_size - 1 && !remcr) { 921 cmdline_paste_str("\r", literally); 922 } 923 924 // Check for CTRL-C, in case someone tries to paste a few thousand 925 // lines and gets bored. 926 os_breakcheck(); 927 if (got_int) { 928 return FAIL; 929 } 930 } 931 return OK; 932 } 933 934 /// Shift the delete registers: "9 is cleared, "8 becomes "9, etc. 935 void shift_delete_registers(bool y_append) 936 { 937 free_register(&y_regs[9]); // free register "9 938 for (int n = 9; n > 1; n--) { 939 y_regs[n] = y_regs[n - 1]; 940 } 941 if (!y_append) { 942 y_previous = &y_regs[1]; 943 } 944 y_regs[1].y_array = NULL; // set register "1 to empty 945 } 946 947 #if defined(EXITFREE) 948 void clear_registers(void) 949 { 950 for (int i = 0; i < NUM_REGISTERS; i++) { 951 free_register(&y_regs[i]); 952 } 953 } 954 #endif 955 956 /// Free contents of yankreg `reg`. 957 /// Called for normal freeing and in case of error. 958 /// 959 /// @param reg must not be NULL (but `reg->y_array` might be) 960 void free_register(yankreg_T *reg) 961 FUNC_ATTR_NONNULL_ALL 962 { 963 XFREE_CLEAR(reg->additional_data); 964 if (reg->y_array == NULL) { 965 return; 966 } 967 968 for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included 969 API_CLEAR_STRING(reg->y_array[i]); 970 } 971 XFREE_CLEAR(reg->y_array); 972 } 973 974 /// Copy a block range into a register. 975 /// 976 /// @param exclude_trailing_space if true, do not copy trailing whitespaces. 977 static void yank_copy_line(yankreg_T *reg, struct block_def *bd, size_t y_idx, 978 bool exclude_trailing_space) 979 FUNC_ATTR_NONNULL_ALL 980 { 981 if (exclude_trailing_space) { 982 bd->endspaces = 0; 983 } 984 int size = bd->startspaces + bd->endspaces + bd->textlen; 985 assert(size >= 0); 986 char *pnew = xmallocz((size_t)size); 987 reg->y_array[y_idx].data = pnew; 988 memset(pnew, ' ', (size_t)bd->startspaces); 989 pnew += bd->startspaces; 990 memmove(pnew, bd->textstart, (size_t)bd->textlen); 991 pnew += bd->textlen; 992 memset(pnew, ' ', (size_t)bd->endspaces); 993 pnew += bd->endspaces; 994 if (exclude_trailing_space) { 995 int s = bd->textlen + bd->endspaces; 996 997 while (s > 0 && ascii_iswhite(*(bd->textstart + s - 1))) { 998 s = s - utf_head_off(bd->textstart, bd->textstart + s - 1) - 1; 999 pnew--; 1000 } 1001 } 1002 *pnew = NUL; 1003 reg->y_array[y_idx].size = (size_t)(pnew - reg->y_array[y_idx].data); 1004 } 1005 1006 void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append) 1007 { 1008 yankreg_T newreg; // new yank register when appending 1009 MotionType yank_type = oap->motion_type; 1010 size_t yanklines = (size_t)oap->line_count; 1011 linenr_T yankendlnum = oap->end.lnum; 1012 struct block_def bd; 1013 1014 yankreg_T *curr = reg; // copy of current register 1015 // append to existing contents 1016 if (append && reg->y_array != NULL) { 1017 reg = &newreg; 1018 } else { 1019 free_register(reg); // free previously yanked lines 1020 } 1021 1022 // If the cursor was in column 1 before and after the movement, and the 1023 // operator is not inclusive, the yank is always linewise. 1024 if (oap->motion_type == kMTCharWise 1025 && oap->start.col == 0 1026 && !oap->inclusive 1027 && (!oap->is_VIsual || *p_sel == 'o') 1028 && oap->end.col == 0 1029 && yanklines > 1) { 1030 yank_type = kMTLineWise; 1031 yankendlnum--; 1032 yanklines--; 1033 } 1034 1035 reg->y_size = yanklines; 1036 reg->y_type = yank_type; // set the yank register type 1037 reg->y_width = 0; 1038 reg->y_array = xcalloc(yanklines, sizeof(String)); 1039 reg->additional_data = NULL; 1040 reg->timestamp = os_time(); 1041 1042 size_t y_idx = 0; // index in y_array[] 1043 linenr_T lnum = oap->start.lnum; // current line number 1044 1045 if (yank_type == kMTBlockWise) { 1046 // Visual block mode 1047 reg->y_width = oap->end_vcol - oap->start_vcol; 1048 1049 if (curwin->w_curswant == MAXCOL && reg->y_width > 0) { 1050 reg->y_width--; 1051 } 1052 } 1053 1054 for (; lnum <= yankendlnum; lnum++, y_idx++) { 1055 switch (reg->y_type) { 1056 case kMTBlockWise: 1057 block_prep(oap, &bd, lnum, false); 1058 yank_copy_line(reg, &bd, y_idx, oap->excl_tr_ws); 1059 break; 1060 1061 case kMTLineWise: 1062 reg->y_array[y_idx] = cbuf_to_string(ml_get(lnum), (size_t)ml_get_len(lnum)); 1063 break; 1064 1065 case kMTCharWise: 1066 charwise_block_prep(oap->start, oap->end, &bd, lnum, oap->inclusive); 1067 // make sure bd.textlen is not longer than the text 1068 int tmp = (int)strlen(bd.textstart); 1069 if (tmp < bd.textlen) { 1070 bd.textlen = tmp; 1071 } 1072 yank_copy_line(reg, &bd, y_idx, false); 1073 break; 1074 1075 // NOTREACHED 1076 case kMTUnknown: 1077 abort(); 1078 } 1079 } 1080 1081 if (curr != reg) { // append the new block to the old block 1082 size_t j; 1083 String *new_ptr = xmalloc(sizeof(String) * (curr->y_size + reg->y_size)); 1084 for (j = 0; j < curr->y_size; j++) { 1085 new_ptr[j] = curr->y_array[j]; 1086 } 1087 xfree(curr->y_array); 1088 curr->y_array = new_ptr; 1089 1090 if (yank_type == kMTLineWise) { 1091 // kMTLineWise overrides kMTCharWise and kMTBlockWise 1092 curr->y_type = kMTLineWise; 1093 } 1094 1095 // Concatenate the last line of the old block with the first line of 1096 // the new block, unless being Vi compatible. 1097 if (curr->y_type == kMTCharWise 1098 && vim_strchr(p_cpo, CPO_REGAPPEND) == NULL) { 1099 char *pnew = xmalloc(curr->y_array[curr->y_size - 1].size 1100 + reg->y_array[0].size + 1); 1101 j--; 1102 STRCPY(pnew, curr->y_array[j].data); 1103 STRCPY(pnew + curr->y_array[j].size, reg->y_array[0].data); 1104 xfree(curr->y_array[j].data); 1105 curr->y_array[j] = cbuf_as_string(pnew, 1106 curr->y_array[j].size + reg->y_array[0].size); 1107 j++; 1108 API_CLEAR_STRING(reg->y_array[0]); 1109 y_idx = 1; 1110 } else { 1111 y_idx = 0; 1112 } 1113 while (y_idx < reg->y_size) { 1114 curr->y_array[j++] = reg->y_array[y_idx++]; 1115 } 1116 curr->y_size = j; 1117 xfree(reg->y_array); 1118 } 1119 1120 if (message) { // Display message about yank? 1121 if (yank_type == kMTCharWise && yanklines == 1) { 1122 yanklines = 0; 1123 } 1124 // Some versions of Vi use ">=" here, some don't... 1125 if (yanklines > (size_t)p_report) { 1126 char namebuf[100]; 1127 1128 if (oap->regname == NUL) { 1129 *namebuf = NUL; 1130 } else { 1131 vim_snprintf(namebuf, sizeof(namebuf), _(" into \"%c"), oap->regname); 1132 } 1133 1134 // redisplay now, so message is not deleted 1135 update_topline(curwin); 1136 if (must_redraw) { 1137 update_screen(); 1138 } 1139 if (yank_type == kMTBlockWise) { 1140 smsg(0, NGETTEXT("block of %" PRId64 " line yanked%s", 1141 "block of %" PRId64 " lines yanked%s", yanklines), 1142 (int64_t)yanklines, namebuf); 1143 } else { 1144 smsg(0, NGETTEXT("%" PRId64 " line yanked%s", 1145 "%" PRId64 " lines yanked%s", yanklines), 1146 (int64_t)yanklines, namebuf); 1147 } 1148 } 1149 } 1150 1151 if ((cmdmod.cmod_flags & CMOD_LOCKMARKS) == 0) { 1152 // Set "'[" and "']" marks. 1153 curbuf->b_op_start = oap->start; 1154 curbuf->b_op_end = oap->end; 1155 if (yank_type == kMTLineWise) { 1156 curbuf->b_op_start.col = 0; 1157 curbuf->b_op_end.col = MAXCOL; 1158 } 1159 if (yank_type != kMTLineWise && !oap->inclusive) { 1160 // Exclude the end position. 1161 decl(&curbuf->b_op_end); 1162 } 1163 } 1164 } 1165 1166 /// Format the register type as a string. 1167 /// 1168 /// @param reg_type The register type. 1169 /// @param reg_width The width, only used if "reg_type" is kMTBlockWise. 1170 /// @param[out] buf Buffer to store formatted string. The allocated size should 1171 /// be at least NUMBUFLEN+2 to always fit the value. 1172 /// @param buf_len The allocated size of the buffer. 1173 void format_reg_type(MotionType reg_type, colnr_T reg_width, char *buf, size_t buf_len) 1174 FUNC_ATTR_NONNULL_ALL 1175 { 1176 assert(buf_len > 1); 1177 switch (reg_type) { 1178 case kMTLineWise: 1179 buf[0] = 'V'; 1180 buf[1] = NUL; 1181 break; 1182 case kMTCharWise: 1183 buf[0] = 'v'; 1184 buf[1] = NUL; 1185 break; 1186 case kMTBlockWise: 1187 snprintf(buf, buf_len, CTRL_V_STR "%" PRIdCOLNR, reg_width + 1); 1188 break; 1189 case kMTUnknown: 1190 buf[0] = NUL; 1191 break; 1192 } 1193 } 1194 1195 /// Execute autocommands for TextYankPost. 1196 /// 1197 /// @param oap Operator arguments. 1198 /// @param reg The yank register used. 1199 void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg) 1200 FUNC_ATTR_NONNULL_ALL 1201 { 1202 static bool recursive = false; 1203 1204 if (recursive || !has_event(EVENT_TEXTYANKPOST)) { 1205 // No autocommand was defined, or we yanked from this autocommand. 1206 return; 1207 } 1208 1209 recursive = true; 1210 1211 save_v_event_T save_v_event; 1212 // Set the v:event dictionary with information about the yank. 1213 dict_T *dict = get_v_event(&save_v_event); 1214 1215 // The yanked text contents. 1216 list_T *const list = tv_list_alloc((ptrdiff_t)reg->y_size); 1217 for (size_t i = 0; i < reg->y_size; i++) { 1218 tv_list_append_string(list, reg->y_array[i].data, (int)reg->y_array[i].size); 1219 } 1220 tv_list_set_lock(list, VAR_FIXED); 1221 tv_dict_add_list(dict, S_LEN("regcontents"), list); 1222 1223 // Register type. 1224 char buf[NUMBUFLEN + 2]; 1225 format_reg_type(reg->y_type, reg->y_width, buf, ARRAY_SIZE(buf)); 1226 tv_dict_add_str(dict, S_LEN("regtype"), buf); 1227 1228 // Name of requested register, or empty string for unnamed operation. 1229 buf[0] = (char)oap->regname; 1230 buf[1] = NUL; 1231 tv_dict_add_str(dict, S_LEN("regname"), buf); 1232 1233 // Motion type: inclusive or exclusive. 1234 tv_dict_add_bool(dict, S_LEN("inclusive"), 1235 oap->inclusive ? kBoolVarTrue : kBoolVarFalse); 1236 1237 // Kind of operation: yank, delete, change). 1238 buf[0] = (char)get_op_char(oap->op_type); 1239 buf[1] = NUL; 1240 tv_dict_add_str(dict, S_LEN("operator"), buf); 1241 1242 // Selection type: visual or not. 1243 tv_dict_add_bool(dict, S_LEN("visual"), 1244 oap->is_VIsual ? kBoolVarTrue : kBoolVarFalse); 1245 1246 tv_dict_set_keys_readonly(dict); 1247 textlock++; 1248 apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, false, curbuf); 1249 textlock--; 1250 restore_v_event(dict, &save_v_event); 1251 1252 recursive = false; 1253 } 1254 1255 /// Yanks the text between "oap->start" and "oap->end" into a yank register. 1256 /// If we are to append (uppercase register), we first yank into a new yank 1257 /// register and then concatenate the old and the new one. 1258 /// Do not call this from a delete operation. Use op_yank_reg() instead. 1259 /// 1260 /// @param oap operator arguments 1261 /// @param message show message when more than `&report` lines are yanked. 1262 /// @returns whether the operation register was writable. 1263 bool op_yank(oparg_T *oap, bool message) 1264 FUNC_ATTR_NONNULL_ALL 1265 { 1266 // check for read-only register 1267 if (oap->regname != 0 && !valid_yank_reg(oap->regname, true)) { 1268 beep_flush(); 1269 return false; 1270 } 1271 if (oap->regname == '_') { 1272 return true; // black hole: nothing to do 1273 } 1274 1275 yankreg_T *reg = get_yank_register(oap->regname, YREG_YANK); 1276 op_yank_reg(oap, message, reg, is_append_register(oap->regname)); 1277 set_clipboard(oap->regname, reg); 1278 do_autocmd_textyankpost(oap, reg); 1279 return true; 1280 } 1281 1282 /// Put contents of register "regname" into the text. 1283 /// Caller must check "regname" to be valid! 1284 /// 1285 /// @param flags PUT_FIXINDENT make indent look nice 1286 /// PUT_CURSEND leave cursor after end of new text 1287 /// PUT_LINE force linewise put (":put") 1288 /// PUT_BLOCK_INNER in block mode, do not add trailing spaces 1289 /// @param dir BACKWARD for 'P', FORWARD for 'p' 1290 void do_put(int regname, yankreg_T *reg, int dir, int count, int flags) 1291 { 1292 size_t totlen = 0; // init for gcc 1293 linenr_T lnum = 0; 1294 MotionType y_type; 1295 size_t y_size; 1296 int y_width = 0; 1297 colnr_T vcol = 0; 1298 String *y_array = NULL; 1299 linenr_T nr_lines = 0; 1300 bool allocated = false; 1301 const pos_T orig_start = curbuf->b_op_start; 1302 const pos_T orig_end = curbuf->b_op_end; 1303 unsigned cur_ve_flags = get_ve_flags(curwin); 1304 1305 // Remove any preinserted text (issue vim/vim#19329) 1306 if (ins_compl_preinsert_effect()) { 1307 ins_compl_delete(false); 1308 } 1309 1310 curbuf->b_op_start = curwin->w_cursor; // default for '[ mark 1311 curbuf->b_op_end = curwin->w_cursor; // default for '] mark 1312 1313 // Using inserted text works differently, because the register includes 1314 // special characters (newlines, etc.). 1315 if (regname == '.' && !reg) { 1316 bool non_linewise_vis = (VIsual_active && VIsual_mode != 'V'); 1317 1318 // PUT_LINE has special handling below which means we use 'i' to start. 1319 char command_start_char = non_linewise_vis 1320 ? 'c' 1321 : (flags & PUT_LINE ? 'i' : (dir == FORWARD ? 'a' : 'i')); 1322 1323 // To avoid 'autoindent' on linewise puts, create a new line with `:put _`. 1324 if (flags & PUT_LINE) { 1325 do_put('_', NULL, dir, 1, PUT_LINE); 1326 } 1327 1328 // If given a count when putting linewise, we stuff the readbuf with the 1329 // dot register 'count' times split by newlines. 1330 if (flags & PUT_LINE) { 1331 stuffcharReadbuff(command_start_char); 1332 for (; count > 0; count--) { 1333 stuff_inserted(NUL, 1, count != 1); 1334 if (count != 1) { 1335 // To avoid 'autoindent' affecting the text, use Ctrl_U to remove any 1336 // whitespace. Can't just insert Ctrl_U into readbuf1, this would go 1337 // back to the previous line in the case of 'noautoindent' and 1338 // 'backspace' includes "eol". So we insert a dummy space for Ctrl_U 1339 // to consume. 1340 stuffReadbuff("\n "); 1341 stuffcharReadbuff(Ctrl_U); 1342 } 1343 } 1344 } else { 1345 stuff_inserted(command_start_char, count, false); 1346 } 1347 1348 // Putting the text is done later, so can't move the cursor to the next 1349 // character. Simulate it with motion commands after the insert. 1350 if (flags & PUT_CURSEND) { 1351 if (flags & PUT_LINE) { 1352 stuffReadbuff("j0"); 1353 } else { 1354 // Avoid ringing the bell from attempting to move into the space after 1355 // the current line. We can stuff the readbuffer with "l" if: 1356 // 1) 'virtualedit' is "all" or "onemore" 1357 // 2) We are not at the end of the line 1358 // 3) We are not (one past the end of the line && on the last line) 1359 // This allows a visual put over a selection one past the end of the 1360 // line joining the current line with the one below. 1361 1362 // curwin->w_cursor.col marks the byte position of the cursor in the 1363 // currunt line. It increases up to a max of 1364 // strlen(ml_get(curwin->w_cursor.lnum)). With 'virtualedit' and the 1365 // cursor past the end of the line, curwin->w_cursor.coladd is 1366 // incremented instead of curwin->w_cursor.col. 1367 char *cursor_pos = get_cursor_pos_ptr(); 1368 bool one_past_line = (*cursor_pos == NUL); 1369 bool eol = false; 1370 if (!one_past_line) { 1371 eol = (*(cursor_pos + utfc_ptr2len(cursor_pos)) == NUL); 1372 } 1373 1374 bool ve_allows = (cur_ve_flags == kOptVeFlagAll || cur_ve_flags == kOptVeFlagOnemore); 1375 bool eof = curbuf->b_ml.ml_line_count == curwin->w_cursor.lnum 1376 && one_past_line; 1377 if (ve_allows || !(eol || eof)) { 1378 stuffcharReadbuff('l'); 1379 } 1380 } 1381 } else if (flags & PUT_LINE) { 1382 stuffReadbuff("g'["); 1383 } 1384 1385 // So the 'u' command restores cursor position after ".p, save the cursor 1386 // position now (though not saving any text). 1387 if (command_start_char == 'a') { 1388 if (u_save(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1) == FAIL) { 1389 return; 1390 } 1391 } 1392 return; 1393 } 1394 1395 // For special registers '%' (file name), '#' (alternate file name) and 1396 // ':' (last command line), etc. we have to create a fake yank register. 1397 String insert_string = STRING_INIT; 1398 if (!reg && get_spec_reg(regname, &insert_string.data, &allocated, true)) { 1399 if (insert_string.data == NULL) { 1400 return; 1401 } 1402 } 1403 1404 if (!curbuf->terminal) { 1405 // Autocommands may be executed when saving lines for undo. This might 1406 // make y_array invalid, so we start undo now to avoid that. 1407 if (u_save(curwin->w_cursor.lnum, curwin->w_cursor.lnum + 1) == FAIL) { 1408 return; 1409 } 1410 } 1411 1412 if (insert_string.data != NULL) { 1413 insert_string.size = strlen(insert_string.data); 1414 y_type = kMTCharWise; 1415 if (regname == '=') { 1416 // For the = register we need to split the string at NL 1417 // characters. 1418 // Loop twice: count the number of lines and save them. 1419 while (true) { 1420 y_size = 0; 1421 char *ptr = insert_string.data; 1422 size_t ptrlen = insert_string.size; 1423 while (ptr != NULL) { 1424 if (y_array != NULL) { 1425 y_array[y_size].data = ptr; 1426 } 1427 y_size++; 1428 char *tmp = vim_strchr(ptr, '\n'); 1429 if (tmp == NULL) { 1430 if (y_array != NULL) { 1431 y_array[y_size - 1].size = ptrlen; 1432 } 1433 } else { 1434 if (y_array != NULL) { 1435 *tmp = NUL; 1436 y_array[y_size - 1].size = (size_t)(tmp - ptr); 1437 ptrlen -= y_array[y_size - 1].size + 1; 1438 } 1439 tmp++; 1440 // A trailing '\n' makes the register linewise. 1441 if (*tmp == NUL) { 1442 y_type = kMTLineWise; 1443 break; 1444 } 1445 } 1446 ptr = tmp; 1447 } 1448 if (y_array != NULL) { 1449 break; 1450 } 1451 y_array = xmalloc(y_size * sizeof(String)); 1452 } 1453 } else { 1454 y_size = 1; // use fake one-line yank register 1455 y_array = &insert_string; 1456 } 1457 } else { 1458 // in case of replacing visually selected text 1459 // the yankreg might already have been saved to avoid 1460 // just restoring the deleted text. 1461 if (reg == NULL) { 1462 reg = get_yank_register(regname, YREG_PASTE); 1463 } 1464 1465 y_type = reg->y_type; 1466 y_width = reg->y_width; 1467 y_size = reg->y_size; 1468 y_array = reg->y_array; 1469 } 1470 1471 if (curbuf->terminal) { 1472 terminal_paste(count, y_array, y_size); 1473 return; 1474 } 1475 1476 colnr_T split_pos = 0; 1477 if (y_type == kMTLineWise) { 1478 if (flags & PUT_LINE_SPLIT) { 1479 // "p" or "P" in Visual mode: split the lines to put the text in 1480 // between. 1481 if (u_save_cursor() == FAIL) { 1482 goto end; 1483 } 1484 char *curline = get_cursor_line_ptr(); 1485 char *p = get_cursor_pos_ptr(); 1486 char *const p_orig = p; 1487 const size_t plen = (size_t)get_cursor_pos_len(); 1488 if (dir == FORWARD && *p != NUL) { 1489 MB_PTR_ADV(p); 1490 } 1491 // we need this later for the correct extmark_splice() event 1492 split_pos = (colnr_T)(p - curline); 1493 1494 char *ptr = xmemdupz(p, plen - (size_t)(p - p_orig)); 1495 ml_append(curwin->w_cursor.lnum, ptr, 0, false); 1496 xfree(ptr); 1497 1498 ptr = xmemdupz(get_cursor_line_ptr(), (size_t)split_pos); 1499 ml_replace(curwin->w_cursor.lnum, ptr, false); 1500 nr_lines++; 1501 dir = FORWARD; 1502 1503 buf_updates_send_changes(curbuf, curwin->w_cursor.lnum, 1, 1); 1504 } 1505 if (flags & PUT_LINE_FORWARD) { 1506 // Must be "p" for a Visual block, put lines below the block. 1507 curwin->w_cursor = curbuf->b_visual.vi_end; 1508 dir = FORWARD; 1509 } 1510 curbuf->b_op_start = curwin->w_cursor; // default for '[ mark 1511 curbuf->b_op_end = curwin->w_cursor; // default for '] mark 1512 } 1513 1514 if (flags & PUT_LINE) { // :put command or "p" in Visual line mode. 1515 y_type = kMTLineWise; 1516 } 1517 1518 if (y_size == 0 || y_array == NULL) { 1519 semsg(_("E353: Nothing in register %s"), 1520 regname == 0 ? "\"" : transchar(regname)); 1521 goto end; 1522 } 1523 1524 if (y_type == kMTBlockWise) { 1525 lnum = curwin->w_cursor.lnum + (linenr_T)y_size + 1; 1526 lnum = MIN(lnum, curbuf->b_ml.ml_line_count + 1); 1527 if (u_save(curwin->w_cursor.lnum - 1, lnum) == FAIL) { 1528 goto end; 1529 } 1530 } else if (y_type == kMTLineWise) { 1531 lnum = curwin->w_cursor.lnum; 1532 // Correct line number for closed fold. Don't move the cursor yet, 1533 // u_save() uses it. 1534 if (dir == BACKWARD) { 1535 hasFolding(curwin, lnum, &lnum, NULL); 1536 } else { 1537 hasFolding(curwin, lnum, NULL, &lnum); 1538 } 1539 if (dir == FORWARD) { 1540 lnum++; 1541 } 1542 // In an empty buffer the empty line is going to be replaced, include 1543 // it in the saved lines. 1544 if ((buf_is_empty(curbuf) 1545 ? u_save(0, 2) : u_save(lnum - 1, lnum)) == FAIL) { 1546 goto end; 1547 } 1548 if (dir == FORWARD) { 1549 curwin->w_cursor.lnum = lnum - 1; 1550 } else { 1551 curwin->w_cursor.lnum = lnum; 1552 } 1553 curbuf->b_op_start = curwin->w_cursor; // for mark_adjust() 1554 } else if (u_save_cursor() == FAIL) { 1555 goto end; 1556 } 1557 1558 if (cur_ve_flags == kOptVeFlagAll && y_type == kMTCharWise) { 1559 if (gchar_cursor() == TAB) { 1560 int viscol = getviscol(); 1561 OptInt ts = curbuf->b_p_ts; 1562 // Don't need to insert spaces when "p" on the last position of a 1563 // tab or "P" on the first position. 1564 if (dir == FORWARD 1565 ? tabstop_padding(viscol, ts, curbuf->b_p_vts_array) != 1 1566 : curwin->w_cursor.coladd > 0) { 1567 coladvance_force(viscol); 1568 } else { 1569 curwin->w_cursor.coladd = 0; 1570 } 1571 } else if (curwin->w_cursor.coladd > 0 || gchar_cursor() == NUL) { 1572 coladvance_force(getviscol() + (dir == FORWARD)); 1573 } 1574 } 1575 1576 lnum = curwin->w_cursor.lnum; 1577 colnr_T col = curwin->w_cursor.col; 1578 1579 // Block mode 1580 if (y_type == kMTBlockWise) { 1581 int incr = 0; 1582 struct block_def bd; 1583 int c = gchar_cursor(); 1584 colnr_T endcol2 = 0; 1585 1586 if (dir == FORWARD && c != NUL) { 1587 if (cur_ve_flags == kOptVeFlagAll) { 1588 getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2); 1589 } else { 1590 getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col); 1591 } 1592 1593 // move to start of next multi-byte character 1594 curwin->w_cursor.col += utfc_ptr2len(get_cursor_pos_ptr()); 1595 col++; 1596 } else { 1597 getvcol(curwin, &curwin->w_cursor, &col, NULL, &endcol2); 1598 } 1599 1600 col += curwin->w_cursor.coladd; 1601 if (cur_ve_flags == kOptVeFlagAll 1602 && (curwin->w_cursor.coladd > 0 || endcol2 == curwin->w_cursor.col)) { 1603 if (dir == FORWARD && c == NUL) { 1604 col++; 1605 } 1606 if (dir != FORWARD && c != NUL && curwin->w_cursor.coladd > 0) { 1607 curwin->w_cursor.col++; 1608 } 1609 if (c == TAB) { 1610 if (dir == BACKWARD && curwin->w_cursor.col) { 1611 curwin->w_cursor.col--; 1612 } 1613 if (dir == FORWARD && col - 1 == endcol2) { 1614 curwin->w_cursor.col++; 1615 } 1616 } 1617 } 1618 curwin->w_cursor.coladd = 0; 1619 bd.textcol = 0; 1620 for (size_t i = 0; i < y_size; i++) { 1621 int spaces = 0; 1622 char shortline; 1623 // can just be 0 or 1, needed for blockwise paste beyond the current 1624 // buffer end 1625 int lines_appended = 0; 1626 1627 bd.startspaces = 0; 1628 bd.endspaces = 0; 1629 vcol = 0; 1630 int delcount = 0; 1631 1632 // add a new line 1633 if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) { 1634 if (ml_append(curbuf->b_ml.ml_line_count, "", 1, false) == FAIL) { 1635 break; 1636 } 1637 nr_lines++; 1638 lines_appended = 1; 1639 } 1640 // get the old line and advance to the position to insert at 1641 char *oldp = get_cursor_line_ptr(); 1642 colnr_T oldlen = get_cursor_line_len(); 1643 1644 CharsizeArg csarg; 1645 CSType cstype = init_charsize_arg(&csarg, curwin, curwin->w_cursor.lnum, oldp); 1646 StrCharInfo ci = utf_ptr2StrCharInfo(oldp); 1647 vcol = 0; 1648 while (vcol < col && *ci.ptr != NUL) { 1649 incr = win_charsize(cstype, vcol, ci.ptr, ci.chr.value, &csarg).width; 1650 vcol += incr; 1651 ci = utfc_next(ci); 1652 } 1653 char *ptr = ci.ptr; 1654 bd.textcol = (colnr_T)(ptr - oldp); 1655 1656 shortline = (vcol < col) || (vcol == col && !*ptr); 1657 1658 if (vcol < col) { // line too short, pad with spaces 1659 bd.startspaces = col - vcol; 1660 } else if (vcol > col) { 1661 bd.endspaces = vcol - col; 1662 bd.startspaces = incr - bd.endspaces; 1663 bd.textcol--; 1664 delcount = 1; 1665 bd.textcol -= utf_head_off(oldp, oldp + bd.textcol); 1666 if (oldp[bd.textcol] != TAB) { 1667 // Only a Tab can be split into spaces. Other 1668 // characters will have to be moved to after the 1669 // block, causing misalignment. 1670 delcount = 0; 1671 bd.endspaces = 0; 1672 } 1673 } 1674 1675 const int yanklen = (int)y_array[i].size; 1676 1677 if ((flags & PUT_BLOCK_INNER) == 0) { 1678 // calculate number of spaces required to fill right side of block 1679 spaces = y_width + 1; 1680 1681 cstype = init_charsize_arg(&csarg, curwin, 0, y_array[i].data); 1682 ci = utf_ptr2StrCharInfo(y_array[i].data); 1683 while (*ci.ptr != NUL) { 1684 spaces -= win_charsize(cstype, 0, ci.ptr, ci.chr.value, &csarg).width; 1685 ci = utfc_next(ci); 1686 } 1687 spaces = MAX(spaces, 0); 1688 } 1689 1690 // Insert the new text. 1691 // First check for multiplication overflow. 1692 if (yanklen + spaces != 0 1693 && count > ((INT_MAX - (bd.startspaces + bd.endspaces)) / (yanklen + spaces))) { 1694 emsg(_(e_resulting_text_too_long)); 1695 break; 1696 } 1697 1698 totlen = (size_t)count * (size_t)(yanklen + spaces) + (size_t)bd.startspaces + 1699 (size_t)bd.endspaces; 1700 char *newp = xmalloc(totlen + (size_t)oldlen + 1); 1701 1702 // copy part up to cursor to new line 1703 ptr = newp; 1704 memmove(ptr, oldp, (size_t)bd.textcol); 1705 ptr += bd.textcol; 1706 1707 // may insert some spaces before the new text 1708 memset(ptr, ' ', (size_t)bd.startspaces); 1709 ptr += bd.startspaces; 1710 1711 // insert the new text 1712 for (int j = 0; j < count; j++) { 1713 memmove(ptr, y_array[i].data, (size_t)yanklen); 1714 ptr += yanklen; 1715 1716 // insert block's trailing spaces only if there's text behind 1717 if ((j < count - 1 || !shortline) && spaces > 0) { 1718 memset(ptr, ' ', (size_t)spaces); 1719 ptr += spaces; 1720 } else { 1721 totlen -= (size_t)spaces; // didn't use these spaces 1722 } 1723 } 1724 1725 // may insert some spaces after the new text 1726 memset(ptr, ' ', (size_t)bd.endspaces); 1727 ptr += bd.endspaces; 1728 1729 // move the text after the cursor to the end of the line. 1730 int columns = oldlen - bd.textcol - delcount + 1; 1731 assert(columns >= 0); 1732 memmove(ptr, oldp + bd.textcol + delcount, (size_t)columns); 1733 ml_replace(curwin->w_cursor.lnum, newp, false); 1734 extmark_splice_cols(curbuf, (int)curwin->w_cursor.lnum - 1, bd.textcol, 1735 delcount, (int)totlen + lines_appended, kExtmarkUndo); 1736 1737 curwin->w_cursor.lnum++; 1738 if (i == 0) { 1739 curwin->w_cursor.col += bd.startspaces; 1740 } 1741 } 1742 1743 changed_lines(curbuf, lnum, 0, curbuf->b_op_start.lnum + (linenr_T)y_size 1744 - nr_lines, nr_lines, true); 1745 1746 // Set '[ mark. 1747 curbuf->b_op_start = curwin->w_cursor; 1748 curbuf->b_op_start.lnum = lnum; 1749 1750 // adjust '] mark 1751 curbuf->b_op_end.lnum = curwin->w_cursor.lnum - 1; 1752 curbuf->b_op_end.col = MAX(bd.textcol + (colnr_T)totlen - 1, 0); 1753 curbuf->b_op_end.coladd = 0; 1754 if (flags & PUT_CURSEND) { 1755 curwin->w_cursor = curbuf->b_op_end; 1756 curwin->w_cursor.col++; 1757 1758 // in Insert mode we might be after the NUL, correct for that 1759 colnr_T len = get_cursor_line_len(); 1760 curwin->w_cursor.col = MIN(curwin->w_cursor.col, len); 1761 } else { 1762 curwin->w_cursor.lnum = lnum; 1763 } 1764 } else { 1765 const int yanklen = (int)y_array[0].size; 1766 1767 // Character or Line mode 1768 if (y_type == kMTCharWise) { 1769 // if type is kMTCharWise, FORWARD is the same as BACKWARD on the next 1770 // char 1771 if (dir == FORWARD && gchar_cursor() != NUL) { 1772 int bytelen = utfc_ptr2len(get_cursor_pos_ptr()); 1773 1774 // put it on the next of the multi-byte character. 1775 col += bytelen; 1776 if (yanklen) { 1777 curwin->w_cursor.col += bytelen; 1778 curbuf->b_op_end.col += bytelen; 1779 } 1780 } 1781 curbuf->b_op_start = curwin->w_cursor; 1782 } else if (dir == BACKWARD) { 1783 // Line mode: BACKWARD is the same as FORWARD on the previous line 1784 lnum--; 1785 } 1786 pos_T new_cursor = curwin->w_cursor; 1787 1788 // simple case: insert into one line at a time 1789 if (y_type == kMTCharWise && y_size == 1) { 1790 linenr_T end_lnum = 0; // init for gcc 1791 linenr_T start_lnum = lnum; 1792 int first_byte_off = 0; 1793 1794 if (VIsual_active) { 1795 end_lnum = MAX(curbuf->b_visual.vi_end.lnum, curbuf->b_visual.vi_start.lnum); 1796 if (end_lnum > start_lnum) { 1797 // "col" is valid for the first line, in following lines 1798 // the virtual column needs to be used. Matters for 1799 // multi-byte characters. 1800 pos_T pos = { 1801 .lnum = lnum, 1802 .col = col, 1803 .coladd = 0, 1804 }; 1805 getvcol(curwin, &pos, NULL, &vcol, NULL); 1806 } 1807 } 1808 1809 if (count == 0 || yanklen == 0) { 1810 if (VIsual_active) { 1811 lnum = end_lnum; 1812 } 1813 } else if (count > INT_MAX / yanklen) { 1814 // multiplication overflow 1815 emsg(_(e_resulting_text_too_long)); 1816 } else { 1817 totlen = (size_t)count * (size_t)yanklen; 1818 do { 1819 char *oldp = ml_get(lnum); 1820 colnr_T oldlen = ml_get_len(lnum); 1821 if (lnum > start_lnum) { 1822 pos_T pos = { 1823 .lnum = lnum, 1824 }; 1825 if (getvpos(curwin, &pos, vcol) == OK) { 1826 col = pos.col; 1827 } else { 1828 col = MAXCOL; 1829 } 1830 } 1831 if (VIsual_active && col > oldlen) { 1832 lnum++; 1833 continue; 1834 } 1835 char *newp = xmalloc(totlen + (size_t)oldlen + 1); 1836 memmove(newp, oldp, (size_t)col); 1837 char *ptr = newp + col; 1838 for (size_t i = 0; i < (size_t)count; i++) { 1839 memmove(ptr, y_array[0].data, (size_t)yanklen); 1840 ptr += yanklen; 1841 } 1842 memmove(ptr, oldp + col, (size_t)(oldlen - col) + 1); // +1 for NUL 1843 ml_replace(lnum, newp, false); 1844 1845 // compute the byte offset for the last character 1846 first_byte_off = utf_head_off(newp, ptr - 1); 1847 1848 // Place cursor on last putted char. 1849 if (lnum == curwin->w_cursor.lnum) { 1850 // make sure curwin->w_virtcol is updated 1851 changed_cline_bef_curs(curwin); 1852 invalidate_botline_win(curwin); 1853 curwin->w_cursor.col += (colnr_T)(totlen - 1); 1854 } 1855 changed_bytes(lnum, col); 1856 extmark_splice_cols(curbuf, (int)lnum - 1, col, 1857 0, (int)totlen, kExtmarkUndo); 1858 if (VIsual_active) { 1859 lnum++; 1860 } 1861 } while (VIsual_active && lnum <= end_lnum); 1862 1863 if (VIsual_active) { // reset lnum to the last visual line 1864 lnum--; 1865 } 1866 } 1867 1868 // put '] at the first byte of the last character 1869 curbuf->b_op_end = curwin->w_cursor; 1870 curbuf->b_op_end.col -= first_byte_off; 1871 1872 // For "CTRL-O p" in Insert mode, put cursor after last char 1873 if (totlen && (restart_edit != 0 || (flags & PUT_CURSEND))) { 1874 curwin->w_cursor.col++; 1875 } else { 1876 curwin->w_cursor.col -= first_byte_off; 1877 } 1878 } else { 1879 linenr_T new_lnum = new_cursor.lnum; 1880 int indent; 1881 int orig_indent = 0; 1882 int indent_diff = 0; // init for gcc 1883 bool first_indent = true; 1884 int lendiff = 0; 1885 1886 if (flags & PUT_FIXINDENT) { 1887 orig_indent = get_indent(); 1888 } 1889 1890 // Insert at least one line. When y_type is kMTCharWise, break the first 1891 // line in two. 1892 for (int cnt = 1; cnt <= count; cnt++) { 1893 size_t i = 0; 1894 if (y_type == kMTCharWise) { 1895 // Split the current line in two at the insert position. 1896 // First insert y_array[size - 1] in front of second line. 1897 // Then append y_array[0] to first line. 1898 lnum = new_cursor.lnum; 1899 char *ptr = ml_get(lnum) + col; 1900 size_t ptrlen = (size_t)ml_get_len(lnum) - (size_t)col; 1901 totlen = y_array[y_size - 1].size; 1902 char *newp = xmalloc(ptrlen + totlen + 1); 1903 STRCPY(newp, y_array[y_size - 1].data); 1904 STRCPY(newp + totlen, ptr); 1905 // insert second line 1906 ml_append(lnum, newp, 0, false); 1907 new_lnum++; 1908 xfree(newp); 1909 1910 char *oldp = ml_get(lnum); 1911 newp = xmalloc((size_t)col + (size_t)yanklen + 1); 1912 // copy first part of line 1913 memmove(newp, oldp, (size_t)col); 1914 // append to first line 1915 memmove(newp + col, y_array[0].data, (size_t)yanklen + 1); 1916 ml_replace(lnum, newp, false); 1917 1918 curwin->w_cursor.lnum = lnum; 1919 i = 1; 1920 } 1921 1922 for (; i < y_size; i++) { 1923 if ((y_type != kMTCharWise || i < y_size - 1)) { 1924 if (ml_append(lnum, y_array[i].data, 0, false) == FAIL) { 1925 goto error; 1926 } 1927 new_lnum++; 1928 } 1929 lnum++; 1930 nr_lines++; 1931 if (flags & PUT_FIXINDENT) { 1932 pos_T old_pos = curwin->w_cursor; 1933 curwin->w_cursor.lnum = lnum; 1934 char *ptr = ml_get(lnum); 1935 if (cnt == count && i == y_size - 1) { 1936 lendiff = ml_get_len(lnum); 1937 } 1938 if (*ptr == '#' && preprocs_left()) { 1939 indent = 0; // Leave # lines at start 1940 } else if (*ptr == NUL) { 1941 indent = 0; // Ignore empty lines 1942 } else if (first_indent) { 1943 indent_diff = orig_indent - get_indent(); 1944 indent = orig_indent; 1945 first_indent = false; 1946 } else if ((indent = get_indent() + indent_diff) < 0) { 1947 indent = 0; 1948 } 1949 set_indent(indent, SIN_NOMARK); 1950 curwin->w_cursor = old_pos; 1951 // remember how many chars were removed 1952 if (cnt == count && i == y_size - 1) { 1953 lendiff -= ml_get_len(lnum); 1954 } 1955 } 1956 } 1957 1958 bcount_t totsize = 0; 1959 int lastsize = 0; 1960 if (y_type == kMTCharWise 1961 || (y_type == kMTLineWise && (flags & PUT_LINE_SPLIT))) { 1962 for (i = 0; i < y_size - 1; i++) { 1963 totsize += (bcount_t)y_array[i].size + 1; 1964 } 1965 lastsize = (int)y_array[y_size - 1].size; 1966 totsize += lastsize; 1967 } 1968 if (y_type == kMTCharWise) { 1969 extmark_splice(curbuf, (int)new_cursor.lnum - 1, col, 0, 0, 0, 1970 (int)y_size - 1, lastsize, totsize, 1971 kExtmarkUndo); 1972 } else if (y_type == kMTLineWise && (flags & PUT_LINE_SPLIT)) { 1973 // Account for last pasted NL + last NL 1974 extmark_splice(curbuf, (int)new_cursor.lnum - 1, split_pos, 0, 0, 0, 1975 (int)y_size + 1, 0, totsize + 2, kExtmarkUndo); 1976 } 1977 1978 if (cnt == 1) { 1979 new_lnum = lnum; 1980 } 1981 } 1982 1983 error: 1984 // Adjust marks. 1985 if (y_type == kMTLineWise) { 1986 curbuf->b_op_start.col = 0; 1987 if (dir == FORWARD) { 1988 curbuf->b_op_start.lnum++; 1989 } 1990 } 1991 1992 ExtmarkOp kind = (y_type == kMTLineWise && !(flags & PUT_LINE_SPLIT)) 1993 ? kExtmarkUndo : kExtmarkNOOP; 1994 mark_adjust(curbuf->b_op_start.lnum + (y_type == kMTCharWise), 1995 (linenr_T)MAXLNUM, nr_lines, 0, kind); 1996 1997 // note changed text for displaying and folding 1998 if (y_type == kMTCharWise) { 1999 changed_lines(curbuf, curwin->w_cursor.lnum, col, 2000 curwin->w_cursor.lnum + 1, nr_lines, true); 2001 } else { 2002 changed_lines(curbuf, curbuf->b_op_start.lnum, 0, 2003 curbuf->b_op_start.lnum, nr_lines, true); 2004 } 2005 2006 // Put the '] mark on the first byte of the last inserted character. 2007 // Correct the length for change in indent. 2008 curbuf->b_op_end.lnum = new_lnum; 2009 col = MAX(0, (colnr_T)y_array[y_size - 1].size - lendiff); 2010 if (col > 1) { 2011 curbuf->b_op_end.col = col - 1; 2012 if (y_array[y_size - 1].size > 0) { 2013 curbuf->b_op_end.col -= utf_head_off(y_array[y_size - 1].data, 2014 y_array[y_size - 1].data 2015 + y_array[y_size - 1].size - 1); 2016 } 2017 } else { 2018 curbuf->b_op_end.col = 0; 2019 } 2020 2021 if (flags & PUT_CURSLINE) { 2022 // ":put": put cursor on last inserted line 2023 curwin->w_cursor.lnum = lnum; 2024 beginline(BL_WHITE | BL_FIX); 2025 } else if (flags & PUT_CURSEND) { 2026 // put cursor after inserted text 2027 if (y_type == kMTLineWise) { 2028 if (lnum >= curbuf->b_ml.ml_line_count) { 2029 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 2030 } else { 2031 curwin->w_cursor.lnum = lnum + 1; 2032 } 2033 curwin->w_cursor.col = 0; 2034 } else { 2035 curwin->w_cursor.lnum = new_lnum; 2036 curwin->w_cursor.col = col; 2037 curbuf->b_op_end = curwin->w_cursor; 2038 if (col > 1) { 2039 curbuf->b_op_end.col = col - 1; 2040 } 2041 } 2042 } else if (y_type == kMTLineWise) { 2043 // put cursor on first non-blank in first inserted line 2044 curwin->w_cursor.col = 0; 2045 if (dir == FORWARD) { 2046 curwin->w_cursor.lnum++; 2047 } 2048 beginline(BL_WHITE | BL_FIX); 2049 } else { // put cursor on first inserted character 2050 curwin->w_cursor = new_cursor; 2051 } 2052 } 2053 } 2054 2055 msgmore(nr_lines); 2056 curwin->w_set_curswant = true; 2057 2058 // Make sure the cursor is not after the NUL. 2059 int len = get_cursor_line_len(); 2060 if (curwin->w_cursor.col > len) { 2061 if (cur_ve_flags == kOptVeFlagAll) { 2062 curwin->w_cursor.coladd = curwin->w_cursor.col - len; 2063 } 2064 curwin->w_cursor.col = len; 2065 } 2066 2067 end: 2068 if (cmdmod.cmod_flags & CMOD_LOCKMARKS) { 2069 curbuf->b_op_start = orig_start; 2070 curbuf->b_op_end = orig_end; 2071 } 2072 if (allocated) { 2073 xfree(insert_string.data); 2074 } 2075 if (regname == '=') { 2076 xfree(y_array); 2077 } 2078 2079 VIsual_active = false; 2080 2081 // If the cursor is past the end of the line put it at the end. 2082 adjust_cursor_eol(); 2083 } 2084 2085 /// display a string for do_dis() 2086 /// truncate at end of screen line 2087 /// 2088 /// @param skip_esc if true, ignore trailing ESC 2089 static void dis_msg(const char *p, bool skip_esc) 2090 FUNC_ATTR_NONNULL_ALL 2091 { 2092 int n = Columns - 6; 2093 while (*p != NUL 2094 && !(*p == ESC && skip_esc && *(p + 1) == NUL) 2095 && (n -= ptr2cells(p)) >= 0) { 2096 int l; 2097 if ((l = utfc_ptr2len(p)) > 1) { 2098 msg_outtrans_len(p, l, 0, false); 2099 p += l; 2100 } else { 2101 msg_outtrans_len(p++, 1, 0, false); 2102 } 2103 } 2104 os_breakcheck(); 2105 } 2106 2107 /// ":dis" and ":registers": Display the contents of the yank registers. 2108 void ex_display(exarg_T *eap) 2109 { 2110 char *p; 2111 yankreg_T *yb; 2112 char *arg = eap->arg; 2113 int type; 2114 2115 if (arg != NULL && *arg == NUL) { 2116 arg = NULL; 2117 } 2118 int hl_id = HLF_8; 2119 2120 msg_ext_set_kind("list_cmd"); 2121 msg_ext_skip_flush = true; 2122 // Highlight title 2123 msg_puts_title(_("\nType Name Content")); 2124 for (int i = -1; i < NUM_REGISTERS && !got_int; i++) { 2125 int name = get_register_name(i); 2126 if (arg != NULL && vim_strchr(arg, name) == NULL) { 2127 continue; // did not ask for this register 2128 } 2129 2130 switch (get_reg_type(name, NULL)) { 2131 case kMTLineWise: 2132 type = 'l'; break; 2133 case kMTCharWise: 2134 type = 'c'; break; 2135 default: 2136 type = 'b'; break; 2137 } 2138 2139 if (i == -1) { 2140 if (y_previous != NULL) { 2141 yb = y_previous; 2142 } else { 2143 yb = &(y_regs[0]); 2144 } 2145 } else { 2146 yb = &(y_regs[i]); 2147 } 2148 2149 get_clipboard(name, &yb, true); 2150 2151 if (name == mb_tolower(redir_reg) 2152 || (redir_reg == '"' && yb == y_previous)) { 2153 continue; // do not list register being written to, the 2154 // pointer can be freed 2155 } 2156 2157 if (yb->y_array != NULL) { 2158 bool do_show = false; 2159 2160 for (size_t j = 0; !do_show && j < yb->y_size; j++) { 2161 do_show = !message_filtered(yb->y_array[j].data); 2162 } 2163 2164 if (do_show || yb->y_size == 0) { 2165 msg_putchar('\n'); 2166 msg_puts(" "); 2167 msg_putchar(type); 2168 msg_puts(" "); 2169 msg_putchar('"'); 2170 msg_putchar(name); 2171 msg_puts(" "); 2172 2173 int n = Columns - 11; 2174 for (size_t j = 0; j < yb->y_size && n > 1; j++) { 2175 if (j) { 2176 msg_puts_hl("^J", hl_id, false); 2177 n -= 2; 2178 } 2179 for (p = yb->y_array[j].data; 2180 *p != NUL && (n -= ptr2cells(p)) >= 0; p++) { 2181 int clen = utfc_ptr2len(p); 2182 msg_outtrans_len(p, clen, 0, false); 2183 p += clen - 1; 2184 } 2185 } 2186 if (n > 1 && yb->y_type == kMTLineWise) { 2187 msg_puts_hl("^J", hl_id, false); 2188 } 2189 } 2190 os_breakcheck(); 2191 } 2192 } 2193 2194 // display last inserted text 2195 String insert = get_last_insert(); 2196 if ((p = insert.data) != NULL 2197 && (arg == NULL || vim_strchr(arg, '.') != NULL) && !got_int 2198 && !message_filtered(p)) { 2199 msg_puts("\n c \". "); 2200 dis_msg(p, true); 2201 } 2202 2203 // display last command line 2204 if (last_cmdline != NULL && (arg == NULL || vim_strchr(arg, ':') != NULL) 2205 && !got_int && !message_filtered(last_cmdline)) { 2206 msg_puts("\n c \": "); 2207 dis_msg(last_cmdline, false); 2208 } 2209 2210 // display current file name 2211 if (curbuf->b_fname != NULL 2212 && (arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int 2213 && !message_filtered(curbuf->b_fname)) { 2214 msg_puts("\n c \"% "); 2215 dis_msg(curbuf->b_fname, false); 2216 } 2217 2218 // display alternate file name 2219 if ((arg == NULL || vim_strchr(arg, '%') != NULL) && !got_int) { 2220 char *fname; 2221 linenr_T dummy; 2222 2223 if (buflist_name_nr(0, &fname, &dummy) != FAIL && !message_filtered(fname)) { 2224 msg_puts("\n c \"# "); 2225 dis_msg(fname, false); 2226 } 2227 } 2228 2229 // display last search pattern 2230 if (last_search_pat() != NULL 2231 && (arg == NULL || vim_strchr(arg, '/') != NULL) && !got_int 2232 && !message_filtered(last_search_pat())) { 2233 msg_puts("\n c \"/ "); 2234 dis_msg(last_search_pat(), false); 2235 } 2236 2237 // display last used expression 2238 if (expr_line != NULL && (arg == NULL || vim_strchr(arg, '=') != NULL) 2239 && !got_int && !message_filtered(expr_line)) { 2240 msg_puts("\n c \"= "); 2241 dis_msg(expr_line, false); 2242 } 2243 msg_ext_skip_flush = false; 2244 } 2245 2246 /// Used for getregtype() 2247 /// 2248 /// @return the type of a register or 2249 /// kMTUnknown for error. 2250 MotionType get_reg_type(int regname, colnr_T *reg_width) 2251 { 2252 switch (regname) { 2253 case '%': // file name 2254 case '#': // alternate file name 2255 case '=': // expression 2256 case ':': // last command line 2257 case '/': // last search-pattern 2258 case '.': // last inserted text 2259 case Ctrl_F: // Filename under cursor 2260 case Ctrl_P: // Path under cursor, expand via "path" 2261 case Ctrl_W: // word under cursor 2262 case Ctrl_A: // WORD (mnemonic All) under cursor 2263 case '_': // black hole: always empty 2264 return kMTCharWise; 2265 } 2266 2267 if (regname != NUL && !valid_yank_reg(regname, false)) { 2268 return kMTUnknown; 2269 } 2270 2271 yankreg_T *reg = get_yank_register(regname, YREG_PASTE); 2272 2273 if (reg->y_array != NULL) { 2274 if (reg_width != NULL && reg->y_type == kMTBlockWise) { 2275 *reg_width = reg->y_width; 2276 } 2277 return reg->y_type; 2278 } 2279 return kMTUnknown; 2280 } 2281 2282 /// When `flags` has `kGRegList` return a list with text `s`. 2283 /// Otherwise just return `s`. 2284 /// 2285 /// @return a void * for use in get_reg_contents(). 2286 static void *get_reg_wrap_one_line(char *s, int flags) 2287 { 2288 if (!(flags & kGRegList)) { 2289 return s; 2290 } 2291 list_T *const list = tv_list_alloc(1); 2292 tv_list_append_allocated_string(list, s); 2293 return list; 2294 } 2295 2296 /// Gets the contents of a register. 2297 /// @remark Used for `@r` in expressions and for `getreg()`. 2298 /// 2299 /// @param regname The register. 2300 /// @param flags see @ref GRegFlags 2301 /// 2302 /// @returns The contents of the register as an allocated string. 2303 /// @returns A linked list when `flags` contains @ref kGRegList. 2304 /// @returns NULL for error. 2305 void *get_reg_contents(int regname, int flags) 2306 { 2307 // Don't allow using an expression register inside an expression. 2308 if (regname == '=') { 2309 if (flags & kGRegNoExpr) { 2310 return NULL; 2311 } 2312 if (flags & kGRegExprSrc) { 2313 return get_reg_wrap_one_line(get_expr_line_src(), flags); 2314 } 2315 return get_reg_wrap_one_line(get_expr_line(), flags); 2316 } 2317 2318 if (regname == '@') { // "@@" is used for unnamed register 2319 regname = '"'; 2320 } 2321 2322 // check for valid regname 2323 if (regname != NUL && !valid_yank_reg(regname, false)) { 2324 return NULL; 2325 } 2326 2327 char *retval; 2328 bool allocated; 2329 if (get_spec_reg(regname, &retval, &allocated, false)) { 2330 if (retval == NULL) { 2331 return NULL; 2332 } 2333 if (allocated) { 2334 return get_reg_wrap_one_line(retval, flags); 2335 } 2336 return get_reg_wrap_one_line(xstrdup(retval), flags); 2337 } 2338 2339 yankreg_T *reg = get_yank_register(regname, YREG_PUT); 2340 if (reg->y_array == NULL) { 2341 return NULL; 2342 } 2343 2344 if (flags & kGRegList) { 2345 list_T *const list = tv_list_alloc((ptrdiff_t)reg->y_size); 2346 for (size_t i = 0; i < reg->y_size; i++) { 2347 tv_list_append_string(list, reg->y_array[i].data, (int)reg->y_array[i].size); 2348 } 2349 2350 return list; 2351 } 2352 2353 // Compute length of resulting string. 2354 size_t len = 0; 2355 for (size_t i = 0; i < reg->y_size; i++) { 2356 len += reg->y_array[i].size; 2357 // Insert a newline between lines and after last line if y_type is kMTLineWise. 2358 if (reg->y_type == kMTLineWise || i < reg->y_size - 1) { 2359 len++; 2360 } 2361 } 2362 2363 retval = xmalloc(len + 1); 2364 2365 // Copy the lines of the yank register into the string. 2366 len = 0; 2367 for (size_t i = 0; i < reg->y_size; i++) { 2368 STRCPY(retval + len, reg->y_array[i].data); 2369 len += reg->y_array[i].size; 2370 2371 // Insert a newline between lines and after the last line if y_type is kMTLineWise. 2372 if (reg->y_type == kMTLineWise || i < reg->y_size - 1) { 2373 retval[len++] = '\n'; 2374 } 2375 } 2376 retval[len] = NUL; 2377 2378 return retval; 2379 } 2380 2381 static yankreg_T *init_write_reg(int name, yankreg_T **old_y_previous, bool must_append) 2382 { 2383 if (!valid_yank_reg(name, true)) { // check for valid reg name 2384 emsg_invreg(name); 2385 return NULL; 2386 } 2387 2388 // Don't want to change the current (unnamed) register. 2389 *old_y_previous = y_previous; 2390 2391 yankreg_T *reg = get_yank_register(name, YREG_YANK); 2392 if (!is_append_register(name) && !must_append) { 2393 free_register(reg); 2394 } 2395 return reg; 2396 } 2397 2398 /// str_to_reg - Put a string into a register. 2399 /// 2400 /// When the register is not empty, the string is appended. 2401 /// 2402 /// @param y_ptr pointer to yank register 2403 /// @param yank_type The motion type (kMTUnknown to auto detect) 2404 /// @param str string or list of strings to put in register 2405 /// @param len length of the string (Ignored when str_list=true.) 2406 /// @param blocklen width of visual block, or -1 for "I don't know." 2407 /// @param str_list True if str is `char **`. 2408 static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str, size_t len, 2409 colnr_T blocklen, bool str_list) 2410 FUNC_ATTR_NONNULL_ALL 2411 { 2412 if (y_ptr->y_array == NULL) { // NULL means empty register 2413 y_ptr->y_size = 0; 2414 } 2415 2416 if (yank_type == kMTUnknown) { 2417 yank_type = ((str_list 2418 || (len > 0 && (str[len - 1] == NL || str[len - 1] == CAR))) 2419 ? kMTLineWise : kMTCharWise); 2420 } 2421 2422 size_t newlines = 0; 2423 bool extraline = false; // extra line at the end 2424 bool append = false; // append to last line in register 2425 2426 // Count the number of lines within the string 2427 if (str_list) { 2428 for (char **ss = (char **)str; *ss != NULL; ss++) { 2429 newlines++; 2430 } 2431 } else { 2432 newlines = memcnt(str, '\n', len); 2433 if (yank_type == kMTCharWise || len == 0 || str[len - 1] != '\n') { 2434 extraline = 1; 2435 newlines++; // count extra newline at the end 2436 } 2437 if (y_ptr->y_size > 0 && y_ptr->y_type == kMTCharWise) { 2438 append = true; 2439 newlines--; // uncount newline when appending first line 2440 } 2441 } 2442 2443 // Without any lines make the register empty. 2444 if (y_ptr->y_size + newlines == 0) { 2445 XFREE_CLEAR(y_ptr->y_array); 2446 return; 2447 } 2448 2449 // Grow the register array to hold the pointers to the new lines. 2450 String *pp = xrealloc(y_ptr->y_array, (y_ptr->y_size + newlines) * sizeof(String)); 2451 y_ptr->y_array = pp; 2452 2453 size_t lnum = y_ptr->y_size; // The current line number. 2454 2455 // If called with `blocklen < 0`, we have to update the yank reg's width. 2456 size_t maxlen = 0; 2457 2458 // Find the end of each line and save it into the array. 2459 if (str_list) { 2460 for (char **ss = (char **)str; *ss != NULL; ss++, lnum++) { 2461 pp[lnum] = cstr_to_string(*ss); 2462 if (yank_type == kMTBlockWise) { 2463 size_t charlen = mb_string2cells(*ss); 2464 maxlen = MAX(maxlen, charlen); 2465 } 2466 } 2467 } else { 2468 size_t line_len; 2469 for (const char *start = str, *end = str + len; 2470 start < end + extraline; 2471 start += line_len + 1, lnum++) { 2472 int charlen = 0; 2473 2474 const char *line_end = start; 2475 while (line_end < end) { // find the end of the line 2476 if (*line_end == '\n') { 2477 break; 2478 } 2479 if (yank_type == kMTBlockWise) { 2480 charlen += utf_ptr2cells_len(line_end, (int)(end - line_end)); 2481 } 2482 2483 if (*line_end == NUL) { 2484 line_end++; // registers can have NUL chars 2485 } else { 2486 line_end += utf_ptr2len_len(line_end, (int)(end - line_end)); 2487 } 2488 } 2489 assert(line_end - start >= 0); 2490 line_len = (size_t)(line_end - start); 2491 maxlen = MAX(maxlen, (size_t)charlen); 2492 2493 // When appending, copy the previous line and free it after. 2494 size_t extra = append ? pp[--lnum].size : 0; 2495 char *s = xmallocz(line_len + extra); 2496 if (extra > 0) { 2497 memcpy(s, pp[lnum].data, extra); 2498 } 2499 if (line_len > 0) { 2500 memcpy(s + extra, start, line_len); 2501 } 2502 size_t s_len = extra + line_len; 2503 2504 if (append) { 2505 xfree(pp[lnum].data); 2506 append = false; // only first line is appended 2507 } 2508 pp[lnum] = cbuf_as_string(s, s_len); 2509 2510 // Convert NULs to '\n' to prevent truncation. 2511 memchrsub(pp[lnum].data, NUL, '\n', s_len); 2512 } 2513 } 2514 y_ptr->y_type = yank_type; 2515 y_ptr->y_size = lnum; 2516 XFREE_CLEAR(y_ptr->additional_data); 2517 y_ptr->timestamp = os_time(); 2518 if (yank_type == kMTBlockWise) { 2519 y_ptr->y_width = (blocklen == -1 ? (colnr_T)maxlen - 1 : blocklen); 2520 } else { 2521 y_ptr->y_width = 0; 2522 } 2523 } 2524 2525 static void finish_write_reg(int name, yankreg_T *reg, yankreg_T *old_y_previous) 2526 { 2527 // Send text of clipboard register to the clipboard. 2528 set_clipboard(name, reg); 2529 2530 // ':let @" = "val"' should change the meaning of the "" register 2531 if (name != '"') { 2532 y_previous = old_y_previous; 2533 } 2534 } 2535 2536 /// store `str` in register `name` 2537 /// 2538 /// @see write_reg_contents_ex 2539 void write_reg_contents(int name, const char *str, ssize_t len, int must_append) 2540 { 2541 write_reg_contents_ex(name, str, len, must_append, kMTUnknown, 0); 2542 } 2543 2544 void write_reg_contents_lst(int name, char **strings, bool must_append, MotionType yank_type, 2545 colnr_T block_len) 2546 { 2547 if (name == '/' || name == '=') { 2548 char *s = strings[0]; 2549 if (strings[0] == NULL) { 2550 s = ""; 2551 } else if (strings[1] != NULL) { 2552 emsg(_(e_search_pattern_and_expression_register_may_not_contain_two_or_more_lines)); 2553 return; 2554 } 2555 write_reg_contents_ex(name, s, -1, must_append, yank_type, block_len); 2556 return; 2557 } 2558 2559 // black hole: nothing to do 2560 if (name == '_') { 2561 return; 2562 } 2563 2564 yankreg_T *old_y_previous, *reg; 2565 if (!(reg = init_write_reg(name, &old_y_previous, must_append))) { 2566 return; 2567 } 2568 2569 str_to_reg(reg, yank_type, (char *)strings, strlen((char *)strings), 2570 block_len, true); 2571 finish_write_reg(name, reg, old_y_previous); 2572 } 2573 2574 /// write_reg_contents_ex - store `str` in register `name` 2575 /// 2576 /// If `str` ends in '\n' or '\r', use linewise, otherwise use charwise. 2577 /// 2578 /// @warning when `name` is '/', `len` and `must_append` are ignored. This 2579 /// means that `str` MUST be NUL-terminated. 2580 /// 2581 /// @param name The name of the register 2582 /// @param str The contents to write 2583 /// @param len If >= 0, write `len` bytes of `str`. Otherwise, write 2584 /// `strlen(str)` bytes. If `len` is larger than the 2585 /// allocated size of `src`, the behaviour is undefined. 2586 /// @param must_append If true, append the contents of `str` to the current 2587 /// contents of the register. Note that regardless of 2588 /// `must_append`, this function will append when `name` 2589 /// is an uppercase letter. 2590 /// @param yank_type The motion type (kMTUnknown to auto detect) 2591 /// @param block_len width of visual block 2592 void write_reg_contents_ex(int name, const char *str, ssize_t len, bool must_append, 2593 MotionType yank_type, colnr_T block_len) 2594 { 2595 if (len < 0) { 2596 len = (ssize_t)strlen(str); 2597 } 2598 2599 // Special case: '/' search pattern 2600 if (name == '/') { 2601 set_last_search_pat(str, RE_SEARCH, true, true); 2602 return; 2603 } 2604 2605 if (name == '#') { 2606 buf_T *buf; 2607 2608 if (ascii_isdigit(*str)) { 2609 int num = atoi(str); 2610 2611 buf = buflist_findnr(num); 2612 if (buf == NULL) { 2613 semsg(_(e_nobufnr), (int64_t)num); 2614 } 2615 } else { 2616 buf = buflist_findnr(buflist_findpat(str, str + len, true, false, false)); 2617 } 2618 if (buf == NULL) { 2619 return; 2620 } 2621 curwin->w_alt_fnum = buf->b_fnum; 2622 return; 2623 } 2624 2625 if (name == '=') { 2626 size_t offset = 0; 2627 size_t totlen = (size_t)len; 2628 2629 if (must_append && expr_line) { 2630 // append has been specified and expr_line already exists, so we'll 2631 // append the new string to expr_line. 2632 size_t exprlen = strlen(expr_line); 2633 2634 totlen += exprlen; 2635 offset = exprlen; 2636 } 2637 2638 // modify the global expr_line, extend/shrink it if necessary (realloc). 2639 // Copy the input string into the adjusted memory at the specified 2640 // offset. 2641 expr_line = xrealloc(expr_line, totlen + 1); 2642 memcpy(expr_line + offset, str, (size_t)len); 2643 expr_line[totlen] = NUL; 2644 2645 return; 2646 } 2647 2648 if (name == '_') { // black hole: nothing to do 2649 return; 2650 } 2651 2652 yankreg_T *old_y_previous, *reg; 2653 if (!(reg = init_write_reg(name, &old_y_previous, must_append))) { 2654 return; 2655 } 2656 str_to_reg(reg, yank_type, str, (size_t)len, block_len, false); 2657 finish_write_reg(name, reg, old_y_previous); 2658 } 2659 2660 /// @param[out] reg Expected to be empty 2661 bool prepare_yankreg_from_object(yankreg_T *reg, String regtype, size_t lines) 2662 { 2663 char type = regtype.data ? regtype.data[0] : NUL; 2664 2665 switch (type) { 2666 case 0: 2667 reg->y_type = kMTUnknown; 2668 break; 2669 case 'v': 2670 case 'c': 2671 reg->y_type = kMTCharWise; 2672 break; 2673 case 'V': 2674 case 'l': 2675 reg->y_type = kMTLineWise; 2676 break; 2677 case 'b': 2678 case Ctrl_V: 2679 reg->y_type = kMTBlockWise; 2680 break; 2681 default: 2682 return false; 2683 } 2684 2685 reg->y_width = 0; 2686 if (regtype.size > 1) { 2687 if (reg->y_type != kMTBlockWise) { 2688 return false; 2689 } 2690 2691 // allow "b7" for a block at least 7 spaces wide 2692 if (!ascii_isdigit(regtype.data[1])) { 2693 return false; 2694 } 2695 const char *p = regtype.data + 1; 2696 reg->y_width = getdigits_int((char **)&p, false, 1) - 1; 2697 if (regtype.size > (size_t)(p - regtype.data)) { 2698 return false; 2699 } 2700 } 2701 2702 reg->additional_data = NULL; 2703 reg->timestamp = 0; 2704 return true; 2705 } 2706 2707 void finish_yankreg_from_object(yankreg_T *reg, bool clipboard_adjust) 2708 { 2709 if (reg->y_size > 0 && reg->y_array[reg->y_size - 1].size == 0) { 2710 // a known-to-be charwise yank might have a final linebreak 2711 // but otherwise there is no line after the final newline 2712 if (reg->y_type != kMTCharWise) { 2713 if (reg->y_type == kMTUnknown || clipboard_adjust) { 2714 reg->y_size--; 2715 } 2716 if (reg->y_type == kMTUnknown) { 2717 reg->y_type = kMTLineWise; 2718 } 2719 } 2720 } else { 2721 if (reg->y_type == kMTUnknown) { 2722 reg->y_type = kMTCharWise; 2723 } 2724 } 2725 2726 update_yankreg_width(reg); 2727 }