diff options
-rw-r--r-- | src/nvim/mouse.c | 210 |
1 files changed, 124 insertions, 86 deletions
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index bd57101de5..176aff849e 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -993,46 +993,111 @@ void ins_mouse(int c) redraw_statuslines(); } +/// Common mouse wheel scrolling, shared between Insert mode and NV modes. +/// Default action is to scroll mouse_vert_step lines (or mouse_hor_step columns +/// depending on the scroll direction) or one page when Shift or Ctrl is used. +/// Direction is indicated by "cap->arg": +/// K_MOUSEUP - MSCR_UP +/// K_MOUSEDOWN - MSCR_DOWN +/// K_MOUSELEFT - MSCR_LEFT +/// K_MOUSERIGHT - MSCR_RIGHT +/// "curwin" may have been changed to the window that should be scrolled and +/// differ from the window that actually has focus. +static void do_mousescroll(cmdarg_T *cap) +{ + bool shift_or_ctrl = mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL); + + if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN) { + // Vertical scrolling + if (!(State & MODE_INSERT) && shift_or_ctrl) { + // whole page up or down + (void)onepage(cap->arg ? FORWARD : BACKWARD, 1); + } else { + if (shift_or_ctrl) { + // whole page up or down + cap->count1 = curwin->w_botline - curwin->w_topline; + } else { + cap->count1 = (int)p_mousescroll_vert; + } + if (cap->count1 > 0) { + cap->count0 = cap->count1; + nv_scroll_line(cap); + } + } + } else { + // Horizontal scrolling + int step = shift_or_ctrl ? curwin->w_width_inner : (int)p_mousescroll_hor; + colnr_T leftcol = curwin->w_leftcol + (cap->arg == MSCR_RIGHT ? -step : +step); + if (leftcol < 0) { + leftcol = 0; + } + (void)do_mousescroll_horiz(leftcol); + } +} + +/// Implementation for scrolling in Insert mode in direction "dir", which is one +/// of the MSCR_ values. void ins_mousescroll(int dir) { - win_T *const old_curwin = curwin; - pos_T tpos = curwin->w_cursor; + cmdarg_T cap; + oparg_T oa; + CLEAR_FIELD(cap); + clear_oparg(&oa); + cap.oap = &oa; + cap.arg = dir; + + switch (dir) { + case MSCR_UP: + cap.cmdchar = K_MOUSEUP; + break; + case MSCR_DOWN: + cap.cmdchar = K_MOUSEDOWN; + break; + case MSCR_LEFT: + cap.cmdchar = K_MOUSELEFT; + break; + case MSCR_RIGHT: + cap.cmdchar = K_MOUSERIGHT; + break; + default: + siemsg("Invalid ins_mousescroll() argument: %d", dir); + } + win_T *old_curwin = curwin; if (mouse_row >= 0 && mouse_col >= 0) { - int row = mouse_row, col = mouse_col, grid = mouse_grid; - - // find the window at the pointer coordinates - win_T *wp = mouse_find_win(&grid, &row, &col); - if (wp == NULL) { + // Find the window at the mouse pointer coordinates. + // NOTE: Must restore "curwin" to "old_curwin" before returning! + int grid = mouse_grid; + int row = mouse_row; + int col = mouse_col; + curwin = mouse_find_win(&grid, &row, &col); + if (curwin == NULL) { + curwin = old_curwin; return; } - curwin = wp; curbuf = curwin->w_buffer; } + if (curwin == old_curwin) { + // Don't scroll the current window if the popup menu is visible. + if (pum_visible()) { + return; + } + undisplay_dollar(); } - // Don't scroll the window in which completion is being done. - if (!pum_visible() || curwin != old_curwin) { - if (dir == MSCR_DOWN || dir == MSCR_UP) { - if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) { - scroll_redraw(dir, curwin->w_botline - curwin->w_topline); - } else if (p_mousescroll_vert > 0) { - scroll_redraw(dir, (linenr_T)p_mousescroll_vert); - } - } else { - mouse_scroll_horiz(dir); - } - } + pos_T orig_cursor = curwin->w_cursor; - curwin->w_redr_status = true; + // Call the common mouse scroll function shared with other modes. + do_mousescroll(&cap); + curwin->w_redr_status = true; curwin = old_curwin; curbuf = curwin->w_buffer; - if (!equalpos(curwin->w_cursor, tpos)) { - start_arrow(&tpos); + if (!equalpos(curwin->w_cursor, orig_cursor)) { + start_arrow(&orig_cursor); set_can_cindent(true); } } @@ -1456,47 +1521,55 @@ retnomove: return count; } -/// Mouse scroll wheel: Default action is to scroll three lines, or one page -/// when Shift or Ctrl is used. -/// K_MOUSEUP (cap->arg == 1) or K_MOUSEDOWN (cap->arg == 0) or -/// K_MOUSELEFT (cap->arg == -1) or K_MOUSERIGHT (cap->arg == -2) -void nv_mousescroll(cmdarg_T *cap) +/// Make a horizontal scroll to "leftcol". +/// @return true if the cursor moved, false otherwise. +static bool do_mousescroll_horiz(colnr_T leftcol) { - win_T *old_curwin = curwin; + if (curwin->w_p_wrap) { + return false; // no horizontal scrolling when wrapping + } + if (curwin->w_leftcol == leftcol) { + return false; // already there + } - if (mouse_row >= 0 && mouse_col >= 0) { - int grid, row, col; + // When the line of the cursor is too short, move the cursor to the + // longest visible line. + if (!virtual_active() + && leftcol > scroll_line_len(curwin->w_cursor.lnum)) { + curwin->w_cursor.lnum = find_longest_lnum(); + curwin->w_cursor.col = 0; + } - grid = mouse_grid; - row = mouse_row; - col = mouse_col; + return set_leftcol(leftcol); +} - // find the window at the pointer coordinates - win_T *wp = mouse_find_win(&grid, &row, &col); - if (wp == NULL) { +/// Normal and Visual modes implementation for scrolling in direction +/// "cap->arg", which is one of the MSCR_ values. +void nv_mousescroll(cmdarg_T *cap) +{ + win_T *const old_curwin = curwin; + + if (mouse_row >= 0 && mouse_col >= 0) { + // Find the window at the mouse pointer coordinates. + // NOTE: Must restore "curwin" to "old_curwin" before returning! + int grid = mouse_grid; + int row = mouse_row; + int col = mouse_col; + curwin = mouse_find_win(&grid, &row, &col); + if (curwin == NULL) { + curwin = old_curwin; return; } - curwin = wp; curbuf = curwin->w_buffer; } - if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN) { - if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) { - (void)onepage(cap->arg ? FORWARD : BACKWARD, 1); - } else if (p_mousescroll_vert > 0) { - cap->count1 = (int)p_mousescroll_vert; - cap->count0 = (int)p_mousescroll_vert; - nv_scroll_line(cap); - } - } else { - mouse_scroll_horiz(cap->arg); - } + // Call the common mouse scroll function shared with other modes. + do_mousescroll(cap); + if (curwin != old_curwin && curwin->w_p_cul) { redraw_for_cursorline(curwin); } - curwin->w_redr_status = true; - curwin = old_curwin; curbuf = curwin->w_buffer; } @@ -1724,9 +1797,7 @@ static colnr_T scroll_line_len(linenr_T lnum) return col; } -/// /// Find longest visible line number. -/// static linenr_T find_longest_lnum(void) { linenr_T ret = 0; @@ -1761,39 +1832,6 @@ static linenr_T find_longest_lnum(void) return ret; } -/// Do a horizontal scroll. -/// @return true if the cursor moved, false otherwise. -bool mouse_scroll_horiz(int dir) -{ - if (curwin->w_p_wrap) { - return false; - } - - int step = (int)p_mousescroll_hor; - if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) { - step = curwin->w_width_inner; - } - - int leftcol = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : +step); - if (leftcol < 0) { - leftcol = 0; - } - - if (curwin->w_leftcol == leftcol) { - return false; - } - - // When the line of the cursor is too short, move the cursor to the - // longest visible line. - if (!virtual_active() - && (colnr_T)leftcol > scroll_line_len(curwin->w_cursor.lnum)) { - curwin->w_cursor.lnum = find_longest_lnum(); - curwin->w_cursor.col = 0; - } - - return set_leftcol(leftcol); -} - /// Check clicked cell on its grid static void mouse_check_grid(colnr_T *vcolp, int *flagsp) FUNC_ATTR_NONNULL_ALL |