From adb73772d9197a7fa6e9ee7a2e8874118e60844d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 21 Sep 2023 08:00:03 +0800 Subject: vim-patch:9.0.1919: Wrong curswant when clicking on empty line or with vsplits Problem: Wrong curswant when clicking on empty line or with vsplits. Solution: Don't check for ScreenCols[] before the start of the window and handle empty line properly. closes: vim/vim#13132 https://github.com/vim/vim/commit/03cd697d635f1b0e7ffe21cf8244a8fb755f2ddb --- src/nvim/mouse.c | 83 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index e35385dd43..c4a31e0783 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -1849,56 +1849,55 @@ static void mouse_check_grid(colnr_T *vcolp, int *flagsp) int click_grid = mouse_grid; int click_row = mouse_row; int click_col = mouse_col; - int max_row = Rows; - int max_col = Columns; - bool multigrid = ui_has(kUIMultigrid); - colnr_T col_from_screen = -1; + // XXX: this doesn't change click_grid if it is 1, even with multigrid win_T *wp = mouse_find_win(&click_grid, &click_row, &click_col); - if (wp && multigrid) { - max_row = wp->w_grid_alloc.rows; - max_col = wp->w_grid_alloc.cols; + // Only use vcols[] after the window was redrawn. Mainly matters + // for tests, a user would not click before redrawing. + if (wp == NULL || wp->w_redr_type != 0) { + return; } + ScreenGrid *gp = &wp->w_grid; + int start_row = 0; + int start_col = 0; + grid_adjust(&gp, &start_row, &start_col); + if (gp->handle != click_grid) { + return; + } + click_row += start_row; + click_col += start_col; - if (wp && mouse_row >= 0 && mouse_row < max_row - && mouse_col >= 0 && mouse_col < max_col) { - ScreenGrid *gp = multigrid ? &wp->w_grid_alloc : &default_grid; - int use_row = multigrid && mouse_grid == 0 ? click_row : mouse_row; - int use_col = multigrid && mouse_grid == 0 ? click_col : mouse_col; - - if (gp->chars != NULL) { - const size_t off = gp->line_offset[use_row] + (size_t)use_col; - - // Only use vcols[] after the window was redrawn. Mainly matters - // for tests, a user would not click before redrawing. - if (wp->w_redr_type == 0) { - col_from_screen = gp->vcols[off]; - } + colnr_T col_from_screen = -1; - if (col_from_screen == MAXCOL) { - // When clicking after end of line, still need to set correct curswant - size_t off_l = gp->line_offset[use_row]; - if (gp->vcols[off_l] < MAXCOL) { - // Binary search to find last char in line - size_t off_r = off; - while (off_l < off_r) { - size_t off_m = (off_l + off_r + 1) / 2; - if (gp->vcols[off_m] < MAXCOL) { - off_l = off_m; - } else { - off_r = off_m - 1; - } + if (gp->chars != NULL + && click_row >= 0 && click_row < gp->rows + && click_col >= 0 && click_col < gp->cols) { + const size_t off = gp->line_offset[click_row] + (size_t)click_col; + col_from_screen = gp->vcols[off]; + + if (col_from_screen == MAXCOL) { + // When clicking after end of line, still need to set correct curswant + size_t off_l = gp->line_offset[click_row] + (size_t)start_col; + if (gp->vcols[off_l] < MAXCOL) { + // Binary search to find last char in line + size_t off_r = off; + while (off_l < off_r) { + size_t off_m = (off_l + off_r + 1) / 2; + if (gp->vcols[off_m] < MAXCOL) { + off_l = off_m; + } else { + off_r = off_m - 1; } - *vcolp = gp->vcols[off_r] + (int)(off - off_r); - } else { - // Shouldn't normally happen - *vcolp = MAXCOL; } - } else if (col_from_screen >= 0) { - // Use the virtual column from vcols[], it is accurate also after - // concealed characters. - *vcolp = col_from_screen; + *vcolp = gp->vcols[off_r] + (int)(off - off_r); + } else { + // Clicking on an empty line + *vcolp = click_col - start_col; } + } else if (col_from_screen >= 0) { + // Use the virtual column from vcols[], it is accurate also after + // concealed characters. + *vcolp = col_from_screen; } } -- cgit From e25cf47ad3e10e0e1ae2b2376d898382af5b1e26 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 21 Sep 2023 10:20:30 +0800 Subject: fix(mouse): click on empty line with 'foldcolumn' --- src/nvim/mouse.c | 61 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index c4a31e0783..33d7bc2e51 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -1861,44 +1861,47 @@ static void mouse_check_grid(colnr_T *vcolp, int *flagsp) int start_row = 0; int start_col = 0; grid_adjust(&gp, &start_row, &start_col); - if (gp->handle != click_grid) { + if (gp->handle != click_grid || gp->chars == NULL) { return; } click_row += start_row; click_col += start_col; + if (click_row < 0 || click_row >= gp->rows + || click_col < 0 || click_col >= gp->cols) { + return; + } - colnr_T col_from_screen = -1; + const size_t off = gp->line_offset[click_row] + (size_t)click_col; + colnr_T col_from_screen = gp->vcols[off]; - if (gp->chars != NULL - && click_row >= 0 && click_row < gp->rows - && click_col >= 0 && click_col < gp->cols) { - const size_t off = gp->line_offset[click_row] + (size_t)click_col; - col_from_screen = gp->vcols[off]; - - if (col_from_screen == MAXCOL) { - // When clicking after end of line, still need to set correct curswant - size_t off_l = gp->line_offset[click_row] + (size_t)start_col; - if (gp->vcols[off_l] < MAXCOL) { - // Binary search to find last char in line - size_t off_r = off; - while (off_l < off_r) { - size_t off_m = (off_l + off_r + 1) / 2; - if (gp->vcols[off_m] < MAXCOL) { - off_l = off_m; - } else { - off_r = off_m - 1; - } + if (col_from_screen == MAXCOL) { + // When clicking after end of line, still need to set correct curswant + size_t off_l = gp->line_offset[click_row] + (size_t)start_col; + if (gp->vcols[off_l] < MAXCOL) { + // Binary search to find last char in line + size_t off_r = off; + while (off_l < off_r) { + size_t off_m = (off_l + off_r + 1) / 2; + if (gp->vcols[off_m] < MAXCOL) { + off_l = off_m; + } else { + off_r = off_m - 1; } - *vcolp = gp->vcols[off_r] + (int)(off - off_r); - } else { - // Clicking on an empty line - *vcolp = click_col - start_col; } - } else if (col_from_screen >= 0) { - // Use the virtual column from vcols[], it is accurate also after - // concealed characters. - *vcolp = col_from_screen; + colnr_T eol_vcol = gp->vcols[off_r]; + assert(eol_vcol < MAXCOL); + // This may be -2 or -3 with 'foldcolumn' and empty line. + // In that case set it to -1 as it's just before start of line. + eol_vcol = MAX(eol_vcol, -1); + *vcolp = eol_vcol + (int)(off - off_r); + } else { + // Clicking on an empty line + *vcolp = click_col - start_col; } + } else if (col_from_screen >= 0) { + // Use the virtual column from vcols[], it is accurate also after + // concealed characters. + *vcolp = col_from_screen; } if (col_from_screen == -2) { -- cgit