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, "$\<C-V>$")
+   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, "\<Esc>$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, "\<Esc>")
+   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, "\<Esc>")
+   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 -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221008154231.1EF501C0D0A%40moolenaar.net.

Raspunde prin e-mail lui