Skip to content

Commit b908188

Browse files
committed
patch 9.0.0048: cursor in wrong column with mouse click after concealed text
Problem: Cursor in wrong column with mouse click after concealed text. Solution: Store the text column when drawing text.
1 parent fee0c4a commit b908188

File tree

6 files changed

+142
-43
lines changed

6 files changed

+142
-43
lines changed

src/drawline.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -779,7 +779,7 @@ win_line(
779779
trailcol = (colnr_T)STRLEN(ptr);
780780
while (trailcol > (colnr_T)0 && VIM_ISWHITE(ptr[trailcol - 1]))
781781
--trailcol;
782-
trailcol += (colnr_T) (ptr - line);
782+
trailcol += (colnr_T)(ptr - line);
783783
}
784784
// find end of leading whitespace
785785
if (wp->w_lcs_chars.lead || wp->w_lcs_chars.leadmultispace != NULL)
@@ -792,7 +792,7 @@ win_line(
792792
leadcol = (colnr_T)0;
793793
else
794794
// keep track of the first column not filled with spaces
795-
leadcol += (colnr_T) (ptr - line) + 1;
795+
leadcol += (colnr_T)(ptr - line) + 1;
796796
}
797797
}
798798

@@ -1027,12 +1027,14 @@ win_line(
10271027
// Repeat for the whole displayed line.
10281028
for (;;)
10291029
{
1030+
char_u *prev_ptr = ptr;
10301031
#if defined(FEAT_CONCEAL) || defined(FEAT_SEARCH_EXTRA)
1031-
int has_match_conc = 0; // match wants to conceal
1032+
int has_match_conc = 0; // match wants to conceal
10321033
#endif
10331034
#ifdef FEAT_CONCEAL
1034-
int did_decrement_ptr = FALSE;
1035+
int did_decrement_ptr = FALSE;
10351036
#endif
1037+
10361038
// Skip this quickly when working on the text.
10371039
if (draw_state != WL_LINE)
10381040
{
@@ -1392,6 +1394,7 @@ win_line(
13921394
&match_conc, did_line_attr, lcs_eol_one,
13931395
&on_last_col);
13941396
ptr = line + v; // "line" may have been changed
1397+
prev_ptr = ptr;
13951398

13961399
// Do not allow a conceal over EOL otherwise EOL will be missed
13971400
// and bad things happen.
@@ -1553,6 +1556,7 @@ win_line(
15531556
// have made it invalid.
15541557
line = ml_get_buf(wp->w_buffer, lnum, FALSE);
15551558
ptr = line + v;
1559+
prev_ptr = ptr;
15561560
# ifdef FEAT_CONCEAL
15571561
// no concealing past the end of the line, it interferes
15581562
// with line highlighting
@@ -1733,9 +1737,10 @@ win_line(
17331737
else
17341738
{
17351739
#ifdef FEAT_LINEBREAK
1736-
int c0;
1740+
int c0;
17371741
#endif
17381742
VIM_CLEAR(p_extra_free);
1743+
prev_ptr = ptr;
17391744

17401745
// Get a character from the line itself.
17411746
c = *ptr;
@@ -1942,17 +1947,12 @@ win_line(
19421947
# endif
19431948
can_spell))
19441949
{
1945-
char_u *prev_ptr, *p;
1950+
char_u *p;
19461951
int len;
19471952
hlf_T spell_hlf = HLF_COUNT;
19481953

19491954
if (has_mbyte)
1950-
{
1951-
prev_ptr = ptr - mb_l;
19521955
v -= mb_l - 1;
1953-
}
1954-
else
1955-
prev_ptr = ptr - 1;
19561956

19571957
// Use nextline[] if possible, it has the start of the
19581958
// next line concatenated.
@@ -2771,6 +2771,7 @@ win_line(
27712771
}
27722772
#endif
27732773
ScreenAttrs[off] = char_attr;
2774+
ScreenCols[off] = MAXCOL;
27742775
#ifdef FEAT_RIGHTLEFT
27752776
if (wp->w_p_rl)
27762777
{
@@ -2839,6 +2840,7 @@ win_line(
28392840
ScreenLines[off] = ' ';
28402841
if (enc_utf8)
28412842
ScreenLinesUC[off] = 0;
2843+
ScreenCols[off] = MAXCOL;
28422844
++col;
28432845
if (draw_color_col)
28442846
draw_color_col = advance_color_col(VCOL_HLC,
@@ -2992,6 +2994,8 @@ win_line(
29922994
else
29932995
ScreenAttrs[off] = char_attr;
29942996

2997+
ScreenCols[off] = (colnr_T)(prev_ptr - line);
2998+
29952999
if (has_mbyte && (*mb_char2cells)(mb_c) > 1)
29963000
{
29973001
// Need to fill two screen columns.
@@ -3013,6 +3017,9 @@ win_line(
30133017
// the character, otherwise highlighting won't stop.
30143018
if (tocol == vcol)
30153019
++tocol;
3020+
3021+
ScreenCols[off] = (colnr_T)(prev_ptr - line);
3022+
30163023
#ifdef FEAT_RIGHTLEFT
30173024
if (wp->w_p_rl)
30183025
{

src/globals.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,17 @@ EXTERN long Columns INIT(= 80); // nr of columns in the screen
3232
* The characters that are currently on the screen are kept in ScreenLines[].
3333
* It is a single block of characters, the size of the screen plus one line.
3434
* The attributes for those characters are kept in ScreenAttrs[].
35+
* The byte offset in the line is kept in ScreenCols[].
3536
*
3637
* "LineOffset[n]" is the offset from ScreenLines[] for the start of line 'n'.
37-
* The same value is used for ScreenLinesUC[] and ScreenAttrs[].
38+
* The same value is used for ScreenLinesUC[], ScreenAttrs[] and ScreenCols[].
3839
*
3940
* Note: before the screen is initialized and when out of memory these can be
4041
* NULL.
4142
*/
4243
EXTERN schar_T *ScreenLines INIT(= NULL);
4344
EXTERN sattr_T *ScreenAttrs INIT(= NULL);
45+
EXTERN colnr_T *ScreenCols INIT(= NULL);
4446
EXTERN unsigned *LineOffset INIT(= NULL);
4547
EXTERN char_u *LineWraps INIT(= NULL); // line wraps to next line
4648

@@ -62,7 +64,7 @@ EXTERN int Screen_mco INIT(= 0); // value of p_mco used when
6264
EXTERN schar_T *ScreenLines2 INIT(= NULL);
6365

6466
/*
65-
* Buffer for one screen line (characters and attributes).
67+
* One screen line to be displayed. Points into ScreenLines.
6668
*/
6769
EXTERN schar_T *current_ScreenLine INIT(= NULL);
6870

src/mouse.c

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,8 +1543,9 @@ jump_to_mouse(
15431543
int first;
15441544
int row = mouse_row;
15451545
int col = mouse_col;
1546+
colnr_T col_from_screen = -1;
15461547
#ifdef FEAT_FOLDING
1547-
int mouse_char;
1548+
int mouse_char = ' ';
15481549
#endif
15491550

15501551
mouse_past_bottom = FALSE;
@@ -1626,16 +1627,6 @@ jump_to_mouse(
16261627
if (flags & MOUSE_SETPOS)
16271628
goto retnomove; // ugly goto...
16281629

1629-
#ifdef FEAT_FOLDING
1630-
// Remember the character under the mouse, it might be a '-' or '+' in the
1631-
// fold column.
1632-
if (row >= 0 && row < Rows && col >= 0 && col <= Columns
1633-
&& ScreenLines != NULL)
1634-
mouse_char = ScreenLines[LineOffset[row] + col];
1635-
else
1636-
mouse_char = ' ';
1637-
#endif
1638-
16391630
old_curwin = curwin;
16401631
old_cursor = curwin->w_cursor;
16411632

@@ -1969,6 +1960,22 @@ jump_to_mouse(
19691960
}
19701961
}
19711962

1963+
if (prev_row >= 0 && prev_row < Rows && prev_col >= 0 && prev_col <= Columns
1964+
&& ScreenLines != NULL)
1965+
{
1966+
int off = LineOffset[prev_row] + prev_col;
1967+
1968+
// Only use ScreenCols[] after the window was redrawn. Mainly matters
1969+
// for tests, a user would not click before redrawing.
1970+
if (curwin->w_redr_type <= VALID_NO_UPDATE)
1971+
col_from_screen = ScreenCols[off];
1972+
#ifdef FEAT_FOLDING
1973+
// Remember the character under the mouse, it might be a '-' or '+' in
1974+
// the fold column.
1975+
mouse_char = ScreenLines[off];
1976+
#endif
1977+
}
1978+
19721979
#ifdef FEAT_FOLDING
19731980
// Check for position outside of the fold column.
19741981
if (
@@ -2001,16 +2008,40 @@ jump_to_mouse(
20012008
redraw_cmdline = TRUE; // show visual mode later
20022009
}
20032010

2004-
curwin->w_curswant = col;
2005-
curwin->w_set_curswant = FALSE; // May still have been TRUE
2006-
if (coladvance(col) == FAIL) // Mouse click beyond end of line
2011+
if (col_from_screen >= 0)
2012+
{
2013+
// Use the column from ScreenCols[], it is accurate also after
2014+
// concealed characters.
2015+
curwin->w_cursor.col = col_from_screen;
2016+
if (col_from_screen == MAXCOL)
2017+
{
2018+
curwin->w_curswant = col_from_screen;
2019+
curwin->w_set_curswant = FALSE; // May still have been TRUE
2020+
mouse_past_eol = TRUE;
2021+
if (inclusive != NULL)
2022+
*inclusive = TRUE;
2023+
}
2024+
else
2025+
{
2026+
curwin->w_set_curswant = TRUE;
2027+
if (inclusive != NULL)
2028+
*inclusive = FALSE;
2029+
}
2030+
check_cursor_col();
2031+
}
2032+
else
20072033
{
2008-
if (inclusive != NULL)
2009-
*inclusive = TRUE;
2010-
mouse_past_eol = TRUE;
2034+
curwin->w_curswant = col;
2035+
curwin->w_set_curswant = FALSE; // May still have been TRUE
2036+
if (coladvance(col) == FAIL) // Mouse click beyond end of line
2037+
{
2038+
if (inclusive != NULL)
2039+
*inclusive = TRUE;
2040+
mouse_past_eol = TRUE;
2041+
}
2042+
else if (inclusive != NULL)
2043+
*inclusive = FALSE;
20112044
}
2012-
else if (inclusive != NULL)
2013-
*inclusive = FALSE;
20142045

20152046
count = IN_BUFFER;
20162047
if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum

0 commit comments

Comments
 (0)