Mercurial > vim
comparison src/ops.c @ 28854:647d7f439622 v8.2.4950
patch 8.2.4950: text properties position wrong after shifting text
Commit: https://github.com/vim/vim/commit/4b93674159d60c985de906c30f45dbaf2b64056f
Author: LemonBoy <thatlemon@gmail.com>
Date: Fri May 13 21:56:28 2022 +0100
patch 8.2.4950: text properties position wrong after shifting text
Problem: Text properties position wrong after shifting text.
Solution: Adjust the text properties when shifting a block of text.
(closes #10418)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 13 May 2022 23:00:03 +0200 |
parents | d0241e74bfdb |
children | 948877671c54 |
comparison
equal
deleted
inserted
replaced
28853:e397a7fd7fc1 | 28854:647d7f439622 |
---|---|
284 int sw_val = (int)get_sw_value_indent(curbuf); | 284 int sw_val = (int)get_sw_value_indent(curbuf); |
285 int ts_val = (int)curbuf->b_p_ts; | 285 int ts_val = (int)curbuf->b_p_ts; |
286 struct block_def bd; | 286 struct block_def bd; |
287 int incr; | 287 int incr; |
288 colnr_T ws_vcol; | 288 colnr_T ws_vcol; |
289 int i = 0, j = 0; | 289 int added; |
290 int len; | 290 unsigned new_line_len; // the length of the line after the |
291 // block shift | |
291 #ifdef FEAT_RIGHTLEFT | 292 #ifdef FEAT_RIGHTLEFT |
292 int old_p_ri = p_ri; | 293 int old_p_ri = p_ri; |
293 | 294 |
294 p_ri = 0; // don't want revins in indent | 295 p_ri = 0; // don't want revins in indent |
295 #endif | 296 #endif |
306 | 307 |
307 oldp = ml_get_curline(); | 308 oldp = ml_get_curline(); |
308 | 309 |
309 if (!left) | 310 if (!left) |
310 { | 311 { |
312 int tabs = 0, spaces = 0; | |
313 | |
311 /* | 314 /* |
312 * 1. Get start vcol | 315 * 1. Get start vcol |
313 * 2. Total ws vcols | 316 * 2. Total ws vcols |
314 * 3. Divvy into TABs & spp | 317 * 3. Divvy into TABs & spp |
315 * 4. Construct new string | 318 * 4. Construct new string |
341 // OK, now total=all the VWS reqd, and textstart points at the 1st | 344 // OK, now total=all the VWS reqd, and textstart points at the 1st |
342 // non-ws char in the block. | 345 // non-ws char in the block. |
343 #ifdef FEAT_VARTABS | 346 #ifdef FEAT_VARTABS |
344 if (!curbuf->b_p_et) | 347 if (!curbuf->b_p_et) |
345 tabstop_fromto(ws_vcol, ws_vcol + total, | 348 tabstop_fromto(ws_vcol, ws_vcol + total, |
346 ts_val, curbuf->b_p_vts_array, &i, &j); | 349 ts_val, curbuf->b_p_vts_array, &tabs, &spaces); |
347 else | 350 else |
348 j = total; | 351 spaces = total; |
349 #else | 352 #else |
350 if (!curbuf->b_p_et) | 353 if (!curbuf->b_p_et) |
351 i = ((ws_vcol % ts_val) + total) / ts_val; // number of tabs | 354 tabs = ((ws_vcol % ts_val) + total) / ts_val; // number of tabs |
352 if (i) | 355 if (tabs > 0) |
353 j = ((ws_vcol % ts_val) + total) % ts_val; // number of spp | 356 spaces = ((ws_vcol % ts_val) + total) % ts_val; // number of spp |
354 else | 357 else |
355 j = total; | 358 spaces = total; |
356 #endif | 359 #endif |
357 // if we're splitting a TAB, allow for it | 360 // if we're splitting a TAB, allow for it |
358 bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0); | 361 bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0); |
359 len = (int)STRLEN(bd.textstart) + 1; | 362 |
360 newp = alloc(bd.textcol + i + j + len); | 363 new_line_len = bd.textcol + tabs + spaces + (int)STRLEN(bd.textstart); |
364 newp = alloc(new_line_len + 1); | |
361 if (newp == NULL) | 365 if (newp == NULL) |
362 return; | 366 return; |
363 vim_memset(newp, NUL, (size_t)(bd.textcol + i + j + len)); | |
364 mch_memmove(newp, oldp, (size_t)bd.textcol); | 367 mch_memmove(newp, oldp, (size_t)bd.textcol); |
365 vim_memset(newp + bd.textcol, TAB, (size_t)i); | 368 vim_memset(newp + bd.textcol, TAB, (size_t)tabs); |
366 vim_memset(newp + bd.textcol + i, ' ', (size_t)j); | 369 vim_memset(newp + bd.textcol + tabs, ' ', (size_t)spaces); |
367 // the end | 370 // Note that STRMOVE() copies the trailing NUL. |
368 mch_memmove(newp + bd.textcol + i + j, bd.textstart, (size_t)len); | 371 STRMOVE(newp + bd.textcol + tabs + spaces, bd.textstart); |
369 } | 372 } |
370 else // left | 373 else // left |
371 { | 374 { |
372 colnr_T destination_col; // column to which text in block will | 375 colnr_T destination_col; // column to which text in block will |
373 // be shifted | 376 // be shifted |
374 char_u *verbatim_copy_end; // end of the part of the line which is | 377 char_u *verbatim_copy_end; // end of the part of the line which is |
375 // copied verbatim | 378 // copied verbatim |
376 colnr_T verbatim_copy_width;// the (displayed) width of this part | 379 colnr_T verbatim_copy_width;// the (displayed) width of this part |
377 // of line | 380 // of line |
378 unsigned fill; // nr of spaces that replace a TAB | 381 unsigned fill; // nr of spaces that replace a TAB |
379 unsigned new_line_len; // the length of the line after the | |
380 // block shift | |
381 size_t block_space_width; | 382 size_t block_space_width; |
382 size_t shift_amount; | 383 size_t shift_amount; |
383 char_u *non_white = bd.textstart; | 384 char_u *non_white = bd.textstart; |
384 colnr_T non_white_col; | 385 colnr_T non_white_col; |
385 | 386 |
446 // - the beginning of the original line up to "verbatim_copy_end", | 447 // - the beginning of the original line up to "verbatim_copy_end", |
447 // - "fill" number of spaces, | 448 // - "fill" number of spaces, |
448 // - the rest of the line, pointed to by non_white. | 449 // - the rest of the line, pointed to by non_white. |
449 new_line_len = (unsigned)(verbatim_copy_end - oldp) | 450 new_line_len = (unsigned)(verbatim_copy_end - oldp) |
450 + fill | 451 + fill |
451 + (unsigned)STRLEN(non_white) + 1; | 452 + (unsigned)STRLEN(non_white); |
452 | 453 |
453 newp = alloc(new_line_len); | 454 newp = alloc(new_line_len + 1); |
454 if (newp == NULL) | 455 if (newp == NULL) |
455 return; | 456 return; |
456 mch_memmove(newp, oldp, (size_t)(verbatim_copy_end - oldp)); | 457 mch_memmove(newp, oldp, (size_t)(verbatim_copy_end - oldp)); |
457 vim_memset(newp + (verbatim_copy_end - oldp), ' ', (size_t)fill); | 458 vim_memset(newp + (verbatim_copy_end - oldp), ' ', (size_t)fill); |
459 // Note that STRMOVE() copies the trailing NUL. | |
458 STRMOVE(newp + (verbatim_copy_end - oldp) + fill, non_white); | 460 STRMOVE(newp + (verbatim_copy_end - oldp) + fill, non_white); |
459 } | 461 } |
460 // replace the line | 462 // replace the line |
463 added = new_line_len - (int)STRLEN(oldp); | |
461 ml_replace(curwin->w_cursor.lnum, newp, FALSE); | 464 ml_replace(curwin->w_cursor.lnum, newp, FALSE); |
462 changed_bytes(curwin->w_cursor.lnum, bd.textcol); | 465 inserted_bytes(curwin->w_cursor.lnum, bd.textcol, added); |
463 State = oldstate; | 466 State = oldstate; |
464 curwin->w_cursor.col = oldcol; | 467 curwin->w_cursor.col = oldcol; |
465 #ifdef FEAT_RIGHTLEFT | 468 #ifdef FEAT_RIGHTLEFT |
466 p_ri = old_p_ri; | 469 p_ri = old_p_ri; |
467 #endif | 470 #endif |