To: [email protected]
Subject: patch 5.5a.14
Fcc: outbox
From: Bram Moolenaar <[email protected]>
------------

Bending the term 'bug fix' a bit...

Patch 5.5a.14
Problem:    Athena, Motif and GTK: The mouse scroll wheel doesn't work.
Solution:   Interpret a click of the wheel as a key press of the <MouseDown>
           or <MouseUp> keys.  Default behavior is to scroll three lines, or
           a full page when Shift is used.
Files:      src/edit.c, src/ex_getln.c, src/gui.c, src/gui_gtk_x11.c,
           src/gui_x11.c, src/keymap.h, src/message.c, src/misc1.c,
           src/misc2.c, src/normal.c,  src/proto/normal.pro, src/vim.h,
           runtime/doc/scroll.txt


*** ../vim-5.5a.13/src/edit.c   Wed Sep  1 18:02:55 1999
--- src/edit.c  Thu Sep  9 17:06:23 1999
***************
*** 129,134 ****
--- 129,135 ----
 static int  ins_bs __ARGS((int c, int mode, int *inserted_space_p));
 #ifdef USE_MOUSE
 static void ins_mouse __ARGS((int c));
+ static void ins_mousescroll __ARGS((int up));
 #endif
 static void ins_left __ARGS((void));
 static void ins_home __ARGS((void));
***************
*** 849,854 ****
--- 850,865 ----

       case K_IGNORE:
           break;
+
+       /* Default action for scroll wheel up: scroll up */
+       case K_MOUSEDOWN:
+           ins_mousescroll(FALSE);
+           break;
+
+       /* Default action for scroll wheel down: scroll down */
+       case K_MOUSEUP:
+           ins_mousescroll(TRUE);
+           break;
 #endif

 #ifdef USE_GUI
***************
*** 5092,5097 ****
--- 5103,5129 ----
     /* redraw status lines (in case another window became active) */
     redraw_statuslines();
 }
+
+     static void
+ ins_mousescroll(up)
+     int               up;
+ {
+     FPOS      tpos;
+
+     undisplay_dollar();
+     tpos = curwin->w_cursor;
+     if (mod_mask & MOD_MASK_SHIFT)
+       scroll_redraw(up, (long)(curwin->w_botline - curwin->w_topline));
+     else
+       scroll_redraw(up, 3L);
+     if (!equal(curwin->w_cursor, tpos))
+     {
+       start_arrow(&tpos);
+ # ifdef CINDENT
+       can_cindent = TRUE;
+ # endif
+     }
+ }
 #endif

 #ifdef USE_GUI
***************
*** 5121,5129 ****
     if (gui_do_horiz_scroll())
     {
       start_arrow(&tpos);
! #ifdef CINDENT
       can_cindent = TRUE;
! #endif
     }
 }
 #endif
--- 5153,5161 ----
     if (gui_do_horiz_scroll())
     {
       start_arrow(&tpos);
! # ifdef CINDENT
       can_cindent = TRUE;
! # endif
     }
 }
 #endif
*** ../vim-5.5a.13/src/ex_getln.c       Mon Aug 30 10:40:50 1999
--- src/ex_getln.c      Thu Sep  9 17:06:26 1999
***************
*** 858,863 ****
--- 858,869 ----
                   ccline.cmdspos += i;
               }
               goto cmdline_not_changed;
+
+       /* Mouse scroll wheel: ignored here */
+       case K_MOUSEDOWN:
+       case K_MOUSEUP:
+               goto cmdline_not_changed;
+
 #endif        /* USE_MOUSE */

 #ifdef USE_GUI
*** ../vim-5.5a.13/src/gui.c    Mon Aug 30 10:40:59 1999
--- src/gui.c   Thu Sep  9 17:05:52 1999
***************
*** 1817,1822 ****
--- 1817,1823 ----
  * the given properties.
  *  button        --- may be any of MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT,
  *                    MOUSE_DRAG, or MOUSE_RELEASE.
+  *                    MOUSE_4 and MOUSE_5 are used for a scroll wheel.
  *  x, y          --- Coordinates of mouse in pixels.
  *  repeated_click  --- TRUE if this click comes only a short time after a
  *                    previous click.
***************
*** 1838,1849 ****
     static int            num_clicks = 1;
     char_u        string[6];
     int                   row, col;
-
 #ifdef USE_CLIPBOARD
