]> granicus.if.org Git - vim/commitdiff
patch 9.0.0886: horizontal mouse scroll only works in the GUI v9.0.0886
authorChristopher Plewright <chris@createng.com>
Tue, 15 Nov 2022 17:43:36 +0000 (17:43 +0000)
committerBram Moolenaar <Bram@vim.org>
Tue, 15 Nov 2022 17:43:36 +0000 (17:43 +0000)
Problem:    Horizontal mouse scroll only works in the GUI.
Solution:   Make horizontal mouse scroll also work in a terminal.
            (Christopher Plewright, closes #11448)

src/edit.c
src/ex_getln.c
src/gui.c
src/mouse.c
src/normal.c
src/proto/gui.pro
src/proto/mouse.pro
src/proto/ui.pro
src/ui.c
src/version.c

index 555b83bc319943314121363d1183569e0d990712..cf114d8bd2952bd20c443352d77433787123b19b 100644 (file)
@@ -4499,7 +4499,7 @@ ins_horscroll(void)
 
     undisplay_dollar();
     tpos = curwin->w_cursor;
-    if (gui_do_horiz_scroll(scrollbar_value, FALSE))
+    if (do_mousescroll_horiz(scrollbar_value))
     {
        start_arrow(&tpos);
        can_cindent = TRUE;
index 770daa9525d7e0c4fea9cc0d5d379781e33a922a..d3119baf25d506025a0655b9bc67f002d11618ec 100644 (file)
@@ -2221,7 +2221,7 @@ getcmdline_int(
        case K_HOR_SCROLLBAR:
                if (msg_scrolled == 0)
                {
-                   gui_do_horiz_scroll(scrollbar_value, FALSE);
+                   do_mousescroll_horiz(scrollbar_value);
                    redrawcmd();
                }
                goto cmdline_not_changed;
index 88c0a1345317138d98ce3772e8659793df25898f..45747ef09ecf970028e6b9ae102c629cd87a9608 100644 (file)
--- a/src/gui.c
+++ b/src/gui.c
@@ -4105,14 +4105,14 @@ gui_drag_scrollbar(scrollbar_T *sb, long value, int still_dragging)
        scrollbar_value = value;
 
        if (State & MODE_NORMAL)
-           gui_do_horiz_scroll(scrollbar_value, FALSE);
+           do_mousescroll_horiz(scrollbar_value);
        else if (State & MODE_INSERT)
            ins_horscroll();
        else if (State & MODE_CMDLINE)
        {
            if (msg_scrolled == 0)
            {
-               gui_do_horiz_scroll(scrollbar_value, FALSE);
+               do_mousescroll_horiz(scrollbar_value);
                redrawcmdline();
            }
        }
@@ -4504,88 +4504,13 @@ gui_do_scroll(void)
     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
+    long       value, size, max;
 
     if (!gui.which_scrollbars[SBAR_BOTTOM])
        return;
@@ -4619,9 +4544,7 @@ gui_update_horiz_scrollbar(int force)
     else
     {
        value = curwin->w_leftcol;
-
-       longest_lnum = gui_find_longest_lnum();
-       max = scroll_line_len(longest_lnum);
+       max = scroll_line_len(ui_find_longest_lnum());
 
        if (virtual_active())
        {
@@ -4669,44 +4592,6 @@ gui_update_horiz_scrollbar(int force)
     gui_mch_set_scrollbar_thumb(&gui.bottom_sbar, value, size, max);
 }
 
-/*
- * 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
  */
index 25e65ed72b23204a5ff9f3ec3de4dbbb7683fe46..5ebf125dcfe3437a1c26b90e6db755c8d672a0ad 100644 (file)
@@ -1101,89 +1101,39 @@ ins_mouse(int c)
     redraw_statuslines();
 }
 
+/*
+ * Implementation for scrolling in direction "dir", which is one of the MSCR_
+ * values.
+ */
     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;
+    cmdarg_T cap;
+    CLEAR_FIELD(cap);
 
-           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();
-    }
+    oparg_T oa;
+    clear_oparg(&oa);
+    cap.oap = &oa;
 
-    if (!EQUAL_POS(curwin->w_cursor, tpos))
+    cap.arg = dir;
+    switch (dir)
     {
-       start_arrow(&tpos);
-       set_can_cindent(TRUE);
+       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);
 }
 
 /*
@@ -2072,17 +2022,53 @@ retnomove:
     return count;
 }
 
+/*
+ * 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.
- * K_MOUSEUP (cap->arg == 1) or K_MOUSEDOWN (cap->arg == 0) or
- * K_MOUSELEFT (cap->arg == -1) or K_MOUSERIGHT (cap->arg == -2)
+ * 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
-nv_mousescroll(cmdarg_T *cap)
+do_mousescroll(int mode, cmdarg_T *cap)
 {
-    win_T *old_curwin = curwin, *wp;
+    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,61 +2088,80 @@ nv_mousescroll(cmdarg_T *cap)
        curwin = wp;
        curbuf = curwin->w_buffer;
     }
-    if (cap->arg == MSCR_UP || cap->arg == MSCR_DOWN)
-    {
+    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
+    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
+    // 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)
        {
-           // Don't scroll more than half the window height.
-           if (curwin->w_height < mouse_vert_step * 2)
+           if (mouse_vert_step < 0
+                   || mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
            {
-               cap->count1 = curwin->w_height / 2;
-               if (cap->count1 == 0)
-                   cap->count1 = 1;
+               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
-               cap->count1 = mouse_vert_step;
-           cap->count0 = cap->count1;
-           nv_scroll_line(cap);
-       }
+           {
+               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);
+           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)
+       }
+       else
        {
-           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;
+           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;
 
-           gui_do_horiz_scroll(val, TRUE);
+           did_ins_scroll = do_mousescroll_horiz((long_u)leftcol);
        }
     }
-# endif
+
 # ifdef FEAT_SYN_HL
-    if (curwin != old_curwin && curwin->w_p_cul)
+    if (mode == MODE_NORMAL && curwin != old_curwin && curwin->w_p_cul)
        redraw_for_cursorline(curwin);
 # endif
     may_trigger_winscrolled();
@@ -2165,6 +2170,29 @@ nv_mousescroll(cmdarg_T *cap)
 
     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);
 }
 
 /*
index 7b47f18a4c51f50c7b5ac0f3a4e19db6cf4fe447..79f168617290a3c6112b338612696e1f1933b2d9 100644 (file)
@@ -3047,7 +3047,7 @@ nv_hor_scrollbar(cmdarg_T *cap)
        clearopbeep(cap->oap);
 
     // Even if an operator was pending, we still want to scroll
-    gui_do_horiz_scroll(scrollbar_value, FALSE);
+    do_mousescroll_horiz(scrollbar_value);
 }
 #endif
 
index 1a04248447f05f6e50ddb8e465bbf78faac98d15..47613f59726a2e7d43d08cbaa6f3327daba09e2c 100644 (file)
@@ -45,7 +45,6 @@ void gui_drag_scrollbar(scrollbar_T *sb, long value, int still_dragging);
 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);
index 7ce470c6c0195e865c4ef95b1eaca3754857eece..e3bb5faff9c5239a8d6ac322ffbb80444948e4e8 100644 (file)
@@ -14,6 +14,8 @@ int mouse_has(int c);
 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);
index f44bad1d65f58a453eb292581541d70a3120ec9d..7ad7c75edcb1e5acd51dadcdd405a74e173d82bc 100644 (file)
@@ -30,6 +30,8 @@ void ui_cursor_shape_forced(int forced);
 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 : */
index b56e3952503ea4f4a349c84a10042f845ecab0c2..9fc88e5e842eaf3f9ca16f4cbdf1f28f0b35dd55 100644 (file)
--- a/src/ui.c
+++ b/src/ui.c
@@ -1125,6 +1125,75 @@ check_row(int row)
     return row;
 }
 
+/*
+ * 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).
index 61ad4c7568c3f15ba90575a862f6574f4f36fdd6..d7f4808f8daa8360dadd5e550be8aeded558beaf 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    886,
 /**/
     885,
 /**/