comparison src/ops.c @ 16678:6f453673eb19 v8.1.1341

patch 8.1.1341: text properties are lost when joining lines commit https://github.com/vim/vim/commit/80e737cc6ab6b68948f6765348b6881be861b200 Author: Bram Moolenaar <Bram@vim.org> Date: Fri May 17 19:56:34 2019 +0200 patch 8.1.1341: text properties are lost when joining lines Problem: Text properties are lost when joining lines. Solution: Move the text properties to the joined line.
author Bram Moolenaar <Bram@vim.org>
date Fri, 17 May 2019 20:00:06 +0200
parents a1229400434a
children c263acbbd961
comparison
equal deleted inserted replaced
16677:9e2b1e449579 16678:6f453673eb19
1209 long i; 1209 long i;
1210 char_u *p; 1210 char_u *p;
1211 int retval = OK; 1211 int retval = OK;
1212 int remap; 1212 int remap;
1213 1213
1214 if (regname == '@') /* repeat previous one */ 1214 // repeat previous one
1215 if (regname == '@')
1215 { 1216 {
1216 if (execreg_lastc == NUL) 1217 if (execreg_lastc == NUL)
1217 { 1218 {
1218 emsg(_("E748: No previously used register")); 1219 emsg(_("E748: No previously used register"));
1219 return FAIL; 1220 return FAIL;
1220 } 1221 }
1221 regname = execreg_lastc; 1222 regname = execreg_lastc;
1222 } 1223 }
1223 /* check for valid regname */ 1224 // check for valid regname
1224 if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE)) 1225 if (regname == '%' || regname == '#' || !valid_yank_reg(regname, FALSE))
1225 { 1226 {
1226 emsg_invreg(regname); 1227 emsg_invreg(regname);
1227 return FAIL; 1228 return FAIL;
1228 } 1229 }
1230 1231
1231 #ifdef FEAT_CLIPBOARD 1232 #ifdef FEAT_CLIPBOARD
1232 regname = may_get_selection(regname); 1233 regname = may_get_selection(regname);
1233 #endif 1234 #endif
1234 1235
1235 if (regname == '_') /* black hole: don't stuff anything */ 1236 // black hole: don't stuff anything
1237 if (regname == '_')
1236 return OK; 1238 return OK;
1237 1239
1238 #ifdef FEAT_CMDHIST 1240 #ifdef FEAT_CMDHIST
1239 if (regname == ':') /* use last command line */ 1241 // use last command line
1242 if (regname == ':')
1240 { 1243 {
1241 if (last_cmdline == NULL) 1244 if (last_cmdline == NULL)
1242 { 1245 {
1243 emsg(_(e_nolastcmd)); 1246 emsg(_(e_nolastcmd));
1244 return FAIL; 1247 return FAIL;
4436 int *comments = NULL; 4439 int *comments = NULL;
4437 int remove_comments = (use_formatoptions == TRUE) 4440 int remove_comments = (use_formatoptions == TRUE)
4438 && has_format_option(FO_REMOVE_COMS); 4441 && has_format_option(FO_REMOVE_COMS);
4439 int prev_was_comment; 4442 int prev_was_comment;
4440 #endif 4443 #endif
4441 4444 #ifdef FEAT_TEXT_PROP
4445 textprop_T **prop_lines = NULL;
4446 int *prop_lengths = NULL;
4447 #endif
4442 4448
4443 if (save_undo && u_save((linenr_T)(curwin->w_cursor.lnum - 1), 4449 if (save_undo && u_save((linenr_T)(curwin->w_cursor.lnum - 1),
4444 (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL) 4450 (linenr_T)(curwin->w_cursor.lnum + count)) == FAIL)
4445 return FAIL; 4451 return FAIL;
4446 4452
4461 } 4467 }
4462 } 4468 }
4463 #endif 4469 #endif
4464 4470
4465 /* 4471 /*
4466 * Don't move anything, just compute the final line length 4472 * Don't move anything yet, just compute the final line length
4467 * and setup the array of space strings lengths 4473 * and setup the array of space strings lengths
4474 * This loops forward over the joined lines.
4468 */ 4475 */
4469 for (t = 0; t < count; ++t) 4476 for (t = 0; t < count; ++t)
4470 { 4477 {
4471 curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t)); 4478 curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t));
4472 if (t == 0 && setmark) 4479 if (t == 0 && setmark)
4554 /* allocate the space for the new line */ 4561 /* allocate the space for the new line */
4555 newp = alloc_check((unsigned)(sumsize + 1)); 4562 newp = alloc_check((unsigned)(sumsize + 1));
4556 cend = newp + sumsize; 4563 cend = newp + sumsize;
4557 *cend = 0; 4564 *cend = 0;
4558 4565
4566 #ifdef FEAT_TEXT_PROP
4567 // We need to move properties of the lines that are going to be deleted to
4568 // the new long one.
4569 if (curbuf->b_has_textprop && !text_prop_frozen)
4570 {
4571 // Allocate an array to copy the text properties of joined lines into.
4572 // And another array to store the number of properties in each line.
4573 prop_lines = (textprop_T **)alloc_clear(
4574 (int)(count - 1) * sizeof(textprop_T *));
4575 prop_lengths = (int *)alloc_clear((int)(count - 1) * sizeof(int));
4576 if (prop_lengths == NULL)
4577 VIM_CLEAR(prop_lines);
4578 }
4579 #endif
4580
4559 /* 4581 /*
4560 * Move affected lines to the new long one. 4582 * Move affected lines to the new long one.
4583 * This loops backwards over the joined lines, including the original line.
4561 * 4584 *
4562 * Move marks from each deleted line to the joined line, adjusting the 4585 * Move marks from each deleted line to the joined line, adjusting the
4563 * column. This is not Vi compatible, but Vi deletes the marks, thus that 4586 * column. This is not Vi compatible, but Vi deletes the marks, thus that
4564 * should not really be a problem. 4587 * should not really be a problem.
4565 */ 4588 */
4581 4604
4582 mark_col_adjust(curwin->w_cursor.lnum + t, (colnr_T)0, (linenr_T)-t, 4605 mark_col_adjust(curwin->w_cursor.lnum + t, (colnr_T)0, (linenr_T)-t,
4583 (long)(cend - newp - spaces_removed), spaces_removed); 4606 (long)(cend - newp - spaces_removed), spaces_removed);
4584 if (t == 0) 4607 if (t == 0)
4585 break; 4608 break;
4609 #ifdef FEAT_TEXT_PROP
4610 if (prop_lines != NULL)
4611 adjust_props_for_join(curwin->w_cursor.lnum + t,
4612 prop_lines + t - 1, prop_lengths + t - 1,
4613 (long)(cend - newp - spaces_removed), spaces_removed);
4614 #endif
4615
4586 curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1)); 4616 curr = curr_start = ml_get((linenr_T)(curwin->w_cursor.lnum + t - 1));
4587 #if defined(FEAT_COMMENTS) || defined(PROTO) 4617 #if defined(FEAT_COMMENTS)
4588 if (remove_comments) 4618 if (remove_comments)
4589 curr += comments[t - 1]; 4619 curr += comments[t - 1];
4590 #endif 4620 #endif
4591 if (insert_space && t > 1) 4621 if (insert_space && t > 1)
4592 curr = skipwhite(curr); 4622 curr = skipwhite(curr);
4593 currsize = (int)STRLEN(curr); 4623 currsize = (int)STRLEN(curr);
4594 } 4624 }
4595 ml_replace(curwin->w_cursor.lnum, newp, FALSE); 4625
4626 #ifdef FEAT_TEXT_PROP
4627 if (prop_lines != NULL)
4628 join_prop_lines(curwin->w_cursor.lnum, newp,
4629 prop_lines, prop_lengths, count);
4630 else
4631 #endif
4632 ml_replace(curwin->w_cursor.lnum, newp, FALSE);
4596 4633
4597 if (setmark) 4634 if (setmark)
4598 { 4635 {
4599 /* Set the '] mark. */ 4636 /* Set the '] mark. */
4600 curwin->w_buffer->b_op_end.lnum = curwin->w_cursor.lnum; 4637 curwin->w_buffer->b_op_end.lnum = curwin->w_cursor.lnum;
4603 4640
4604 /* Only report the change in the first line here, del_lines() will report 4641 /* Only report the change in the first line here, del_lines() will report
4605 * the deleted line. */ 4642 * the deleted line. */
4606 changed_lines(curwin->w_cursor.lnum, currsize, 4643 changed_lines(curwin->w_cursor.lnum, currsize,
4607 curwin->w_cursor.lnum + 1, 0L); 4644 curwin->w_cursor.lnum + 1, 0L);
4608
4609 /* 4645 /*
4610 * Delete following lines. To do this we move the cursor there 4646 * Delete following lines. To do this we move the cursor there
4611 * briefly, and then move it back. After del_lines() the cursor may 4647 * briefly, and then move it back. After del_lines() the cursor may
4612 * have moved up (last line deleted), so the current lnum is kept in t. 4648 * have moved up (last line deleted), so the current lnum is kept in t.
4613 */ 4649 */