To: vim_dev@googlegroups.com Subject: Patch 8.2.4950 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.4950 Problem: Text properties position wrong after shifting text. Solution: Adjust the text properties when shifting a block of text. (closes #10418) Files: src/ops.c, src/testdir/test_textprop.vim *** ../vim-8.2.4949/src/ops.c 2022-05-09 20:09:19.290641428 +0100 --- src/ops.c 2022-05-13 21:55:46.377099505 +0100 *************** *** 286,293 **** struct block_def bd; int incr; colnr_T ws_vcol; ! int i = 0, j = 0; ! int len; #ifdef FEAT_RIGHTLEFT int old_p_ri = p_ri; --- 286,294 ---- struct block_def bd; int incr; colnr_T ws_vcol; ! int added; ! unsigned new_line_len; // the length of the line after the ! // block shift #ifdef FEAT_RIGHTLEFT int old_p_ri = p_ri; *************** *** 308,313 **** --- 309,316 ---- if (!left) { + int tabs = 0, spaces = 0; + /* * 1. Get start vcol * 2. Total ws vcols *************** *** 343,371 **** #ifdef FEAT_VARTABS if (!curbuf->b_p_et) tabstop_fromto(ws_vcol, ws_vcol + total, ! ts_val, curbuf->b_p_vts_array, &i, &j); else ! j = total; #else if (!curbuf->b_p_et) ! i = ((ws_vcol % ts_val) + total) / ts_val; // number of tabs ! if (i) ! j = ((ws_vcol % ts_val) + total) % ts_val; // number of spp else ! j = total; #endif // if we're splitting a TAB, allow for it bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0); ! len = (int)STRLEN(bd.textstart) + 1; ! newp = alloc(bd.textcol + i + j + len); if (newp == NULL) return; - vim_memset(newp, NUL, (size_t)(bd.textcol + i + j + len)); mch_memmove(newp, oldp, (size_t)bd.textcol); ! vim_memset(newp + bd.textcol, TAB, (size_t)i); ! vim_memset(newp + bd.textcol + i, ' ', (size_t)j); ! // the end ! mch_memmove(newp + bd.textcol + i + j, bd.textstart, (size_t)len); } else // left { --- 346,374 ---- #ifdef FEAT_VARTABS if (!curbuf->b_p_et) tabstop_fromto(ws_vcol, ws_vcol + total, ! ts_val, curbuf->b_p_vts_array, &tabs, &spaces); else ! spaces = total; #else if (!curbuf->b_p_et) ! tabs = ((ws_vcol % ts_val) + total) / ts_val; // number of tabs ! if (tabs > 0) ! spaces = ((ws_vcol % ts_val) + total) % ts_val; // number of spp else ! spaces = total; #endif // if we're splitting a TAB, allow for it bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0); ! ! new_line_len = bd.textcol + tabs + spaces + (int)STRLEN(bd.textstart); ! newp = alloc(new_line_len + 1); if (newp == NULL) return; mch_memmove(newp, oldp, (size_t)bd.textcol); ! vim_memset(newp + bd.textcol, TAB, (size_t)tabs); ! vim_memset(newp + bd.textcol + tabs, ' ', (size_t)spaces); ! // Note that STRMOVE() copies the trailing NUL. ! STRMOVE(newp + bd.textcol + tabs + spaces, bd.textstart); } else // left { *************** *** 376,383 **** colnr_T verbatim_copy_width;// the (displayed) width of this part // of line unsigned fill; // nr of spaces that replace a TAB - unsigned new_line_len; // the length of the line after the - // block shift size_t block_space_width; size_t shift_amount; char_u *non_white = bd.textstart; --- 379,384 ---- *************** *** 448,465 **** // - the rest of the line, pointed to by non_white. new_line_len = (unsigned)(verbatim_copy_end - oldp) + fill ! + (unsigned)STRLEN(non_white) + 1; ! newp = alloc(new_line_len); if (newp == NULL) return; mch_memmove(newp, oldp, (size_t)(verbatim_copy_end - oldp)); vim_memset(newp + (verbatim_copy_end - oldp), ' ', (size_t)fill); STRMOVE(newp + (verbatim_copy_end - oldp) + fill, non_white); } // replace the line ml_replace(curwin->w_cursor.lnum, newp, FALSE); ! changed_bytes(curwin->w_cursor.lnum, bd.textcol); State = oldstate; curwin->w_cursor.col = oldcol; #ifdef FEAT_RIGHTLEFT --- 449,468 ---- // - the rest of the line, pointed to by non_white. new_line_len = (unsigned)(verbatim_copy_end - oldp) + fill ! + (unsigned)STRLEN(non_white); ! newp = alloc(new_line_len + 1); if (newp == NULL) return; mch_memmove(newp, oldp, (size_t)(verbatim_copy_end - oldp)); vim_memset(newp + (verbatim_copy_end - oldp), ' ', (size_t)fill); + // Note that STRMOVE() copies the trailing NUL. STRMOVE(newp + (verbatim_copy_end - oldp) + fill, non_white); } // replace the line + added = new_line_len - (int)STRLEN(oldp); ml_replace(curwin->w_cursor.lnum, newp, FALSE); ! inserted_bytes(curwin->w_cursor.lnum, bd.textcol, added); State = oldstate; curwin->w_cursor.col = oldcol; #ifdef FEAT_RIGHTLEFT *** ../vim-8.2.4949/src/testdir/test_textprop.vim 2022-05-13 12:41:39.469488941 +0100 --- src/testdir/test_textprop.vim 2022-05-13 21:48:25.837324296 +0100 *************** *** 1933,1937 **** --- 1933,1961 ---- bwipe! endfunc + func Test_prop_shift_block() + new + call AddPropTypes() + + call setline(1, ['some highlighted text']->repeat(2)) + call prop_add(1, 10, #{type: 'one', length: 11}) + call prop_add(2, 10, #{type: 'two', length: 11}) + + call cursor(1, 1) + call feedkeys("5l\>", 'nxt') + call cursor(2, 1) + call feedkeys("5l\<", 'nxt') + + let expected = [ + \ {'lnum': 1, 'id': 0, 'col': 8, 'type_bufnr': 0, 'end': 1, 'type': 'one', + \ 'length': 11, 'start' : 1}, + \ {'lnum': 2, 'id': 0, 'col': 6, 'type_bufnr': 0, 'end': 1, 'type': 'two', + \ 'length': 11, 'start' : 1} + \ ] + call assert_equal(expected, prop_list(1, #{end_lnum: 2})) + + call DeletePropTypes() + bwipe! + endfunc " vim: shiftwidth=2 sts=2 expandtab *** ../vim-8.2.4949/src/version.c 2022-05-13 16:23:33.797284090 +0100 --- src/version.c 2022-05-13 21:49:48.961281878 +0100 *************** *** 748,749 **** --- 748,751 ---- { /* Add new patch number below this line */ + /**/ + 4950, /**/ -- What is the difference between a professional and an amateur? The ark was built by an amateur; professionals gave us the Titanic. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///