Patch 9.0.0886

6 views
Skip to first unread message

Bram Moolenaar

unread,
Nov 15, 2022, 12:44:20 PM11/15/22
to vim...@googlegroups.com

Patch 9.0.0886
Problem: Horizontal mouse scroll only works in the GUI.
Solution: Make horizontal mouse scroll also work in a terminal.
(Christopher Plewright, closes #11448)
Files: src/edit.c, src/ex_getln.c, src/gui.c, src/proto/gui.pro,
src/mouse.c, src/proto/mouse.pro, src/normal.c, src/ui.c,
src/proto/ui.pro


*** ../vim-9.0.0885/src/edit.c 2022-10-14 20:09:00.895207512 +0100
--- src/edit.c 2022-11-15 17:03:43.364670773 +0000
***************
*** 4499,4505 ****

undisplay_dollar();
tpos = curwin->w_cursor;
! if (gui_do_horiz_scroll(scrollbar_value, FALSE))
{
start_arrow(&tpos);
can_cindent = TRUE;
--- 4499,4505 ----

undisplay_dollar();
tpos = curwin->w_cursor;
! if (do_mousescroll_horiz(scrollbar_value))
{
start_arrow(&tpos);
can_cindent = TRUE;
*** ../vim-9.0.0885/src/ex_getln.c 2022-10-04 16:23:39.014042183 +0100
--- src/ex_getln.c 2022-11-15 17:04:05.740682564 +0000
***************
*** 2221,2227 ****
case K_HOR_SCROLLBAR:
if (msg_scrolled == 0)
{
! gui_do_horiz_scroll(scrollbar_value, FALSE);
redrawcmd();
}
goto cmdline_not_changed;
--- 2221,2227 ----
case K_HOR_SCROLLBAR:
if (msg_scrolled == 0)
{
! do_mousescroll_horiz(scrollbar_value);
redrawcmd();
}
goto cmdline_not_changed;
*** ../vim-9.0.0885/src/gui.c 2022-11-14 15:31:04.041587447 +0000
--- src/gui.c 2022-11-15 17:18:30.097158161 +0000
***************
*** 4105,4118 ****
scrollbar_value = value;

if (State & MODE_NORMAL)
! gui_do_horiz_scroll(scrollbar_value, FALSE);
else if (State & MODE_INSERT)
ins_horscroll();
else if (State & MODE_CMDLINE)
{
if (msg_scrolled == 0)
{
! gui_do_horiz_scroll(scrollbar_value, FALSE);
redrawcmdline();
}
}
--- 4105,4118 ----
scrollbar_value = value;

if (State & MODE_NORMAL)
! do_mousescroll_horiz(scrollbar_value);
else if (State & MODE_INSERT)
ins_horscroll();
else if (State & MODE_CMDLINE)
{
if (msg_scrolled == 0)
{
! do_mousescroll_horiz(scrollbar_value);
redrawcmdline();
}
}
***************
*** 4504,4591 ****
return (wp == curwin && !EQUAL_POS(curwin->w_cursor, old_cursor));
}

-
/*
* Horizontal scrollbar stuff:
*/
-
- /*
- * Return length of line "lnum" for horizontal scrolling.
- */
- static colnr_T
- scroll_line_len(linenr_T lnum)
- {
- char_u *p;
- colnr_T col;
- int w;
-
- p = ml_get(lnum);
- col = 0;
- if (*p != NUL)
- for (;;)
- {
- w = chartabsize(p, col);
- MB_PTR_ADV(p);
- if (*p == NUL) // don't count the last character
- break;
- col += w;
- }
- return col;
- }
-
- // Remember which line is currently the longest, so that we don't have to
- // search for it when scrolling horizontally.
- static linenr_T longest_lnum = 0;
-
- /*
- * Find longest visible line number. If this is not possible (or not desired,
- * by setting 'h' in "guioptions") then the current line number is returned.
- */
- static linenr_T
- gui_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 (vim_strchr(p_go, GO_HORSCROLL) == NULL
- && curwin->w_topline <= curwin->w_cursor.lnum
- && curwin->w_botline > curwin->w_cursor.lnum
- && curwin->w_botline <= curbuf->b_ml.ml_line_count + 1)
- {
- linenr_T lnum;
- colnr_T n;
- 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 (lnum = curwin->w_topline; lnum < curwin->w_botline; ++lnum)
- {
- n = scroll_line_len(lnum);
- if (n > (colnr_T)max)
- {
- max = n;
- ret = lnum;
- }
- else if (n == (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;
- }
-
static void
gui_update_horiz_scrollbar(int force)
{
! long value, size, max; // need 32 bit ints here

if (!gui.which_scrollbars[SBAR_BOTTOM])
return;
--- 4504,4516 ----
return (wp == curwin && !EQUAL_POS(curwin->w_cursor, old_cursor));
}

/*
* Horizontal scrollbar stuff:
*/
static void
gui_update_horiz_scrollbar(int force)
{
! long value, size, max;

if (!gui.which_scrollbars[SBAR_BOTTOM])
return;
***************
*** 4619,4627 ****
else
{
value = curwin->w_leftcol;
!
! longest_lnum = gui_find_longest_lnum();
! max = scroll_line_len(longest_lnum);

if (virtual_active())
{
--- 4544,4550 ----
else
{
value = curwin->w_leftcol;
! max = scroll_line_len(ui_find_longest_lnum());

if (virtual_active())
{
***************
*** 4670,4713 ****
}

/*
- * Do a horizontal scroll. Return TRUE if the cursor moved, FALSE otherwise.
- */
- int
- gui_do_horiz_scroll(long_u leftcol, int compute_longest_lnum)
- {
- // no wrapping, no scrolling
- if (curwin->w_p_wrap)
- return FALSE;
-
- if (curwin->w_leftcol == (colnr_T)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 (vim_strchr(p_go, GO_HORSCROLL) == NULL
- && !virtual_active()
- && (colnr_T)leftcol > scroll_line_len(curwin->w_cursor.lnum))
- {
- if (compute_longest_lnum)
- {
- curwin->w_cursor.lnum = gui_find_longest_lnum();
- curwin->w_cursor.col = 0;
- }
- // Do a sanity check on "longest_lnum", just in case.
- else if (longest_lnum >= curwin->w_topline
- && longest_lnum < curwin->w_botline)
- {
- curwin->w_cursor.lnum = longest_lnum;
- curwin->w_cursor.col = 0;
- }
- }
-
- return leftcol_changed();
- }
-
- /*
* Check that none of the colors are the same as the background color
*/
void
--- 4593,4598 ----
*** ../vim-9.0.0885/src/proto/gui.pro 2022-06-29 12:54:48.064572066 +0100
--- src/proto/gui.pro 2022-11-15 17:24:06.441386208 +0000
***************
*** 45,51 ****
void gui_may_update_scrollbars(void);
void gui_update_scrollbars(int force);
int gui_do_scroll(void);
- int gui_do_horiz_scroll(long_u leftcol, int compute_longest_lnum);
void gui_check_colors(void);
guicolor_T gui_get_color(char_u *name);
int gui_get_lightness(guicolor_T pixel);
--- 45,50 ----
*** ../vim-9.0.0885/src/mouse.c 2022-11-01 18:34:02.783964409 +0000
--- src/mouse.c 2022-11-15 17:22:13.993304937 +0000
***************
*** 1101,1189 ****
redraw_statuslines();
}

void
ins_mousescroll(int dir)
{
! pos_T tpos;
! win_T *old_curwin = curwin, *wp;
! int did_scroll = FALSE;
!
! tpos = curwin->w_cursor;
!
! if (mouse_row >= 0 && mouse_col >= 0)
! {
! int row, col;
!
! row = mouse_row;
! col = mouse_col;
!
! // find the window at the pointer coordinates
! wp = mouse_find_win(&row, &col, FIND_POPUP);
! if (wp == NULL)
! return;
! curwin = wp;
! curbuf = curwin->w_buffer;
! }
! if (curwin == old_curwin)
! undisplay_dollar();
!
! // Don't scroll the window in which completion is being done.
! if (!pum_visible() || curwin != old_curwin)
! {
! long step;
!
! if (dir == MSCR_DOWN || dir == MSCR_UP)
! {
! if (mouse_vert_step < 0
! || mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
! step = (long)(curwin->w_botline - curwin->w_topline);
! else
! step = mouse_vert_step;
! scroll_redraw(dir, step);
! # ifdef FEAT_PROP_POPUP
! if (WIN_IS_POPUP(curwin))
! popup_set_firstline(curwin);
! # endif
! }
! #ifdef FEAT_GUI
! else
! {
! int val;
!
! if (mouse_hor_step < 0
! || mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
! step = curwin->w_width;
! else
! step = mouse_hor_step;
! val = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : step);
! if (val < 0)
! val = 0;
! gui_do_horiz_scroll(val, TRUE);
! }
! #endif
! did_scroll = TRUE;
! may_trigger_winscrolled();
! }

! curwin->w_redr_status = TRUE;
!
! curwin = old_curwin;
! curbuf = curwin->w_buffer;

! // The popup menu may overlay the window, need to redraw it.
! // TODO: Would be more efficient to only redraw the windows that are
! // overlapped by the popup menu.
! if (pum_visible() && did_scroll)
{
! redraw_all_later(UPD_NOT_VALID);
! ins_compl_show_pum();
! }
!
! if (!EQUAL_POS(curwin->w_cursor, tpos))
! {
! start_arrow(&tpos);
! set_can_cindent(TRUE);
}
}

/*
--- 1101,1139 ----
redraw_statuslines();
}

+ /*
+ * Implementation for scrolling in direction "dir", which is one of the MSCR_
+ * values.
+ */
void
ins_mousescroll(int dir)
{
! cmdarg_T cap;
! CLEAR_FIELD(cap);

! oparg_T oa;
! 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);
}
+ do_mousescroll(MODE_INSERT, &cap);
}

/*
***************
*** 2073,2088 ****
}

/*
* Mouse scroll wheel: Default action is to scroll mouse_vert_step lines (or
! * mouse_hor_step, depending on the scroll direction), 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)
{
! win_T *old_curwin = curwin, *wp;

if (mouse_row >= 0 && mouse_col >= 0)
{
--- 2023,2074 ----
}

/*
+ * Make a horizontal scroll to "leftcol".
+ * Return TRUE if the cursor moved, FALSE otherwise.
+ */
+ int
+ do_mousescroll_horiz(long_u leftcol)
+ {
+ if (curwin->w_p_wrap)
+ return FALSE; // no wrapping, no scrolling
+
+ if (curwin->w_leftcol == (colnr_T)leftcol)
+ return FALSE; // already there
+
+ curwin->w_leftcol = (colnr_T)leftcol;
+
+ // When the line of the cursor is too short, move the cursor to the
+ // longest visible line.
+ if (
+ #ifdef FEAT_GUI
+ (!gui.in_use || vim_strchr(p_go, GO_HORSCROLL) == NULL) &&
+ #endif
+ !virtual_active()
+ && (long)leftcol > scroll_line_len(curwin->w_cursor.lnum))
+ {
+ curwin->w_cursor.lnum = ui_find_longest_lnum();
+ curwin->w_cursor.col = 0;
+ }
+
+ return leftcol_changed();
+ }
+
+ /*
* Mouse scroll wheel: Default action is to scroll mouse_vert_step lines (or
! * mouse_hor_step, 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
*/
void
! do_mousescroll(int mode, cmdarg_T *cap)
{
! win_T *old_curwin = curwin, *wp;
! int did_ins_scroll = FALSE;
! pos_T tpos = curwin->w_cursor;

if (mouse_row >= 0 && mouse_col >= 0)
{
***************
*** 2102,2162 ****
curwin = wp;
curbuf = curwin->w_buffer;
}
! if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN)
! {
# ifdef FEAT_TERMINAL
! if (term_use_loop())
! // This window is a terminal window, send the mouse event there.
! // Set "typed" to FALSE to avoid an endless loop.
! send_keys_to_term(curbuf->b_term, cap->cmdchar, mod_mask, FALSE);
! else
# endif
! if (mouse_vert_step < 0 || mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
! {
! (void)onepage(cap->arg ? FORWARD : BACKWARD, 1L);
! }
! else
{
! // Don't scroll more than half the window height.
! if (curwin->w_height < mouse_vert_step * 2)
{
! cap->count1 = curwin->w_height / 2;
! if (cap->count1 == 0)
! cap->count1 = 1;
}
else
! cap->count1 = mouse_vert_step;
! cap->count0 = cap->count1;
! nv_scroll_line(cap);
! }
#ifdef FEAT_PROP_POPUP
! if (WIN_IS_POPUP(curwin))
! popup_set_firstline(curwin);
#endif
! }
! # ifdef FEAT_GUI
! else
! {
! // Horizontal scroll - only allowed when 'wrap' is disabled
! if (!curwin->w_p_wrap)
{
! int val, step;
!
! if (mouse_hor_step < 0
! || mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
! step = curwin->w_width;
! else
! step = mouse_hor_step;
! val = curwin->w_leftcol + (cap->arg == MSCR_RIGHT ? -step : +step);
! if (val < 0)
! val = 0;

! gui_do_horiz_scroll(val, TRUE);
}
}
! # endif
# ifdef FEAT_SYN_HL
! if (curwin != old_curwin && curwin->w_p_cul)
redraw_for_cursorline(curwin);
# endif
may_trigger_winscrolled();
--- 2088,2167 ----
curwin = wp;
curbuf = curwin->w_buffer;
}
! if (mode == MODE_INSERT && curwin == old_curwin)
! undisplay_dollar();
!
# ifdef FEAT_TERMINAL
! if (term_use_loop())
! // This window is a terminal window, send the mouse event there.
! // Set "typed" to FALSE to avoid an endless loop.
! send_keys_to_term(curbuf->b_term, cap->cmdchar, mod_mask, FALSE);
! else
# endif
! // For insert mode, don't scroll the window in which completion is being
! // done.
! if (mode == MODE_NORMAL || !pum_visible() || curwin != old_curwin)
! {
! if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN)
{
! if (mouse_vert_step < 0
! || mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
{
! if (mode == MODE_INSERT)
! {
! long step = (long)(curwin->w_botline - curwin->w_topline);
! scroll_redraw(cap->arg, step);
! }
! else
! {
! did_ins_scroll = onepage(cap->arg ? FORWARD : BACKWARD, 1L);
! }
}
else
! {
! if (mode == MODE_INSERT)
! {
! scroll_redraw(cap->arg, mouse_vert_step);
! }
! else
! {
! // Don't scroll more than half the window height.
! if (curwin->w_height < mouse_vert_step * 2)
! {
! cap->count1 = curwin->w_height / 2;
! if (cap->count1 == 0)
! cap->count1 = 1;
! }
! else
! {
! cap->count1 = mouse_vert_step;
! }
! cap->count0 = cap->count1;
! nv_scroll_line(cap);
! }
! }
!
#ifdef FEAT_PROP_POPUP
! if (WIN_IS_POPUP(curwin))
! popup_set_firstline(curwin);
#endif
! }
! else
{
! long step = (mouse_hor_step < 0
! || (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)))
! ? curwin->w_width : mouse_hor_step;
! long leftcol = curwin->w_leftcol
! + (cap->arg == MSCR_RIGHT ? -step : step);
! if (leftcol < 0)
! leftcol = 0;

! did_ins_scroll = do_mousescroll_horiz((long_u)leftcol);
}
}
!
# ifdef FEAT_SYN_HL
! if (mode == MODE_NORMAL && curwin != old_curwin && curwin->w_p_cul)
redraw_for_cursorline(curwin);
# endif
may_trigger_winscrolled();
***************
*** 2165,2170 ****
--- 2170,2198 ----

curwin = old_curwin;
curbuf = curwin->w_buffer;
+
+ if (mode == MODE_INSERT)
+ {
+ // The popup menu may overlay the window, need to redraw it.
+ // TODO: Would be more efficient to only redraw the windows that are
+ // overlapped by the popup menu.
+ if (pum_visible() && did_ins_scroll)
+ {
+ redraw_all_later(UPD_NOT_VALID);
+ ins_compl_show_pum();
+ }
+ if (!EQUAL_POS(curwin->w_cursor, tpos))
+ {
+ start_arrow(&tpos);
+ set_can_cindent(TRUE);
+ }
+ }
+ }
+
+ void
+ nv_mousescroll(cmdarg_T *cap)
+ {
+ do_mousescroll(MODE_NORMAL, cap);
}

/*
*** ../vim-9.0.0885/src/proto/mouse.pro 2022-11-01 18:34:02.783964409 +0000
--- src/proto/mouse.pro 2022-11-15 17:24:13.265391047 +0000
***************
*** 14,19 ****
--- 14,21 ----
int mouse_model_popup(void);
void reset_dragwin(void);
int jump_to_mouse(int flags, int *inclusive, int which_button);
+ int do_mousescroll_horiz(long_u leftcol);
+ void do_mousescroll(int mode, cmdarg_T *cap);
void nv_mousescroll(cmdarg_T *cap);
void nv_mouse(cmdarg_T *cap);
void reset_held_button(void);
*** ../vim-9.0.0885/src/normal.c 2022-10-14 20:09:00.895207512 +0100
--- src/normal.c 2022-11-15 17:04:41.080701273 +0000
***************
*** 3047,3053 ****
clearopbeep(cap->oap);

// Even if an operator was pending, we still want to scroll
! gui_do_horiz_scroll(scrollbar_value, FALSE);
}
#endif

--- 3047,3053 ----
clearopbeep(cap->oap);

// Even if an operator was pending, we still want to scroll
! do_mousescroll_horiz(scrollbar_value);
}
#endif

*** ../vim-9.0.0885/src/ui.c 2022-10-08 13:49:41.893378443 +0100
--- src/ui.c 2022-11-15 17:18:04.629143824 +0000
***************
*** 1126,1131 ****
--- 1126,1200 ----
}

/*
+ * Return length of line "lnum" in screen cells for horizontal scrolling.
+ */
+ long
+ scroll_line_len(linenr_T lnum)
+ {
+ char_u *p = ml_get(lnum);
+ colnr_T col = 0;
+
+ if (*p != NUL)
+ for (;;)
+ {
+ int w = chartabsize(p, col);
+ MB_PTR_ADV(p);
+ if (*p == NUL) // don't count the last character
+ break;
+ col += w;
+ }
+ return col;
+ }
+
+ /*
+ * Find the longest visible line number. This is used for horizontal
+ * scrolling. If this is not possible (or not desired, by setting 'h' in
+ * "guioptions") then the current line number is returned.
+ */
+ linenr_T
+ ui_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 (
+ # ifdef FEAT_GUI
+ (!gui.in_use || vim_strchr(p_go, GO_HORSCROLL) == NULL) &&
+ # endif
+ curwin->w_topline <= curwin->w_cursor.lnum
+ && curwin->w_botline > curwin->w_cursor.lnum
+ && curwin->w_botline <= curbuf->b_ml.ml_line_count + 1)
+ {
+ linenr_T lnum;
+ long n;
+ 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 (lnum = curwin->w_topline; lnum < curwin->w_botline; ++lnum)
+ {
+ n = scroll_line_len(lnum);
+ if (n > max)
+ {
+ max = n;
+ ret = lnum;
+ }
+ else if (n == 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;
+ }
+
+ /*
* Called when focus changed. Used for the GUI or for systems where this can
* be done in the console (Win32).
*/
*** ../vim-9.0.0885/src/proto/ui.pro 2022-06-27 23:15:27.000000000 +0100
--- src/proto/ui.pro 2022-11-15 17:24:17.917394342 +0000
***************
*** 30,35 ****
--- 30,37 ----
void ui_cursor_shape(void);
int check_col(int col);
int check_row(int row);
+ long scroll_line_len(linenr_T lnum);
+ linenr_T ui_find_longest_lnum(void);
void ui_focus_change(int in_focus);
void im_save_status(long *psave);
/* vim: set ft=c : */
*** ../vim-9.0.0885/src/version.c 2022-11-15 13:57:35.122066675 +0000
--- src/version.c 2022-11-15 15:24:41.840859316 +0000
***************
*** 697,698 ****
--- 697,700 ----
{ /* Add new patch number below this line */
+ /**/
+ 886,
/**/

--
hundred-and-one symptoms of being an internet addict:
77. The phone company asks you to test drive their new PBX system

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages