mouse: Implement horizontal scroll. #3450

- Code from Vim source.
- Removed the check for 'guioptions'
- mouse_spec.lua: test <ScrollWheelLeft> and <ScrollWheelRight>
- Move horizontal scroll logic to mouse.c
- Remove 'gui_' from the function names
- Renamed variables to be more specific (as opposed to generic p, w).
- Marked some functions as `static`
This commit is contained in:
bambu 2015-10-12 20:27:17 -04:00 committed by Justin M. Keyes
parent dfe85dd80a
commit 5a5ef1c222
6 changed files with 135 additions and 6 deletions

View File

@ -7741,6 +7741,8 @@ static void ins_mousescroll(int dir)
(long)(curwin->w_botline - curwin->w_topline));
else
scroll_redraw(dir, 3L);
} else {
mouse_scroll_horiz(dir);
}
did_scroll = TRUE;
}

View File

@ -36,12 +36,6 @@ typedef int (*IndentGetter)(void);
#define INSCHAR_NO_FEX 8 /* don't use 'formatexpr' */
#define INSCHAR_COM_LIST 16 /* format comments with list/2nd line indent */
/* direction for nv_mousescroll() and ins_mousescroll() */
#define MSCR_DOWN 0 /* DOWN must be FALSE */
#define MSCR_UP 1
#define MSCR_LEFT -1
#define MSCR_RIGHT -2
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "edit.h.generated.h"
#endif

View File

@ -14,6 +14,8 @@
#include "nvim/misc1.h"
#include "nvim/cursor.h"
#include "nvim/buffer_defs.h"
#include "nvim/memline.h"
#include "nvim/charset.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "mouse.c.generated.h"
@ -503,3 +505,95 @@ void set_mouse_topline(win_T *wp)
orig_topfill = wp->w_topfill;
}
///
/// Return length of line "lnum" for horizontal scrolling.
///
static colnr_T scroll_line_len(linenr_T lnum)
{
colnr_T col = 0;
char_u *line = ml_get(lnum);
if (*line != NUL) {
for (;;) {
int numchar = chartabsize(line, col);
mb_ptr_adv(line);
if (*line == NUL) { // don't count the last character
break;
}
col += numchar;
}
}
return col;
}
///
/// Find longest visible line number.
///
static linenr_T find_longest_lnum(void)
{
linenr_T ret = 0;
// Calculate maximum for horizontal scrollbar. Check for reasonable
// line numbers, topline and botline can be invalid when displaying is
// postponed.
if (curwin->w_topline <= curwin->w_cursor.lnum &&
curwin->w_botline > curwin->w_cursor.lnum &&
curwin->w_botline <= curbuf->b_ml.ml_line_count + 1) {
long max = 0;
// Use maximum of all visible lines. Remember the lnum of the
// longest line, closest to the cursor line. Used when scrolling
// below.
for (linenr_T lnum = curwin->w_topline; lnum < curwin->w_botline; lnum++) {
colnr_T len = scroll_line_len(lnum);
if (len > (colnr_T)max) {
max = len;
ret = lnum;
} else if (len == (colnr_T)max
&& abs((int)(lnum - curwin->w_cursor.lnum))
< abs((int)(ret - curwin->w_cursor.lnum))) {
ret = lnum;
}
}
} else {
// Use cursor line only.
ret = curwin->w_cursor.lnum;
}
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 = 6;
if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) {
step = curwin->w_width;
}
int leftcol = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : +step);
if (leftcol < 0) {
leftcol = 0;
}
if (curwin->w_leftcol == leftcol) {
return false;
}
curwin->w_leftcol = (colnr_T)leftcol;
// 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 leftcol_changed();
}

View File

@ -34,6 +34,12 @@
#define MOUSE_X1 0x300 // Mouse-button X1 (6th)
#define MOUSE_X2 0x400 // Mouse-button X2
// Direction for nv_mousescroll() and ins_mousescroll()
#define MSCR_DOWN 0 // DOWN must be FALSE
#define MSCR_UP 1
#define MSCR_LEFT -1
#define MSCR_RIGHT -2
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "mouse.h.generated.h"

View File

@ -3927,6 +3927,8 @@ static void nv_mousescroll(cmdarg_T *cap)
cap->count0 = 3;
nv_scroll_line(cap);
}
} else {
mouse_scroll_horiz(cap->arg);
}
curwin->w_redr_status = true;

View File

@ -426,4 +426,35 @@ describe('Mouse input', function()
|
]])
end)
it('horizontal scrolling', function()
feed("<esc>:set nowrap<cr>")
feed("a <esc>20Ab<esc>")
screen:expect([[
|
|
bbbbbbbbbbbbbbb^b |
~ |
|
]])
feed("<ScrollWheelLeft><0,0>")
screen:expect([[
|
|
n bbbbbbbbbbbbbbbbbbb^b |
~ |
|
]])
feed("^<ScrollWheelRight><0,0>")
screen:expect([[
g |
|
^t and selection bbbbbbbbb|
~ |
|
]])
end)
end)