To: vim_dev@googlegroups.com Subject: Patch 9.0.0697 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.0697 Problem: Cursor in wrong position with Visual substitute. Solution: When restoring 'linebreak' mark the virtual column as invalid. (closes #11309, closes #11311) Files: src/ops.c, src/testdir/test_visual.vim, src/testdir/test_listlbr.vim, src/testdir/dumps/Test_linebreak_reset_restore_1.dump *** ../vim-9.0.0696/src/ops.c 2022-09-16 22:16:54.404074904 +0100 --- src/ops.c 2022-10-08 16:39:35.327858697 +0100 *************** *** 2208,2213 **** --- 2208,2242 ---- } /* + * Reset 'linebreak' and take care of side effects. + * Returns the previous value, to be passed to restore_lbr(). + */ + static int + reset_lbr(void) + { + if (!curwin->w_p_lbr) + return FALSE; + // changing 'linebreak' may require w_virtcol to be updated + curwin->w_p_lbr = FALSE; + curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL); + return TRUE; + } + + /* + * Restore 'linebreak' and take care of side effects. + */ + static void + restore_lbr(int lbr_saved) + { + if (!curwin->w_p_lbr && lbr_saved) + { + // changing 'linebreak' may require w_virtcol to be updated + curwin->w_p_lbr = TRUE; + curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL); + } + } + + /* * prepare a few things for block mode yank/delete/tilde * * for delete: *************** *** 2235,2245 **** char_u *prev_pend; chartabsize_T cts; #ifdef FEAT_LINEBREAK ! int lbr_saved = curwin->w_p_lbr; ! ! // Avoid a problem with unwanted linebreaks in block mode. ! curwin->w_p_lbr = FALSE; #endif bdp->startspaces = 0; bdp->endspaces = 0; bdp->textlen = 0; --- 2264,2273 ---- char_u *prev_pend; chartabsize_T cts; #ifdef FEAT_LINEBREAK ! // Avoid a problem with unwanted linebreaks in block mode. ! int lbr_saved = reset_lbr(); #endif + bdp->startspaces = 0; bdp->endspaces = 0; bdp->textlen = 0; *************** *** 2369,2375 **** bdp->textcol = (colnr_T) (pstart - line); bdp->textstart = pstart; #ifdef FEAT_LINEBREAK ! curwin->w_p_lbr = lbr_saved; #endif } --- 2397,2403 ---- bdp->textcol = (colnr_T) (pstart - line); bdp->textstart = pstart; #ifdef FEAT_LINEBREAK ! restore_lbr(lbr_saved); #endif } *************** *** 3570,3578 **** #ifdef FEAT_LINEBREAK // Avoid a problem with unwanted linebreaks in block mode. ! if (curwin->w_p_lbr) ! curwin->w_valid &= ~VALID_VIRTCOL; ! curwin->w_p_lbr = FALSE; #endif oap->is_VIsual = VIsual_active; if (oap->motion_force == 'V') --- 3598,3604 ---- #ifdef FEAT_LINEBREAK // Avoid a problem with unwanted linebreaks in block mode. ! (void)reset_lbr(); #endif oap->is_VIsual = VIsual_active; if (oap->motion_force == 'V') *************** *** 3908,3914 **** { #ifdef FEAT_LINEBREAK // make sure redrawing is correct ! curwin->w_p_lbr = lbr_saved; #endif redraw_curbuf_later(UPD_INVERTED); } --- 3934,3940 ---- { #ifdef FEAT_LINEBREAK // make sure redrawing is correct ! restore_lbr(lbr_saved); #endif redraw_curbuf_later(UPD_INVERTED); } *************** *** 3948,3954 **** )) { #ifdef FEAT_LINEBREAK ! curwin->w_p_lbr = lbr_saved; #endif redraw_curbuf_later(UPD_INVERTED); } --- 3974,3980 ---- )) { #ifdef FEAT_LINEBREAK ! restore_lbr(lbr_saved); #endif redraw_curbuf_later(UPD_INVERTED); } *************** *** 4036,4042 **** else { #ifdef FEAT_LINEBREAK ! curwin->w_p_lbr = lbr_saved; #endif oap->excl_tr_ws = cap->cmdchar == 'z'; (void)op_yank(oap, FALSE, !gui_yank); --- 4062,4068 ---- else { #ifdef FEAT_LINEBREAK ! restore_lbr(lbr_saved); #endif oap->excl_tr_ws = cap->cmdchar == 'z'; (void)op_yank(oap, FALSE, !gui_yank); *************** *** 4065,4071 **** #ifdef FEAT_LINEBREAK // Restore linebreak, so that when the user edits it looks as // before. ! curwin->w_p_lbr = lbr_saved; #endif // Reset finish_op now, don't want it set inside edit(). finish_op = FALSE; --- 4091,4097 ---- #ifdef FEAT_LINEBREAK // Restore linebreak, so that when the user edits it looks as // before. ! restore_lbr(lbr_saved); #endif // Reset finish_op now, don't want it set inside edit(). finish_op = FALSE; *************** *** 4143,4149 **** #ifdef FEAT_LINEBREAK // Restore linebreak, so that when the user edits it looks as // before. ! curwin->w_p_lbr = lbr_saved; #endif // call 'operatorfunc' op_function(oap); --- 4169,4175 ---- #ifdef FEAT_LINEBREAK // Restore linebreak, so that when the user edits it looks as // before. ! restore_lbr(lbr_saved); #endif // call 'operatorfunc' op_function(oap); *************** *** 4172,4183 **** #ifdef FEAT_LINEBREAK // Restore linebreak, so that when the user edits it looks as // before. ! curwin->w_p_lbr = lbr_saved; #endif op_insert(oap, cap->count1); #ifdef FEAT_LINEBREAK // Reset linebreak, so that formatting works correctly. ! curwin->w_p_lbr = FALSE; #endif // TODO: when inserting in several lines, should format all --- 4198,4209 ---- #ifdef FEAT_LINEBREAK // Restore linebreak, so that when the user edits it looks as // before. ! restore_lbr(lbr_saved); #endif op_insert(oap, cap->count1); #ifdef FEAT_LINEBREAK // Reset linebreak, so that formatting works correctly. ! (void)reset_lbr(); #endif // TODO: when inserting in several lines, should format all *************** *** 4203,4209 **** #ifdef FEAT_LINEBREAK // Restore linebreak, so that when the user edits it looks as // before. ! curwin->w_p_lbr = lbr_saved; #endif op_replace(oap, cap->nchar); } --- 4229,4235 ---- #ifdef FEAT_LINEBREAK // Restore linebreak, so that when the user edits it looks as // before. ! restore_lbr(lbr_saved); #endif op_replace(oap, cap->nchar); } *************** *** 4246,4252 **** { VIsual_active = TRUE; #ifdef FEAT_LINEBREAK ! curwin->w_p_lbr = lbr_saved; #endif op_addsub(oap, cap->count1, redo_VIsual.rv_arg); VIsual_active = FALSE; --- 4272,4278 ---- { VIsual_active = TRUE; #ifdef FEAT_LINEBREAK ! restore_lbr(lbr_saved); #endif op_addsub(oap, cap->count1, redo_VIsual.rv_arg); VIsual_active = FALSE; *************** *** 4265,4271 **** || oap->op_type == OP_DELETE)) { #ifdef FEAT_LINEBREAK ! curwin->w_p_lbr = FALSE; #endif coladvance(curwin->w_curswant = old_col); } --- 4291,4297 ---- || oap->op_type == OP_DELETE)) { #ifdef FEAT_LINEBREAK ! (void)reset_lbr(); #endif coladvance(curwin->w_curswant = old_col); } *************** *** 4279,4284 **** motion_force = NUL; } #ifdef FEAT_LINEBREAK ! curwin->w_p_lbr = lbr_saved; #endif } --- 4305,4310 ---- motion_force = NUL; } #ifdef FEAT_LINEBREAK ! restore_lbr(lbr_saved); #endif } *** ../vim-9.0.0696/src/testdir/test_visual.vim 2022-09-02 21:55:45.511049444 +0100 --- src/testdir/test_visual.vim 2022-10-08 16:33:10.667914109 +0100 *************** *** 1501,1505 **** --- 1501,1537 ---- exe 'bwipe!' buf2 endfunc + " Test that cursor is drawn at correct position after an operator in Visual + " mode when 'linebreak' and 'showcmd' are enabled. + func Test_visual_operator_with_linebreak() + CheckRunVimInTerminal + + let lines =<< trim END + set linebreak showcmd noshowmode + call setline(1, repeat('a', &columns - 10) .. ' bbbbbbbbbb c') + END + call writefile(lines, 'XTest_visual_op_linebreak', 'D') + + let buf = RunVimInTerminal('-S XTest_visual_op_linebreak', {'rows': 6}) + + call term_sendkeys(buf, '$v$') + call WaitForAssert({-> assert_equal(13, term_getcursor(buf)[1])}) + call term_sendkeys(buf, 'zo') + call WaitForAssert({-> assert_equal(12, term_getcursor(buf)[1])}) + + call term_sendkeys(buf, "$\$") + call WaitForAssert({-> assert_equal(13, term_getcursor(buf)[1])}) + call term_sendkeys(buf, 'I') + call WaitForAssert({-> assert_equal(12, term_getcursor(buf)[1])}) + + call term_sendkeys(buf, "\$v$") + call WaitForAssert({-> assert_equal(13, term_getcursor(buf)[1])}) + call term_sendkeys(buf, 's') + call WaitForAssert({-> assert_equal(12, term_getcursor(buf)[1])}) + + " clean up + call term_sendkeys(buf, "\") + call StopVimInTerminal(buf) + endfunc " vim: shiftwidth=2 sts=2 expandtab *** ../vim-9.0.0696/src/testdir/test_listlbr.vim 2022-10-03 17:07:29.993542954 +0100 --- src/testdir/test_listlbr.vim 2022-10-08 16:25:35.301384797 +0100 *************** *** 8,13 **** --- 8,14 ---- CheckFeature conceal source view_util.vim + source screendump.vim function s:screen_lines(lnum, width) abort return ScreenLines(a:lnum, a:width) *************** *** 133,138 **** --- 134,159 ---- call s:close_windows() endfunc + func Test_linebreak_reset_restore() + CheckScreendump + + let lines =<< trim END + vim9script + &linebreak = true + &showcmd = true + &showmode = false + ('a'->repeat(&columns - 10) .. ' ' .. 'b'->repeat(10) .. ' c')->setline(1) + END + call writefile(lines, 'XlbrResetRestore', 'D') + let buf = RunVimInTerminal('-S XlbrResetRestore', {'rows': 8}) + + call term_sendkeys(buf, '$v$s') + call VerifyScreenDump(buf, 'Test_linebreak_reset_restore_1', {}) + + call term_sendkeys(buf, "\") + call StopVimInTerminal(buf) + endfunc + func Test_virtual_block() call s:test_windows('setl sbr=+') call setline(1, [ *** ../vim-9.0.0696/src/testdir/dumps/Test_linebreak_reset_restore_1.dump 2022-10-08 16:40:12.463845375 +0100 --- src/testdir/dumps/Test_linebreak_reset_restore_1.dump 2022-10-08 16:25:38.933372180 +0100 *************** *** 0 **** --- 1,8 ---- + |a+0&#ffffff0@64| @9 + |b@9| > @63 + |~+0#4040ff13&| @73 + |~| @73 + |~| @73 + |~| @73 + |~| @73 + | +0#0000000&@56|1|,|7|8|-|8|7| @6|A|l@1| *** ../vim-9.0.0696/src/version.c 2022-10-08 15:30:52.271540199 +0100 --- src/version.c 2022-10-08 16:39:55.987851931 +0100 *************** *** 701,702 **** --- 701,704 ---- { /* Add new patch number below this line */ + /**/ + 697, /**/ -- LAUNCELOT: At last! A call! A cry of distress ... (he draws his sword, and turns to CONCORDE) Concorde! Brave, Concorde ... you shall not have died in vain! CONCORDE: I'm not quite dead, sir ... "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// 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 ///