diff src/mouse.c @ 32824:22a08166a876 v9.0.1725

patch 9.0.1725: cursor pos wrong after concealed text with 'virtualedit' Commit: https://github.com/vim/vim/commit/e500ae8e29ad921378085f5d70ee5c0c537be1ba Author: zeertzjq <zeertzjq@outlook.com> Date: Thu Aug 17 22:35:26 2023 +0200 patch 9.0.1725: cursor pos wrong after concealed text with 'virtualedit' Problem: Wrong cursor position when clicking after concealed text with 'virtualedit'. Solution: Store virtual columns in ScreenCols[] instead of text columns, and always use coladvance() when clicking. This also fixes incorrect curswant when clicking on a TAB, so now Test_normal_click_on_ctrl_char() asserts the same results as the ones before patch 9.0.0048. closes: #12808 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: zeertzjq <zeertzjq@outlook.com>
author Christian Brabandt <cb@256bit.org>
date Thu, 17 Aug 2023 22:45:04 +0200
parents 4545f58c8490
children def9fc5c92d1
line wrap: on
line diff
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -2060,7 +2060,7 @@ retnomove:
 	// Only use ScreenCols[] after the window was redrawn.  Mainly matters
 	// for tests, a user would not click before redrawing.
 	// Do not use when 'virtualedit' is active.
-	if (curwin->w_redr_type <= UPD_VALID_NO_UPDATE && !virtual_active())
+	if (curwin->w_redr_type <= UPD_VALID_NO_UPDATE)
 	    col_from_screen = ScreenCols[off];
 #ifdef FEAT_FOLDING
 	// Remember the character under the mouse, it might be a '-' or '+' in
@@ -2098,41 +2098,47 @@ retnomove:
 	    redraw_cmdline = TRUE;	// show visual mode later
     }
 
-    if (col_from_screen >= 0)
+    if (col_from_screen == MAXCOL)
     {
-	// Use the column from ScreenCols[], it is accurate also after
-	// concealed characters.
-	curwin->w_cursor.col = col_from_screen;
-	if (col_from_screen == MAXCOL)
+	// When clicking after end of line, still need to set correct curswant
+	int off_l = LineOffset[prev_row];
+	if (ScreenCols[off_l] < MAXCOL)
 	{
-	    curwin->w_curswant = col_from_screen;
-	    curwin->w_set_curswant = FALSE;	// May still have been TRUE
-	    mouse_past_eol = TRUE;
-	    if (inclusive != NULL)
-		*inclusive = TRUE;
+	    // Binary search to find last char in line
+	    int off_r = off_l + prev_col;
+	    int off_click = off_r;
+	    while (off_l < off_r)
+	    {
+		int off_m = (off_l + off_r + 1) / 2;
+		if (ScreenCols[off_m] < MAXCOL)
+		    off_l = off_m;
+		else
+		    off_r = off_m - 1;
+	    }
+	    col = ScreenCols[off_r] + (off_click - off_r);
 	}
 	else
-	{
-	    curwin->w_set_curswant = TRUE;
-	    if (inclusive != NULL)
-		*inclusive = FALSE;
-	}
-	check_cursor_col();
+	    // Shouldn't normally happen
+	    col = MAXCOL;
     }
-    else
+    else if (col_from_screen >= 0)
     {
-	curwin->w_curswant = col;
-	curwin->w_set_curswant = FALSE;	// May still have been TRUE
-	if (coladvance(col) == FAIL)	// Mouse click beyond end of line
-	{
-	    if (inclusive != NULL)
-		*inclusive = TRUE;
-	    mouse_past_eol = TRUE;
-	}
-	else if (inclusive != NULL)
-	    *inclusive = FALSE;
+	// Use the virtual column from ScreenCols[], it is accurate also after
+	// concealed characters.
+	col = col_from_screen;
     }
 
+    curwin->w_curswant = col;
+    curwin->w_set_curswant = FALSE;	// May still have been TRUE
+    if (coladvance(col) == FAIL)	// Mouse click beyond end of line
+    {
+	if (inclusive != NULL)
+	    *inclusive = TRUE;
+	mouse_past_eol = TRUE;
+    }
+    else if (inclusive != NULL)
+	*inclusive = FALSE;
+
     count = IN_BUFFER;
     if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum
 	    || curwin->w_cursor.col != old_cursor.col)