-
     int                   checkfor;
     int                   did_clip = FALSE;

     /* If a clipboard selection is in progress, handle it */
     if (clipboard.state == SELECT_IN_PROGRESS)
     {
--- 1839,1880 ----
     static int            num_clicks = 1;
     char_u        string[6];
     int                   row, col;
 #ifdef USE_CLIPBOARD
     int                   checkfor;
     int                   did_clip = FALSE;
+ #endif
+
+     /*
+      * Scrolling may happen at any time, also while a selection is present.
+      */
+     if (button == MOUSE_4 || button == MOUSE_5)
+     {
+       /* Don't put events in the input queue now. */
+       if (hold_gui_events)
+           return;

+       string[3] = CSI;
+       string[4] = KS_EXTRA;
+       string[5] = button == MOUSE_4 ? KE_MOUSEDOWN : KE_MOUSEUP;
+       if (modifiers == 0)
+           add_to_input_buf(string + 3, 3);
+       else
+       {
+           string[0] = CSI;
+           string[1] = KS_MODIFIER;
+           string[2] = 0;
+           if (modifiers & MOUSE_SHIFT)
+               string[2] |= MOD_MASK_SHIFT;
+           if (modifiers & MOUSE_CTRL)
+               string[2] |= MOD_MASK_CTRL;
+           if (modifiers & MOUSE_ALT)
+               string[2] |= MOD_MASK_ALT;
+           add_to_input_buf(string, 6);
+       }
+       return;
+     }
+
+ #ifdef USE_CLIPBOARD
     /* If a clipboard selection is in progress, handle it */
     if (clipboard.state == SELECT_IN_PROGRESS)
     {
*** ../vim-5.5a.13/src/gui_gtk_x11.c    Mon Aug 30 10:40:53 1999
--- src/gui_gtk_x11.c   Thu Sep  9 15:20:51 1999
***************
*** 2642,2648 ****
     mouse_click_timer = gtk_timeout_add(p_mouset,
                                 mouse_click_timer_cb, &mouse_timed_out);

!     switch (event->button) {
     case 1:
       button = MOUSE_LEFT;
       break;
--- 2642,2649 ----
     mouse_click_timer = gtk_timeout_add(p_mouset,
                                 mouse_click_timer_cb, &mouse_timed_out);

!     switch (event->button)
!     {
     case 1:
       button = MOUSE_LEFT;
       break;
***************
*** 2651,2656 ****
--- 2652,2663 ----
       break;
     case 3:
       button = MOUSE_RIGHT;
+       break;
+     case 4:
+       button = MOUSE_4;
+       break;
+     case 5:
+       button = MOUSE_5;
       break;
     default:
       return FALSE;           /* Unknown button */
*** ../vim-5.5a.13/src/gui_x11.c        Mon Aug 30 10:40:54 1999
--- src/gui_x11.c       Thu Sep  9 13:20:19 1999
***************
*** 792,797 ****
--- 795,802 ----
               case Button1:   button = MOUSE_LEFT;    break;
               case Button2:   button = MOUSE_MIDDLE;  break;
               case Button3:   button = MOUSE_RIGHT;   break;
+               case Button4:   button = MOUSE_4;       break;
+               case Button5:   button = MOUSE_5;       break;
               default:
                   return;     /* Unknown button */
           }
*** ../vim-5.5a.13/src/keymap.h Mon Aug 30 10:40:47 1999
--- src/keymap.h        Thu Sep  9 17:06:35 1999
***************
*** 200,206 ****
     KE_S_XF1,         /* extra vt100 shifted function keys for xterm */
     KE_S_XF2,
     KE_S_XF3,
!     KE_S_XF4
 };

 /*
--- 200,209 ----
     KE_S_XF1,         /* extra vt100 shifted function keys for xterm */
     KE_S_XF2,
     KE_S_XF3,
!     KE_S_XF4,
!
!     KE_MOUSEDOWN,     /* scroll wheel pseudo-button Down */
!     KE_MOUSEUP                /* scroll wheel pseudo-button Up */
 };

 /*
***************
*** 362,367 ****
--- 365,373 ----
 #define K_IGNORE          TERMCAP2KEY(KS_EXTRA, KE_IGNORE)

 #define K_SNIFF                   TERMCAP2KEY(KS_EXTRA, KE_SNIFF)
+
+ #define K_MOUSEDOWN       TERMCAP2KEY(KS_EXTRA, KE_MOUSEDOWN)
+ #define K_MOUSEUP         TERMCAP2KEY(KS_EXTRA, KE_MOUSEUP)

 /* Bits for modifier mask */
 /* 0x01 cannot be used, because the modifier must be 0x02 or higher */
*** ../vim-5.5a.13/src/message.c        Mon Aug 30 10:40:58 1999
--- src/message.c       Thu Sep  9 17:06:40 1999
***************
*** 589,594 ****
--- 589,595 ----
                               || c == K_LEFTDRAG   || c == K_LEFTRELEASE
                               || c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
                               || c == K_RIGHTDRAG  || c == K_RIGHTRELEASE
+                               || c == K_MOUSEDOWN  || c == K_MOUSEUP
                               || c == K_IGNORE     ||
                               (!mouse_has(MOUSE_RETURN) &&
                                    (c == K_LEFTMOUSE ||
*** ../vim-5.5a.13/src/misc1.c  Mon Aug 30 10:40:51 1999
--- src/misc1.c Thu Sep  9 17:06:43 1999
***************
*** 2056,2061 ****
--- 2056,2063 ----
                   || n ==  K_RIGHTMOUSE
                   || n ==  K_RIGHTDRAG
                   || n ==  K_RIGHTRELEASE
+                   || n ==  K_MOUSEDOWN
+                   || n ==  K_MOUSEUP
 # ifdef USE_GUI
                   || n == K_SCROLLBAR
                   || n == K_HORIZ_SCROLLBAR
*** ../vim-5.5a.13/src/misc2.c  Mon Aug 30 10:40:52 1999
--- src/misc2.c Thu Sep  9 17:06:50 1999
***************
*** 1422,1427 ****
--- 1422,1429 ----
     {K_RIGHTMOUSE,    (char_u *)"RightMouse"},
     {K_RIGHTDRAG,     (char_u *)"RightDrag"},
     {K_RIGHTRELEASE,  (char_u *)"RightRelease"},
+     {K_MOUSEDOWN,     (char_u *)"MouseDown"},
+     {K_MOUSEUP,               (char_u *)"MouseUp"},
     {K_ZERO,          (char_u *)"Nul"},
     {0,                       NULL}
 };
*** ../vim-5.5a.13/src/normal.c Mon Aug 30 10:40:58 1999
--- src/normal.c        Thu Sep  9 17:07:00 1999
***************
*** 1180,1185 ****
--- 1180,1198 ----

     case K_IGNORE:
       break;
+
+     /* Mouse scroll wheel: default action is to scroll three lines, or one
+      * page when Shift is used. */
+     case K_MOUSEUP:
+       flag = TRUE;
+     case K_MOUSEDOWN:
+       if (mod_mask & MOD_MASK_SHIFT)
+           ca.count1 = curwin->w_botline - curwin->w_topline;
+       else
+           ca.count1 = 3;
+       ca.count0 = ca.count1;
+       nv_scroll_line(&ca, flag);
+       break;
 #endif

 #ifdef USE_GUI
***************
*** 2860,2865 ****
--- 2873,2879 ----
               K_LEFTMOUSE, K_LEFTDRAG, K_LEFTRELEASE,
               K_MIDDLEMOUSE, K_MIDDLEDRAG, K_MIDDLERELEASE,
               K_RIGHTMOUSE, K_RIGHTDRAG, K_RIGHTRELEASE,
+               K_MOUSEDOWN, K_MOUSEUP,
               0};
 #endif

***************
*** 3274,3290 ****
  */
     static void
 nv_scroll_line(cap, is_ctrl_e)
!     CMDARG  *cap;
!     int           is_ctrl_e;      /* TRUE for CTRL-E command */
 {
-     linenr_t      prev_topline = curwin->w_topline;
-
     if (checkclearop(cap->oap))
       return;
!     if (is_ctrl_e)
!       scrollup(cap->count1);
     else
!       scrolldown(cap->count1);
     if (p_so)
     {
       cursor_correct();
--- 3288,3316 ----
  */
     static void
 nv_scroll_line(cap, is_ctrl_e)
!     CMDARG    *cap;
!     int               is_ctrl_e;          /* TRUE for CTRL-E command */
 {
     if (checkclearop(cap->oap))
       return;
!     scroll_redraw(is_ctrl_e, cap->count1);
! }
!
! /*
!  * Scroll "count" lines up or down, and redraw.
!  */
!     void
! scroll_redraw(up, count)
!     int               up;
!     long      count;
! {
!     linenr_t  prev_topline = curwin->w_topline;
!     linenr_t  prev_lnum = curwin->w_cursor.lnum;
!
!     if (up)
!       scrollup(count);
     else
!       scrolldown(count);
     if (p_so)
     {
       cursor_correct();
***************
*** 3294,3306 ****
        * first line of the buffer is already on the screen */
       if (curwin->w_topline == prev_topline)
       {
!           if (is_ctrl_e)
               cursor_down(1L, FALSE);
           else if (prev_topline != 1L)
               cursor_up(1L, FALSE);
       }
     }
!     coladvance(curwin->w_curswant);
     update_screen(VALID);
 }

--- 3320,3333 ----
        * first line of the buffer is already on the screen */
       if (curwin->w_topline == prev_topline)
       {
!           if (up)
               cursor_down(1L, FALSE);
           else if (prev_topline != 1L)
               cursor_up(1L, FALSE);
       }
     }
!     if (curwin->w_cursor.lnum != prev_lnum)
!       coladvance(curwin->w_curswant);
     update_screen(VALID);
 }

*** ../vim-5.5a.13/src/proto/normal.pro Mon Aug 30 10:40:39 1999
--- src/proto/normal.pro        Thu Sep  9 14:45:32 1999
***************
*** 12,16 ****
--- 12,17 ----
 void pop_showcmd __ARGS((void));
 void do_check_scrollbind __ARGS((int check));
 void check_scrollbind __ARGS((linenr_t topline_diff, long leftcol_diff));
+ void scroll_redraw __ARGS((int up, long count));
 void start_selection __ARGS((void));
 void may_start_select __ARGS((int c));
*** ../vim-5.5a.13/src/vim.h    Mon Aug 30 10:40:48 1999
--- src/vim.h   Thu Sep  9 17:13:43 1999
***************
*** 886,891 ****
--- 886,895 ----
 # define MOUSE_ALT    0x08
 # define MOUSE_CTRL   0x10

+ /* mouse buttons that are handled like a key press */
+ # define MOUSE_4      0x100   /* scroll wheel down */
+ # define MOUSE_5      0x200   /* scroll wheel up */
+
 /* 0x20 is reserved by xterm */
 # define MOUSE_DRAG_XTERM   0x40

*** ../vim-5.5a.13/runtime/doc/scroll.txt       Mon Aug 30 10:41:12 1999
--- runtime/doc/scroll.txt      Thu Sep  9 17:02:59 1999
***************
*** 1,4 ****
! *scroll.txt*    For Vim version 5.5a.  Last change: 1999 Mar 31


                 VIM REFERENCE MANUAL    by Bram Moolenaar
--- 1,4 ----
! *scroll.txt*    For Vim version 5.5a.  Last change: 1999 Sep 09


                 VIM REFERENCE MANUAL    by Bram Moolenaar
***************
*** 19,24 ****
--- 19,25 ----
 3. Scrolling relative to cursor       |scroll-cursor|
 4. Scrolling horizontally     |scroll-horizontal|
 5. Scrolling synchronously    |scroll-binding|
+ 6. Scrolling with a mouse wheel |scroll-mouse-wheel|

 ==============================================================================
 1. Scrolling downwards                                        *scroll-down*
***************
*** 195,199 ****
--- 196,237 ----
 window which has the cursor focus.  However, when using the vertical scrollbar
 of a window which doesn't have the cursor focus, 'scrollbind' is ignored.
 This allows quick adjustment of the relative offset of 'scrollbind' windows.
+
+ ==============================================================================
+ 6. Scrolling with a mouse wheel                               *scroll-mouse-wheel*
+
+ When your mouse has a scroll wheel, it should work with Vim in the GUI.  How
+ it works depends on your system.
+
+ For the Win32 GUI the scroll action is hard coded.  It works just like
+ dragging the scrollbar of the current window.  How many lines are scrolled
+ depends on your mouse driver.  If the scroll action causes input focus
+ problems, see |intellimouse-wheel-problems|.
+
+ For the X11 GUIs (Motif, Athena and GTK) scrolling the wheel generates key
+ presses <MouseDown> and <MouseUp>.  The default action for these keys are:
+     <MouseDown>               scroll three lines down.        *<MouseDown>*
+     <S-MouseDown>     scroll a full page down.        *<S-MouseDown>*
+     <MouseUp>         scroll three lines up.          *<MouseUp>*
+     <S-MouseUp>               scroll a full page up.          *<S-MouseUp>*
+ This should work in all modes, except when editing the command line.
+
+ You can modify this behavior by mapping the keys.  For example, to make the
+ scroll wheel move one line or half a page in Normal mode:
+ >   map <MouseDown> <C-Y>
+ >   map <S-MouseDown> <C-U>
+ >   map <MouseUp> <C-E>
+ >   map <S-MouseUp> <C-D>
+ You can also use Alt and Ctrl modifiers.
+
+ This only works when Vim gets the scroll wheel events, of course.  You can
+ check if this works with the "xev" program.
+
+ When using Xfree86, the /etc/XF86Config file should have the correct entry for
+ your mouse.  For FreeBSD, this entry works for a Logitech scrollmouse:
+ >   Protocol     "MouseMan"
+ >   Device       "/dev/psm0"
+ >   ZAxisMapping 4 5
+ See the Xfree86 documentation for information.

  vim:tw=78:ts=8:sw=8:
*** ../vim-5.5a.13/src/version.c        Thu Sep  9 17:16:27 1999
--- src/version.c       Thu Sep  9 17:15:51 1999
***************
*** 420,420 ****
--- 420,421 ----
 {   /* Add new patch number below this line */
+     14,

--
Mynd you, m00se bites Kan be pretty nasti ...
                "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

--/-/---- Bram Moolenaar ---- [email protected] ---- [email protected] ---\-\--
 \ \    www.vim.org/iccf      www.moolenaar.net       www.vim.org    / /