Patch 8.1.2070
Problem:    Mouse code is spread out.
Solution:   Move mouse terminal code parsing to mouse.c. (Yegappan Lakshmanan,
            closes #4966)
Files:      src/mouse.c, src/proto/mouse.pro, src/proto/term.pro, src/term.c


*** ../vim-8.1.2069/src/mouse.c 2019-09-22 14:11:42.796083779 +0200
--- src/mouse.c 2019-09-23 21:16:30.439643464 +0200
***************
*** 2089,2094 ****
--- 2089,2815 ----
  {
      (void)do_mouse(cap->oap, cap->cmdchar, BACKWARD, cap->count1, 0);
  }
+ 
+ /*
+  * Check if typebuf 'tp' contains a terminal mouse code and returns the
+  * modifiers found in typebuf in 'modifiers'.
+  */
+     int
+ check_termcode_mouse(
+     char_u    *tp,
+     int               *slen,
+     char_u    *key_name,
+     char_u    *modifiers_start,
+     int               idx,
+     int               *modifiers)
+ {
+     int               j;
+     char_u    *p;
+ # if !defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_GUI) \
+     || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE)
+     char_u    bytes[6];
+     int               num_bytes;
+ # endif
+     int               mouse_code = 0;     // init for GCC
+     int               is_click, is_drag;
+     int               wheel_code = 0;
+     int               current_button;
+     static int        held_button = MOUSE_RELEASE;
+     static int        orig_num_clicks = 1;
+     static int        orig_mouse_code = 0x0;
+ # ifdef CHECK_DOUBLE_CLICK
+     static int        orig_mouse_col = 0;
+     static int        orig_mouse_row = 0;
+     static struct timeval  orig_mouse_time = {0, 0};
+     // time of previous mouse click
+     struct timeval  mouse_time;               // time of current mouse click
+     long      timediff;               // elapsed time in msec
+ # endif
+ 
+     is_click = is_drag = FALSE;
+ 
+ # if !defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_GUI) \
+     || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE)
+     if (key_name[0] == KS_MOUSE
+ #  ifdef FEAT_MOUSE_GPM
+           || key_name[0] == KS_GPM_MOUSE
+ #  endif
+        )
+     {
+       /*
+        * For xterm we get "<t_mouse>scr", where
+        *  s == encoded button state:
+        *         0x20 = left button down
+        *         0x21 = middle button down
+        *         0x22 = right button down
+        *         0x23 = any button release
+        *         0x60 = button 4 down (scroll wheel down)
+        *         0x61 = button 5 down (scroll wheel up)
+        *      add 0x04 for SHIFT
+        *      add 0x08 for ALT
+        *      add 0x10 for CTRL
+        *      add 0x20 for mouse drag (0x40 is drag with left button)
+        *      add 0x40 for mouse move (0x80 is move, 0x81 too)
+        *               0x43 (drag + release) is also move
+        *  c == column + ' ' + 1 == column + 33
+        *  r == row + ' ' + 1 == row + 33
+        *
+        * The coordinates are passed on through global variables.
+        * Ugly, but this avoids trouble with mouse clicks at an
+        * unexpected moment and allows for mapping them.
+        */
+       for (;;)
+       {
+ #  ifdef FEAT_GUI
+           if (gui.in_use)
+           {
+               // GUI uses more bits for columns > 223
+               num_bytes = get_bytes_from_buf(tp + *slen, bytes, 5);
+               if (num_bytes == -1)    // not enough coordinates
+                   return -1;
+               mouse_code = bytes[0];
+               mouse_col = 128 * (bytes[1] - ' ' - 1)
+                   + bytes[2] - ' ' - 1;
+               mouse_row = 128 * (bytes[3] - ' ' - 1)
+                   + bytes[4] - ' ' - 1;
+           }
+           else
+ #  endif
+           {
+               num_bytes = get_bytes_from_buf(tp + *slen, bytes, 3);
+               if (num_bytes == -1)    // not enough coordinates
+                   return -1;
+               mouse_code = bytes[0];
+               mouse_col = bytes[1] - ' ' - 1;
+               mouse_row = bytes[2] - ' ' - 1;
+           }
+           *slen += num_bytes;
+ 
+           // If the following bytes is also a mouse code and it has
+           // the same code, dump this one and get the next.  This
+           // makes dragging a whole lot faster.
+ #  ifdef FEAT_GUI
+           if (gui.in_use)
+               j = 3;
+           else
+ #  endif
+               j = get_termcode_len(idx);
+           if (STRNCMP(tp, tp + *slen, (size_t)j) == 0
+                   && tp[*slen + j] == mouse_code
+                   && tp[*slen + j + 1] != NUL
+                   && tp[*slen + j + 2] != NUL
+ #  ifdef FEAT_GUI
+                   && (!gui.in_use
+                       || (tp[*slen + j + 3] != NUL
+                           && tp[*slen + j + 4] != NUL))
+ #  endif
+              )
+               *slen += j;
+           else
+               break;
+       }
+     }
+ 
+     if (key_name[0] == KS_URXVT_MOUSE
+           || key_name[0] == KS_SGR_MOUSE
+           || key_name[0] == KS_SGR_MOUSE_RELEASE)
+     {
+       // URXVT 1015 mouse reporting mode:
+       // Almost identical to xterm mouse mode, except the values
+       // are decimal instead of bytes.
+       //
+       // \033[%d;%d;%dM
+       //             ^-- row
+       //          ^----- column
+       //       ^-------- code
+       //
+       // SGR 1006 mouse reporting mode:
+       // Almost identical to xterm mouse mode, except the values
+       // are decimal instead of bytes.
+       //
+       // \033[<%d;%d;%dM
+       //             ^-- row
+       //          ^----- column
+       //       ^-------- code
+       //
+       // \033[<%d;%d;%dm        : mouse release event
+       //             ^-- row
+       //          ^----- column
+       //       ^-------- code
+       p = modifiers_start;
+       if (p == NULL)
+           return -1;
+ 
+       mouse_code = getdigits(&p);
+       if (*p++ != ';')
+           return -1;
+ 
+       // when mouse reporting is SGR, add 32 to mouse code
+       if (key_name[0] == KS_SGR_MOUSE
+               || key_name[0] == KS_SGR_MOUSE_RELEASE)
+           mouse_code += 32;
+ 
+       if (key_name[0] == KS_SGR_MOUSE_RELEASE)
+           mouse_code |= MOUSE_RELEASE;
+ 
+       mouse_col = getdigits(&p) - 1;
+       if (*p++ != ';')
+           return -1;
+ 
+       mouse_row = getdigits(&p) - 1;
+ 
+       // The modifiers were the mouse coordinates, not the
+       // modifier keys (alt/shift/ctrl/meta) state.
+       *modifiers = 0;
+     }
+ 
+     if (key_name[0] == KS_MOUSE
+ #  ifdef FEAT_MOUSE_GPM
+           || key_name[0] == KS_GPM_MOUSE
+ #  endif
+ #  ifdef FEAT_MOUSE_URXVT
+           || key_name[0] == KS_URXVT_MOUSE
+ #  endif
+           || key_name[0] == KS_SGR_MOUSE
+           || key_name[0] == KS_SGR_MOUSE_RELEASE)
+     {
+ #  if !defined(MSWIN)
+       /*
+        * Handle mouse events.
+        * Recognize the xterm mouse wheel, but not in the GUI, the
+        * Linux console with GPM and the MS-DOS or Win32 console
+        * (multi-clicks use >= 0x60).
+        */
+       if (mouse_code >= MOUSEWHEEL_LOW
+ #   ifdef FEAT_GUI
+               && !gui.in_use
+ #   endif
+ #   ifdef FEAT_MOUSE_GPM
+               && key_name[0] != KS_GPM_MOUSE
+ #   endif
+          )
+       {
+ #   if defined(UNIX) && defined(FEAT_MOUSE_TTY)
+           if (use_xterm_mouse() > 1 && mouse_code >= 0x80)
+               // mouse-move event, using MOUSE_DRAG works
+               mouse_code = MOUSE_DRAG;
+           else
+ #   endif
+               // Keep the mouse_code before it's changed, so that we
+               // remember that it was a mouse wheel click.
+               wheel_code = mouse_code;
+       }
+ #   ifdef FEAT_MOUSE_XTERM
+       else if (held_button == MOUSE_RELEASE
+ #    ifdef FEAT_GUI
+               && !gui.in_use
+ #    endif
+               && (mouse_code == 0x23 || mouse_code == 0x24
+                   || mouse_code == 0x40 || mouse_code == 0x41))
+       {
+           // Apparently 0x23 and 0x24 are used by rxvt scroll wheel.
+           // And 0x40 and 0x41 are used by some xterm emulator.
+           wheel_code = mouse_code - (mouse_code >= 0x40 ? 0x40 : 0x23)
+               + MOUSEWHEEL_LOW;
+       }
+ #   endif
+ 
+ #   if defined(UNIX) && defined(FEAT_MOUSE_TTY)
+       else if (use_xterm_mouse() > 1)
+       {
+           if (mouse_code & MOUSE_DRAG_XTERM)
+               mouse_code |= MOUSE_DRAG;
+       }
+ #   endif
+ #   ifdef FEAT_XCLIPBOARD
+       else if (!(mouse_code & MOUSE_DRAG & ~MOUSE_CLICK_MASK))
+       {
+           if ((mouse_code & MOUSE_RELEASE) == MOUSE_RELEASE)
+               stop_xterm_trace();
+           else
+               start_xterm_trace(mouse_code);
+       }
+ #   endif
+ #  endif
+     }
+ # endif // !UNIX || FEAT_MOUSE_XTERM
+ # ifdef FEAT_MOUSE_NET
+     if (key_name[0] == KS_NETTERM_MOUSE)
+     {
+       int mc, mr;
+ 
+       // expect a rather limited sequence like: balancing {
+       // \033}6,45\r
+       // '6' is the row, 45 is the column
+       p = tp + *slen;
+       mr = getdigits(&p);
+       if (*p++ != ',')
+           return -1;
+       mc = getdigits(&p);
+       if (*p++ != '\r')
+           return -1;
+ 
+       mouse_col = mc - 1;
+       mouse_row = mr - 1;
+       mouse_code = MOUSE_LEFT;
+       *slen += (int)(p - (tp + *slen));
+     }
+ # endif       // FEAT_MOUSE_NET
+ # ifdef FEAT_MOUSE_JSB
+     if (key_name[0] == KS_JSBTERM_MOUSE)
+     {
+       int mult, val, iter, button, status;
+ 
+       /*
+        * JSBTERM Input Model
+        * \033[0~zw uniq escape sequence
+        * (L-x)  Left button pressed - not pressed x not reporting
+        * (M-x)  Middle button pressed - not pressed x not reporting
+        * (R-x)  Right button pressed - not pressed x not reporting
+        * (SDmdu)  Single , Double click, m mouse move d button down
+        *                                                 u button up
+        *  ###   X cursor position padded to 3 digits
+        *  ###   Y cursor position padded to 3 digits
+        * (s-x)  SHIFT key pressed - not pressed x not reporting
+        * (c-x)  CTRL key pressed - not pressed x not reporting
+        * \033\\ terminating sequence
+        */
+       p = tp + *slen;
+       button = mouse_code = 0;
+       switch (*p++)
+       {
+           case 'L': button = 1; break;
+           case '-': break;
+           case 'x': break; // ignore sequence
+           default:  return -1; // Unknown Result
+       }
+       switch (*p++)
+       {
+           case 'M': button |= 2; break;
+           case '-': break;
+           case 'x': break; // ignore sequence
+           default:  return -1; // Unknown Result
+       }
+       switch (*p++)
+       {
+           case 'R': button |= 4; break;
+           case '-': break;
+           case 'x': break; // ignore sequence
+           default:  return -1; // Unknown Result
+       }
+       status = *p++;
+       for (val = 0, mult = 100, iter = 0; iter < 3; iter++,
+               mult /= 10, p++)
+           if (*p >= '0' && *p <= '9')
+               val += (*p - '0') * mult;
+           else
+               return -1;
+       mouse_col = val;
+       for (val = 0, mult = 100, iter = 0; iter < 3; iter++,
+               mult /= 10, p++)
+           if (*p >= '0' && *p <= '9')
+               val += (*p - '0') * mult;
+           else
+               return -1;
+       mouse_row = val;
+       switch (*p++)
+       {
+           case 's': button |= 8; break;  // SHIFT key Pressed
+           case '-': break;  // Not Pressed
+           case 'x': break;  // Not Reporting
+           default:  return -1; // Unknown Result
+       }
+       switch (*p++)
+       {
+           case 'c': button |= 16; break;  // CTRL key Pressed
+           case '-': break;  // Not Pressed
+           case 'x': break;  // Not Reporting
+           default:  return -1; // Unknown Result
+       }
+       if (*p++ != '\033')
+           return -1;
+       if (*p++ != '\\')
+           return -1;
+       switch (status)
+       {
+           case 'D': // Double Click
+           case 'S': // Single Click
+               if (button & 1) mouse_code |= MOUSE_LEFT;
+               if (button & 2) mouse_code |= MOUSE_MIDDLE;
+               if (button & 4) mouse_code |= MOUSE_RIGHT;
+               if (button & 8) mouse_code |= MOUSE_SHIFT;
+               if (button & 16) mouse_code |= MOUSE_CTRL;
+               break;
+           case 'm': // Mouse move
+               if (button & 1) mouse_code |= MOUSE_LEFT;
+               if (button & 2) mouse_code |= MOUSE_MIDDLE;
+               if (button & 4) mouse_code |= MOUSE_RIGHT;
+               if (button & 8) mouse_code |= MOUSE_SHIFT;
+               if (button & 16) mouse_code |= MOUSE_CTRL;
+               if ((button & 7) != 0)
+               {
+                   held_button = mouse_code;
+                   mouse_code |= MOUSE_DRAG;
+               }
+               is_drag = TRUE;
+               showmode();
+               break;
+           case 'd': // Button Down
+               if (button & 1) mouse_code |= MOUSE_LEFT;
+               if (button & 2) mouse_code |= MOUSE_MIDDLE;
+               if (button & 4) mouse_code |= MOUSE_RIGHT;
+               if (button & 8) mouse_code |= MOUSE_SHIFT;
+               if (button & 16) mouse_code |= MOUSE_CTRL;
+               break;
+           case 'u': // Button Up
+               if (button & 1)
+                   mouse_code |= MOUSE_LEFT | MOUSE_RELEASE;
+               if (button & 2)
+                   mouse_code |= MOUSE_MIDDLE | MOUSE_RELEASE;
+               if (button & 4)
+                   mouse_code |= MOUSE_RIGHT | MOUSE_RELEASE;
+               if (button & 8)
+                   mouse_code |= MOUSE_SHIFT;
+               if (button & 16)
+                   mouse_code |= MOUSE_CTRL;
+               break;
+           default: return -1; // Unknown Result
+       }
+ 
+       *slen += (p - (tp + *slen));
+     }
+ # endif // FEAT_MOUSE_JSB
+ # ifdef FEAT_MOUSE_DEC
+     if (key_name[0] == KS_DEC_MOUSE)
+     {
+       /*
+        * The DEC Locator Input Model
+        * Netterm delivers the code sequence:
+        *  \033[2;4;24;80&w  (left button down)
+        *  \033[3;0;24;80&w  (left button up)
+        *  \033[6;1;24;80&w  (right button down)
+        *  \033[7;0;24;80&w  (right button up)
+        * CSI Pe ; Pb ; Pr ; Pc ; Pp & w
+        * Pe is the event code
+        * Pb is the button code
+        * Pr is the row coordinate
+        * Pc is the column coordinate
+        * Pp is the third coordinate (page number)
+        * Pe, the event code indicates what event caused this report
+        *    The following event codes are defined:
+        *    0 - request, the terminal received an explicit request
+        *       for a locator report, but the locator is unavailable
+        *    1 - request, the terminal received an explicit request
+        *       for a locator report
+        *    2 - left button down
+        *    3 - left button up
+        *    4 - middle button down
+        *    5 - middle button up
+        *    6 - right button down
+        *    7 - right button up
+        *    8 - fourth button down
+        *    9 - fourth button up
+        *    10 - locator outside filter rectangle
+        * Pb, the button code, ASCII decimal 0-15 indicating which
+        *   buttons are down if any. The state of the four buttons
+        *   on the locator correspond to the low four bits of the
+        *   decimal value,
+        *   "1" means button depressed
+        *   0 - no buttons down,
+        *   1 - right,
+        *   2 - middle,
+        *   4 - left,
+        *   8 - fourth
+        * Pr is the row coordinate of the locator position in the page,
+        *   encoded as an ASCII decimal value.
+        *   If Pr is omitted, the locator position is undefined
+        *   (outside the terminal window for example).
+        * Pc is the column coordinate of the locator position in the
+        *   page, encoded as an ASCII decimal value.
+        *   If Pc is omitted, the locator position is undefined
+        *   (outside the terminal window for example).
+        * Pp is the page coordinate of the locator position
+        *   encoded as an ASCII decimal value.
+        *   The page coordinate may be omitted if the locator is on
+        *   page one (the default).  We ignore it anyway.
+        */
+       int Pe, Pb, Pr, Pc;
+ 
+       p = tp + *slen;
+ 
+       // get event status
+       Pe = getdigits(&p);
+       if (*p++ != ';')
+           return -1;
+ 
+       // get button status
+       Pb = getdigits(&p);
+       if (*p++ != ';')
+           return -1;
+ 
+       // get row status
+       Pr = getdigits(&p);
+       if (*p++ != ';')
+           return -1;
+ 
+       // get column status
+       Pc = getdigits(&p);
+ 
+       // the page parameter is optional
+       if (*p == ';')
+       {
+           p++;
+           (void)getdigits(&p);
+       }
+       if (*p++ != '&')
+           return -1;
+       if (*p++ != 'w')
+           return -1;
+ 
+       mouse_code = 0;
+       switch (Pe)
+       {
+           case  0: return -1; // position request while unavailable
+           case  1: // a response to a locator position request includes
+                    // the status of all buttons
+                    Pb &= 7;   // mask off and ignore fourth button
+                    if (Pb & 4)
+                        mouse_code  = MOUSE_LEFT;
+                    if (Pb & 2)
+                        mouse_code  = MOUSE_MIDDLE;
+                    if (Pb & 1)
+                        mouse_code  = MOUSE_RIGHT;
+                    if (Pb)
+                    {
+                        held_button = mouse_code;
+                        mouse_code |= MOUSE_DRAG;
+                        WantQueryMouse = TRUE;
+                    }
+                    is_drag = TRUE;
+                    showmode();
+                    break;
+           case  2: mouse_code = MOUSE_LEFT;
+                    WantQueryMouse = TRUE;
+                    break;
+           case  3: mouse_code = MOUSE_RELEASE | MOUSE_LEFT;
+                    break;
+           case  4: mouse_code = MOUSE_MIDDLE;
+                    WantQueryMouse = TRUE;
+                    break;
+           case  5: mouse_code = MOUSE_RELEASE | MOUSE_MIDDLE;
+                    break;
+           case  6: mouse_code = MOUSE_RIGHT;
+                    WantQueryMouse = TRUE;
+                    break;
+           case  7: mouse_code = MOUSE_RELEASE | MOUSE_RIGHT;
+                    break;
+           case  8: return -1; // fourth button down
+           case  9: return -1; // fourth button up
+           case 10: return -1; // mouse outside of filter rectangle
+           default: return -1; // should never occur
+       }
+ 
+       mouse_col = Pc - 1;
+       mouse_row = Pr - 1;
+ 
+       *slen += (int)(p - (tp + *slen));
+     }
+ # endif // FEAT_MOUSE_DEC
+ # ifdef FEAT_MOUSE_PTERM
+     if (key_name[0] == KS_PTERM_MOUSE)
+     {
+       int button, num_clicks, action;
+ 
+       p = tp + *slen;
+ 
+       action = getdigits(&p);
+       if (*p++ != ';')
+           return -1;
+ 
+       mouse_row = getdigits(&p);
+       if (*p++ != ';')
+           return -1;
+       mouse_col = getdigits(&p);
+       if (*p++ != ';')
+           return -1;
+ 
+       button = getdigits(&p);
+       mouse_code = 0;
+ 
+       switch (button)
+       {
+           case 4: mouse_code = MOUSE_LEFT; break;
+           case 1: mouse_code = MOUSE_RIGHT; break;
+           case 2: mouse_code = MOUSE_MIDDLE; break;
+           default: return -1;
+       }
+ 
+       switch (action)
+       {
+           case 31: // Initial press
+               if (*p++ != ';')
+                   return -1;
+ 
+               num_clicks = getdigits(&p); // Not used
+               break;
+ 
+           case 32: // Release
+               mouse_code |= MOUSE_RELEASE;
+               break;
+ 
+           case 33: // Drag
+               held_button = mouse_code;
+               mouse_code |= MOUSE_DRAG;
+               break;
+ 
+           default:
+               return -1;
+       }
+ 
+       if (*p++ != 't')
+           return -1;
+ 
+       *slen += (p - (tp + *slen));
+     }
+ # endif // FEAT_MOUSE_PTERM
+ 
+     // Interpret the mouse code
+     current_button = (mouse_code & MOUSE_CLICK_MASK);
+     if (current_button == MOUSE_RELEASE
+ # ifdef FEAT_MOUSE_XTERM
+           && wheel_code == 0
+ # endif
+        )
+     {
+       /*
+        * If we get a mouse drag or release event when
+        * there is no mouse button held down (held_button ==
+        * MOUSE_RELEASE), produce a K_IGNORE below.
+        * (can happen when you hold down two buttons
+        * and then let them go, or click in the menu bar, but not
+        * on a menu, and drag into the text).
+        */
+       if ((mouse_code & MOUSE_DRAG) == MOUSE_DRAG)
+           is_drag = TRUE;
+       current_button = held_button;
+     }
+     else if (wheel_code == 0)
+     {
+ # ifdef CHECK_DOUBLE_CLICK
+ #  ifdef FEAT_MOUSE_GPM
+       /*
+        * Only for Unix, when GUI not active, we handle
+        * multi-clicks here, but not for GPM mouse events.
+        */
+ #   ifdef FEAT_GUI
+       if (key_name[0] != KS_GPM_MOUSE && !gui.in_use)
+ #   else
+           if (key_name[0] != KS_GPM_MOUSE)
+ #   endif
+ #  else
+ #   ifdef FEAT_GUI
+               if (!gui.in_use)
+ #   endif
+ #  endif
+               {
+                   /*
+                    * Compute the time elapsed since the previous mouse click.
+                    */
+                   gettimeofday(&mouse_time, NULL);
+                   if (orig_mouse_time.tv_sec == 0)
+                   {
+                       /*
+                        * Avoid computing the difference between mouse_time
+                        * and orig_mouse_time for the first click, as the
+                        * difference would be huge and would cause
+                        * multiplication overflow.
+                        */
+                       timediff = p_mouset;
+                   }
+                   else
+                   {
+                       timediff = (mouse_time.tv_usec
+                               - orig_mouse_time.tv_usec) / 1000;
+                       if (timediff < 0)
+                           --orig_mouse_time.tv_sec;
+                       timediff += (mouse_time.tv_sec
+                               - orig_mouse_time.tv_sec) * 1000;
+                   }
+                   orig_mouse_time = mouse_time;
+                   if (mouse_code == orig_mouse_code
+                           && timediff < p_mouset
+                           && orig_num_clicks != 4
+                           && orig_mouse_col == mouse_col
+                           && orig_mouse_row == mouse_row
+                           && (is_mouse_topline(curwin)
+                               // Double click in tab pages line also works
+                               // when window contents changes.
+                               || (mouse_row == 0 && firstwin->w_winrow > 0))
+                      )
+                       ++orig_num_clicks;
+                   else
+                       orig_num_clicks = 1;
+                   orig_mouse_col = mouse_col;
+                   orig_mouse_row = mouse_row;
+                   set_mouse_topline(curwin);
+               }
+ #  if defined(FEAT_GUI) || defined(FEAT_MOUSE_GPM)
+               else
+                   orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
+ #  endif
+ # else
+       orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
+ # endif
+       is_click = TRUE;
+       orig_mouse_code = mouse_code;
+     }
+     if (!is_drag)
+       held_button = mouse_code & MOUSE_CLICK_MASK;
+ 
+     /*
+      * Translate the actual mouse event into a pseudo mouse event.
+      * First work out what modifiers are to be used.
+      */
+     if (orig_mouse_code & MOUSE_SHIFT)
+       *modifiers |= MOD_MASK_SHIFT;
+     if (orig_mouse_code & MOUSE_CTRL)
+       *modifiers |= MOD_MASK_CTRL;
+     if (orig_mouse_code & MOUSE_ALT)
+       *modifiers |= MOD_MASK_ALT;
+     if (orig_num_clicks == 2)
+       *modifiers |= MOD_MASK_2CLICK;
+     else if (orig_num_clicks == 3)
+       *modifiers |= MOD_MASK_3CLICK;
+     else if (orig_num_clicks == 4)
+       *modifiers |= MOD_MASK_4CLICK;
+ 
+     // Work out our pseudo mouse event. Note that MOUSE_RELEASE gets
+     // added, then it's not mouse up/down.
+     key_name[0] = KS_EXTRA;
+     if (wheel_code != 0
+           && (wheel_code & MOUSE_RELEASE) != MOUSE_RELEASE)
+     {
+       if (wheel_code & MOUSE_CTRL)
+           *modifiers |= MOD_MASK_CTRL;
+       if (wheel_code & MOUSE_ALT)
+           *modifiers |= MOD_MASK_ALT;
+       key_name[1] = (wheel_code & 1)
+           ? (int)KE_MOUSEUP : (int)KE_MOUSEDOWN;
+       held_button = MOUSE_RELEASE;
+     }
+     else
+       key_name[1] = get_pseudo_mouse_code(current_button,
+               is_click, is_drag);
+ 
+     // Make sure the mouse position is valid.  Some terminals may
+     // return weird values.
+     if (mouse_col >= Columns)
+       mouse_col = Columns - 1;
+     if (mouse_row >= Rows)
+       mouse_row = Rows - 1;
+ 
+     return 0;
+ }
  #endif // FEAT_MOUSE
  
  // Functions also used for popup windows.
*** ../vim-8.1.2069/src/proto/mouse.pro 2019-09-21 20:46:14.728275744 +0200
--- src/proto/mouse.pro 2019-09-23 21:03:33.423409913 +0200
***************
*** 13,18 ****
--- 13,19 ----
  int jump_to_mouse(int flags, int *inclusive, int which_button);
  void nv_mousescroll(cmdarg_T *cap);
  void nv_mouse(cmdarg_T *cap);
+ int check_termcode_mouse(char_u *tp, int *slen, char_u *key_name, char_u 
*modifiers_start, int idx, int *modifiers);
  int mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump, int 
*plines_cache);
  win_T *mouse_find_win(int *rowp, int *colp, mouse_find_T popup);
  int vcol2col(win_T *wp, linenr_T lnum, int vcol);
*** ../vim-8.1.2069/src/proto/term.pro  2019-09-21 20:46:14.728275744 +0200
--- src/proto/term.pro  2019-09-23 21:03:33.423409913 +0200
***************
*** 32,37 ****
--- 32,38 ----
  void term_pop_title(int which);
  void ttest(int pairs);
  void add_long_to_buf(long_u val, char_u *dst);
+ int get_bytes_from_buf(char_u *buf, char_u *bytes, int num_bytes);
  void check_shellsize(void);
  void limit_screen_size(void);
  void win_new_shellsize(void);
***************
*** 59,66 ****
--- 60,69 ----
  void add_termcode(char_u *name, char_u *string, int flags);
  char_u *find_termcode(char_u *name);
  char_u *get_termcode(int i);
+ int get_termcode_len(int idx);
  void del_termcode(char_u *name);
  void set_mouse_topline(win_T *wp);
+ int is_mouse_topline(win_T *wp);
  int check_termcode(int max_offset, char_u *buf, int bufsize, int *buflen);
  void term_get_fg_color(char_u *r, char_u *g, char_u *b);
  void term_get_bg_color(char_u *r, char_u *g, char_u *b);
*** ../vim-8.1.2069/src/term.c  2019-09-21 20:46:14.728275744 +0200
--- src/term.c  2019-09-23 21:08:57.549810238 +0200
***************
*** 82,92 ****
  static void got_code_from_term(char_u *code, int len);
  static void check_for_codes_from_term(void);
  #endif
- #if defined(FEAT_GUI) \
-     || (defined(FEAT_MOUSE) && (!defined(UNIX) || defined(FEAT_MOUSE_XTERM) \
-               || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE)))
- static int get_bytes_from_buf(char_u *, char_u *, int);
- #endif
  static void del_termcode_idx(int idx);
  static int find_term_bykeys(char_u *src);
  static int term_is_builtin(char_u *name);
--- 82,87 ----
***************
*** 3160,3166 ****
   * from buf (between num_bytes and num_bytes*2), or -1 if not enough bytes 
were
   * available.
   */
!     static int
  get_bytes_from_buf(char_u *buf, char_u *bytes, int num_bytes)
  {
      int           len = 0;
--- 3155,3161 ----
   * from buf (between num_bytes and num_bytes*2), or -1 if not enough bytes 
were
   * available.
   */
!     int
  get_bytes_from_buf(char_u *buf, char_u *bytes, int num_bytes)
  {
      int           len = 0;
***************
*** 4094,4099 ****
--- 4089,4103 ----
      return &termcodes[i].name[0];
  }
  
+ /*
+  * Returns the length of the terminal code at index 'idx'.
+  */
+     int
+ get_termcode_len(int idx)
+ {
+     return termcodes[idx].len;
+ }
+ 
      void
  del_termcode(char_u *name)
  {
***************
*** 4178,4183 ****
--- 4182,4201 ----
      orig_topfill = wp->w_topfill;
  # endif
  }
+ 
+ /*
+  * Returns TRUE if the top line and top fill of window 'wp' matches the saved
+  * topline and topfill.
+  */
+     int
+ is_mouse_topline(win_T *wp)
+ {
+     return orig_topline == wp->w_topline
+ #ifdef FEAT_DIFF
+       && orig_topfill == wp->w_topfill
+ #endif
+       ;
+ }
  #endif
  
  /*
***************
*** 4216,4243 ****
      char_u    string[MAX_KEY_CODE_LEN + 1];
      int               i, j;
      int               idx = 0;
- #ifdef FEAT_MOUSE
- # if !defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_GUI) \
-     || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE)
-     char_u    bytes[6];
-     int               num_bytes;
- # endif
-     int               mouse_code = 0;     /* init for GCC */
-     int               is_click, is_drag;
-     int               wheel_code = 0;
-     int               current_button;
-     static int        held_button = MOUSE_RELEASE;
-     static int        orig_num_clicks = 1;
-     static int        orig_mouse_code = 0x0;
- # ifdef CHECK_DOUBLE_CLICK
-     static int        orig_mouse_col = 0;
-     static int        orig_mouse_row = 0;
-     static struct timeval  orig_mouse_time = {0, 0};
-                                       /* time of previous mouse click */
-     struct timeval  mouse_time;               /* time of current mouse click 
*/
-     long      timediff;               /* elapsed time in msec */
- # endif
- #endif
      int               cpo_koffset;
  
      cpo_koffset = (vim_strchr(p_cpo, CPO_KOFFSET) != NULL);
--- 4234,4239 ----
***************
*** 4958,4965 ****
                    || key_name[1] == (int)KE_MOUSEDOWN
                    || key_name[1] == (int)KE_MOUSEUP))
        {
!           num_bytes = get_bytes_from_buf(tp + slen, bytes, 4);
!           if (num_bytes == -1)        /* not enough coordinates */
                return -1;
            mouse_col = 128 * (bytes[0] - ' ' - 1) + bytes[1] - ' ' - 1;
            mouse_row = 128 * (bytes[2] - ' ' - 1) + bytes[3] - ' ' - 1;
--- 4954,4963 ----
                    || key_name[1] == (int)KE_MOUSEDOWN
                    || key_name[1] == (int)KE_MOUSEUP))
        {
!           char_u      bytes[6];
!           int         num_bytes = get_bytes_from_buf(tp + slen, bytes, 4);
! 
!           if (num_bytes == -1)        // not enough coordinates
                return -1;
            mouse_col = 128 * (bytes[0] - ' ' - 1) + bytes[1] - ' ' - 1;
            mouse_row = 128 * (bytes[2] - ' ' - 1) + bytes[3] - ' ' - 1;
***************
*** 4992,5686 ****
                || key_name[0] == KS_SGR_MOUSE
                || key_name[0] == KS_SGR_MOUSE_RELEASE)
        {
!           is_click = is_drag = FALSE;
! 
! # if !defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_GUI) \
!           || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE)
!           if (key_name[0] == KS_MOUSE
! #  ifdef FEAT_MOUSE_GPM
!                   || key_name[0] == KS_GPM_MOUSE
! #  endif
!              )
!           {
!               /*
!                * For xterm we get "<t_mouse>scr", where
!                *  s == encoded button state:
!                *         0x20 = left button down
!                *         0x21 = middle button down
!                *         0x22 = right button down
!                *         0x23 = any button release
!                *         0x60 = button 4 down (scroll wheel down)
!                *         0x61 = button 5 down (scroll wheel up)
!                *      add 0x04 for SHIFT
!                *      add 0x08 for ALT
!                *      add 0x10 for CTRL
!                *      add 0x20 for mouse drag (0x40 is drag with left button)
!                *      add 0x40 for mouse move (0x80 is move, 0x81 too)
!                *               0x43 (drag + release) is also move
!                *  c == column + ' ' + 1 == column + 33
!                *  r == row + ' ' + 1 == row + 33
!                *
!                * The coordinates are passed on through global variables.
!                * Ugly, but this avoids trouble with mouse clicks at an
!                * unexpected moment and allows for mapping them.
!                */
!               for (;;)
!               {
! #  ifdef FEAT_GUI
!                   if (gui.in_use)
!                   {
!                       /* GUI uses more bits for columns > 223 */
!                       num_bytes = get_bytes_from_buf(tp + slen, bytes, 5);
!                       if (num_bytes == -1)    /* not enough coordinates */
!                           return -1;
!                       mouse_code = bytes[0];
!                       mouse_col = 128 * (bytes[1] - ' ' - 1)
!                                                        + bytes[2] - ' ' - 1;
!                       mouse_row = 128 * (bytes[3] - ' ' - 1)
!                                                        + bytes[4] - ' ' - 1;
!                   }
!                   else
! #  endif
!                   {
!                       num_bytes = get_bytes_from_buf(tp + slen, bytes, 3);
!                       if (num_bytes == -1)    /* not enough coordinates */
!                           return -1;
!                       mouse_code = bytes[0];
!                       mouse_col = bytes[1] - ' ' - 1;
!                       mouse_row = bytes[2] - ' ' - 1;
!                   }
!                   slen += num_bytes;
! 
!                   /* If the following bytes is also a mouse code and it has
!                    * the same code, dump this one and get the next.  This
!                    * makes dragging a whole lot faster. */
! #  ifdef FEAT_GUI
!                   if (gui.in_use)
!                       j = 3;
!                   else
! #  endif
!                       j = termcodes[idx].len;
!                   if (STRNCMP(tp, tp + slen, (size_t)j) == 0
!                           && tp[slen + j] == mouse_code
!                           && tp[slen + j + 1] != NUL
!                           && tp[slen + j + 2] != NUL
! #  ifdef FEAT_GUI
!                           && (!gui.in_use
!                               || (tp[slen + j + 3] != NUL
!                                       && tp[slen + j + 4] != NUL))
! #  endif
!                           )
!                       slen += j;
!                   else
!                       break;
!               }
!           }
! 
!           if (key_name[0] == KS_URXVT_MOUSE
!               || key_name[0] == KS_SGR_MOUSE
!               || key_name[0] == KS_SGR_MOUSE_RELEASE)
!           {
!               /* URXVT 1015 mouse reporting mode:
!                * Almost identical to xterm mouse mode, except the values
!                * are decimal instead of bytes.
!                *
!                * \033[%d;%d;%dM
!                *             ^-- row
!                *          ^----- column
!                *       ^-------- code
!                *
!                * SGR 1006 mouse reporting mode:
!                * Almost identical to xterm mouse mode, except the values
!                * are decimal instead of bytes.
!                *
!                * \033[<%d;%d;%dM
!                *             ^-- row
!                *          ^----- column
!                *       ^-------- code
!                *
!                * \033[<%d;%d;%dm        : mouse release event
!                *             ^-- row
!                *          ^----- column
!                *       ^-------- code
!                */
!               p = modifiers_start;
!               if (p == NULL)
!                   return -1;
! 
!               mouse_code = getdigits(&p);
!               if (*p++ != ';')
!                   return -1;
! 
!               /* when mouse reporting is SGR, add 32 to mouse code */
!               if (key_name[0] == KS_SGR_MOUSE
!                                   || key_name[0] == KS_SGR_MOUSE_RELEASE)
!                   mouse_code += 32;
! 
!               if (key_name[0] == KS_SGR_MOUSE_RELEASE)
!                   mouse_code |= MOUSE_RELEASE;
! 
!               mouse_col = getdigits(&p) - 1;
!               if (*p++ != ';')
!                   return -1;
! 
!               mouse_row = getdigits(&p) - 1;
! 
!               /* The modifiers were the mouse coordinates, not the
!                * modifier keys (alt/shift/ctrl/meta) state. */
!               modifiers = 0;
!           }
! 
!       if (key_name[0] == KS_MOUSE
! #  ifdef FEAT_MOUSE_GPM
!           || key_name[0] == KS_GPM_MOUSE
! #  endif
! #  ifdef FEAT_MOUSE_URXVT
!           || key_name[0] == KS_URXVT_MOUSE
! #  endif
!           || key_name[0] == KS_SGR_MOUSE
!           || key_name[0] == KS_SGR_MOUSE_RELEASE)
!       {
! #  if !defined(MSWIN)
!               /*
!                * Handle mouse events.
!                * Recognize the xterm mouse wheel, but not in the GUI, the
!                * Linux console with GPM and the MS-DOS or Win32 console
!                * (multi-clicks use >= 0x60).
!                */
!               if (mouse_code >= MOUSEWHEEL_LOW
! #   ifdef FEAT_GUI
!                       && !gui.in_use
! #   endif
! #   ifdef FEAT_MOUSE_GPM
!                       && key_name[0] != KS_GPM_MOUSE
! #   endif
!                       )
!               {
! #   if defined(UNIX) && defined(FEAT_MOUSE_TTY)
!                   if (use_xterm_mouse() > 1 && mouse_code >= 0x80)
!                       /* mouse-move event, using MOUSE_DRAG works */
!                       mouse_code = MOUSE_DRAG;
!                   else
! #   endif
!                       /* Keep the mouse_code before it's changed, so that we
!                        * remember that it was a mouse wheel click. */
!                       wheel_code = mouse_code;
!               }
! #   ifdef FEAT_MOUSE_XTERM
!               else if (held_button == MOUSE_RELEASE
! #    ifdef FEAT_GUI
!                       && !gui.in_use
! #    endif
!                       && (mouse_code == 0x23 || mouse_code == 0x24
!                           || mouse_code == 0x40 || mouse_code == 0x41))
!               {
!                   /* Apparently 0x23 and 0x24 are used by rxvt scroll wheel.
!                    * And 0x40 and 0x41 are used by some xterm emulator. */
!                   wheel_code = mouse_code - (mouse_code >= 0x40 ? 0x40 : 0x23)
!                                                             + MOUSEWHEEL_LOW;
!               }
! #   endif
! 
! #   if defined(UNIX) && defined(FEAT_MOUSE_TTY)
!               else if (use_xterm_mouse() > 1)
!               {
!                   if (mouse_code & MOUSE_DRAG_XTERM)
!                       mouse_code |= MOUSE_DRAG;
!               }
! #   endif
! #   ifdef FEAT_XCLIPBOARD
!               else if (!(mouse_code & MOUSE_DRAG & ~MOUSE_CLICK_MASK))
!               {
!                   if ((mouse_code & MOUSE_RELEASE) == MOUSE_RELEASE)
!                       stop_xterm_trace();
!                   else
!                       start_xterm_trace(mouse_code);
!               }
! #   endif
! #  endif
!           }
! # endif /* !UNIX || FEAT_MOUSE_XTERM */
! # ifdef FEAT_MOUSE_NET
!           if (key_name[0] == KS_NETTERM_MOUSE)
!           {
!               int mc, mr;
! 
!               /* expect a rather limited sequence like: balancing {
!                * \033}6,45\r
!                * '6' is the row, 45 is the column
!                */
!               p = tp + slen;
!               mr = getdigits(&p);
!               if (*p++ != ',')
!                   return -1;
!               mc = getdigits(&p);
!               if (*p++ != '\r')
!                   return -1;
! 
!               mouse_col = mc - 1;
!               mouse_row = mr - 1;
!               mouse_code = MOUSE_LEFT;
!               slen += (int)(p - (tp + slen));
!           }
! # endif       /* FEAT_MOUSE_NET */
! # ifdef FEAT_MOUSE_JSB
!           if (key_name[0] == KS_JSBTERM_MOUSE)
!           {
!               int mult, val, iter, button, status;
! 
!               /* JSBTERM Input Model
!                * \033[0~zw uniq escape sequence
!                * (L-x)  Left button pressed - not pressed x not reporting
!                * (M-x)  Middle button pressed - not pressed x not reporting
!                * (R-x)  Right button pressed - not pressed x not reporting
!                * (SDmdu)  Single , Double click, m mouse move d button down
!                *                                                 u button up
!                *  ###   X cursor position padded to 3 digits
!                *  ###   Y cursor position padded to 3 digits
!                * (s-x)  SHIFT key pressed - not pressed x not reporting
!                * (c-x)  CTRL key pressed - not pressed x not reporting
!                * \033\\ terminating sequence
!                */
! 
!               p = tp + slen;
!               button = mouse_code = 0;
!               switch (*p++)
!               {
!                   case 'L': button = 1; break;
!                   case '-': break;
!                   case 'x': break; /* ignore sequence */
!                   default:  return -1; /* Unknown Result */
!               }
!               switch (*p++)
!               {
!                   case 'M': button |= 2; break;
!                   case '-': break;
!                   case 'x': break; /* ignore sequence */
!                   default:  return -1; /* Unknown Result */
!               }
!               switch (*p++)
!               {
!                   case 'R': button |= 4; break;
!                   case '-': break;
!                   case 'x': break; /* ignore sequence */
!                   default:  return -1; /* Unknown Result */
!               }
!               status = *p++;
!               for (val = 0, mult = 100, iter = 0; iter < 3; iter++,
!                                                             mult /= 10, p++)
!                   if (*p >= '0' && *p <= '9')
!                       val += (*p - '0') * mult;
!                   else
!                       return -1;
!               mouse_col = val;
!               for (val = 0, mult = 100, iter = 0; iter < 3; iter++,
!                                                             mult /= 10, p++)
!                   if (*p >= '0' && *p <= '9')
!                       val += (*p - '0') * mult;
!                   else
!                       return -1;
!               mouse_row = val;
!               switch (*p++)
!               {
!                   case 's': button |= 8; break;  /* SHIFT key Pressed */
!                   case '-': break;  /* Not Pressed */
!                   case 'x': break;  /* Not Reporting */
!                   default:  return -1; /* Unknown Result */
!               }
!               switch (*p++)
!               {
!                   case 'c': button |= 16; break;  /* CTRL key Pressed */
!                   case '-': break;  /* Not Pressed */
!                   case 'x': break;  /* Not Reporting */
!                   default:  return -1; /* Unknown Result */
!               }
!               if (*p++ != '\033')
!                   return -1;
!               if (*p++ != '\\')
!                   return -1;
!               switch (status)
!               {
!                   case 'D': /* Double Click */
!                   case 'S': /* Single Click */
!                       if (button & 1) mouse_code |= MOUSE_LEFT;
!                       if (button & 2) mouse_code |= MOUSE_MIDDLE;
!                       if (button & 4) mouse_code |= MOUSE_RIGHT;
!                       if (button & 8) mouse_code |= MOUSE_SHIFT;
!                       if (button & 16) mouse_code |= MOUSE_CTRL;
!                       break;
!                   case 'm': /* Mouse move */
!                       if (button & 1) mouse_code |= MOUSE_LEFT;
!                       if (button & 2) mouse_code |= MOUSE_MIDDLE;
!                       if (button & 4) mouse_code |= MOUSE_RIGHT;
!                       if (button & 8) mouse_code |= MOUSE_SHIFT;
!                       if (button & 16) mouse_code |= MOUSE_CTRL;
!                       if ((button & 7) != 0)
!                       {
!                           held_button = mouse_code;
!                           mouse_code |= MOUSE_DRAG;
!                       }
!                       is_drag = TRUE;
!                       showmode();
!                       break;
!                   case 'd': /* Button Down */
!                       if (button & 1) mouse_code |= MOUSE_LEFT;
!                       if (button & 2) mouse_code |= MOUSE_MIDDLE;
!                       if (button & 4) mouse_code |= MOUSE_RIGHT;
!                       if (button & 8) mouse_code |= MOUSE_SHIFT;
!                       if (button & 16) mouse_code |= MOUSE_CTRL;
!                       break;
!                   case 'u': /* Button Up */
!                       if (button & 1)
!                           mouse_code |= MOUSE_LEFT | MOUSE_RELEASE;
!                       if (button & 2)
!                           mouse_code |= MOUSE_MIDDLE | MOUSE_RELEASE;
!                       if (button & 4)
!                           mouse_code |= MOUSE_RIGHT | MOUSE_RELEASE;
!                       if (button & 8)
!                           mouse_code |= MOUSE_SHIFT;
!                       if (button & 16)
!                           mouse_code |= MOUSE_CTRL;
!                       break;
!                   default: return -1; /* Unknown Result */
!               }
! 
!               slen += (p - (tp + slen));
!           }
! # endif /* FEAT_MOUSE_JSB */
! # ifdef FEAT_MOUSE_DEC
!           if (key_name[0] == KS_DEC_MOUSE)
!           {
!              /* The DEC Locator Input Model
!               * Netterm delivers the code sequence:
!               *  \033[2;4;24;80&w  (left button down)
!               *  \033[3;0;24;80&w  (left button up)
!               *  \033[6;1;24;80&w  (right button down)
!               *  \033[7;0;24;80&w  (right button up)
!               * CSI Pe ; Pb ; Pr ; Pc ; Pp & w
!               * Pe is the event code
!               * Pb is the button code
!               * Pr is the row coordinate
!               * Pc is the column coordinate
!               * Pp is the third coordinate (page number)
!               * Pe, the event code indicates what event caused this report
!               *    The following event codes are defined:
!               *    0 - request, the terminal received an explicit request
!               *        for a locator report, but the locator is unavailable
!               *    1 - request, the terminal received an explicit request
!               *        for a locator report
!               *    2 - left button down
!               *    3 - left button up
!               *    4 - middle button down
!               *    5 - middle button up
!               *    6 - right button down
!               *    7 - right button up
!               *    8 - fourth button down
!               *    9 - fourth button up
!               *    10 - locator outside filter rectangle
!               * Pb, the button code, ASCII decimal 0-15 indicating which
!               *   buttons are down if any. The state of the four buttons
!               *   on the locator correspond to the low four bits of the
!               *   decimal value,
!               *   "1" means button depressed
!               *   0 - no buttons down,
!               *   1 - right,
!               *   2 - middle,
!               *   4 - left,
!               *   8 - fourth
!               * Pr is the row coordinate of the locator position in the page,
!               *   encoded as an ASCII decimal value.
!               *   If Pr is omitted, the locator position is undefined
!               *   (outside the terminal window for example).
!               * Pc is the column coordinate of the locator position in the
!               *   page, encoded as an ASCII decimal value.
!               *   If Pc is omitted, the locator position is undefined
!               *   (outside the terminal window for example).
!               * Pp is the page coordinate of the locator position
!               *   encoded as an ASCII decimal value.
!               *   The page coordinate may be omitted if the locator is on
!               *   page one (the default).  We ignore it anyway.
!               */
!               int Pe, Pb, Pr, Pc;
! 
!               p = tp + slen;
! 
!               /* get event status */
!               Pe = getdigits(&p);
!               if (*p++ != ';')
!                   return -1;
! 
!               /* get button status */
!               Pb = getdigits(&p);
!               if (*p++ != ';')
!                   return -1;
! 
!               /* get row status */
!               Pr = getdigits(&p);
!               if (*p++ != ';')
!                   return -1;
! 
!               /* get column status */
!               Pc = getdigits(&p);
! 
!               /* the page parameter is optional */
!               if (*p == ';')
!               {
!                   p++;
!                   (void)getdigits(&p);
!               }
!               if (*p++ != '&')
!                   return -1;
!               if (*p++ != 'w')
!                   return -1;
! 
!               mouse_code = 0;
!               switch (Pe)
!               {
!               case  0: return -1; /* position request while unavailable */
!               case  1: /* a response to a locator position request includes
!                           the status of all buttons */
!                        Pb &= 7;   /* mask off and ignore fourth button */
!                        if (Pb & 4)
!                            mouse_code  = MOUSE_LEFT;
!                        if (Pb & 2)
!                            mouse_code  = MOUSE_MIDDLE;
!                        if (Pb & 1)
!                            mouse_code  = MOUSE_RIGHT;
!                        if (Pb)
!                        {
!                            held_button = mouse_code;
!                            mouse_code |= MOUSE_DRAG;
!                            WantQueryMouse = TRUE;
!                        }
!                        is_drag = TRUE;
!                        showmode();
!                        break;
!               case  2: mouse_code = MOUSE_LEFT;
!                        WantQueryMouse = TRUE;
!                        break;
!               case  3: mouse_code = MOUSE_RELEASE | MOUSE_LEFT;
!                        break;
!               case  4: mouse_code = MOUSE_MIDDLE;
!                        WantQueryMouse = TRUE;
!                        break;
!               case  5: mouse_code = MOUSE_RELEASE | MOUSE_MIDDLE;
!                        break;
!               case  6: mouse_code = MOUSE_RIGHT;
!                        WantQueryMouse = TRUE;
!                        break;
!               case  7: mouse_code = MOUSE_RELEASE | MOUSE_RIGHT;
!                        break;
!               case  8: return -1; /* fourth button down */
!               case  9: return -1; /* fourth button up */
!               case 10: return -1; /* mouse outside of filter rectangle */
!               default: return -1; /* should never occur */
!               }
! 
!               mouse_col = Pc - 1;
!               mouse_row = Pr - 1;
! 
!               slen += (int)(p - (tp + slen));
!           }
! # endif /* FEAT_MOUSE_DEC */
! # ifdef FEAT_MOUSE_PTERM
!           if (key_name[0] == KS_PTERM_MOUSE)
!           {
!               int button, num_clicks, action;
! 
!               p = tp + slen;
! 
!               action = getdigits(&p);
!               if (*p++ != ';')
!                   return -1;
! 
!               mouse_row = getdigits(&p);
!               if (*p++ != ';')
!                   return -1;
!               mouse_col = getdigits(&p);
!               if (*p++ != ';')
!                   return -1;
! 
!               button = getdigits(&p);
!               mouse_code = 0;
! 
!               switch (button)
!               {
!                   case 4: mouse_code = MOUSE_LEFT; break;
!                   case 1: mouse_code = MOUSE_RIGHT; break;
!                   case 2: mouse_code = MOUSE_MIDDLE; break;
!                   default: return -1;
!               }
! 
!               switch (action)
!               {
!                   case 31: /* Initial press */
!                       if (*p++ != ';')
!                           return -1;
! 
!                       num_clicks = getdigits(&p); /* Not used */
!                       break;
! 
!                   case 32: /* Release */
!                       mouse_code |= MOUSE_RELEASE;
!                       break;
! 
!                   case 33: /* Drag */
!                       held_button = mouse_code;
!                       mouse_code |= MOUSE_DRAG;
!                       break;
! 
!                   default:
!                       return -1;
!               }
! 
!               if (*p++ != 't')
!                   return -1;
! 
!               slen += (p - (tp + slen));
!           }
! # endif /* FEAT_MOUSE_PTERM */
! 
!           /* Interpret the mouse code */
!           current_button = (mouse_code & MOUSE_CLICK_MASK);
!           if (current_button == MOUSE_RELEASE
! # ifdef FEAT_MOUSE_XTERM
!                   && wheel_code == 0
! # endif
!                   )
!           {
!               /*
!                * If we get a mouse drag or release event when
!                * there is no mouse button held down (held_button ==
!                * MOUSE_RELEASE), produce a K_IGNORE below.
!                * (can happen when you hold down two buttons
!                * and then let them go, or click in the menu bar, but not
!                * on a menu, and drag into the text).
!                */
!               if ((mouse_code & MOUSE_DRAG) == MOUSE_DRAG)
!                   is_drag = TRUE;
!               current_button = held_button;
!           }
!           else if (wheel_code == 0)
!           {
! # ifdef CHECK_DOUBLE_CLICK
! #  ifdef FEAT_MOUSE_GPM
!               /*
!                * Only for Unix, when GUI not active, we handle
!                * multi-clicks here, but not for GPM mouse events.
!                */
! #   ifdef FEAT_GUI
!               if (key_name[0] != KS_GPM_MOUSE && !gui.in_use)
! #   else
!               if (key_name[0] != KS_GPM_MOUSE)
! #   endif
! #  else
! #   ifdef FEAT_GUI
!               if (!gui.in_use)
! #   endif
! #  endif
!               {
!                   /*
!                    * Compute the time elapsed since the previous mouse click.
!                    */
!                   gettimeofday(&mouse_time, NULL);
!                   if (orig_mouse_time.tv_sec == 0)
!                   {
!                       /*
!                        * Avoid computing the difference between mouse_time
!                        * and orig_mouse_time for the first click, as the
!                        * difference would be huge and would cause
!                        * multiplication overflow.
!                        */
!                       timediff = p_mouset;
!                   }
!                   else
!                   {
!                       timediff = (mouse_time.tv_usec
!                                            - orig_mouse_time.tv_usec) / 1000;
!                       if (timediff < 0)
!                           --orig_mouse_time.tv_sec;
!                       timediff += (mouse_time.tv_sec
!                                             - orig_mouse_time.tv_sec) * 1000;
!                   }
!                   orig_mouse_time = mouse_time;
!                   if (mouse_code == orig_mouse_code
!                           && timediff < p_mouset
!                           && orig_num_clicks != 4
!                           && orig_mouse_col == mouse_col
!                           && orig_mouse_row == mouse_row
!                           && ((orig_topline == curwin->w_topline
! #ifdef FEAT_DIFF
!                                   && orig_topfill == curwin->w_topfill
! #endif
!                               )
!                               /* Double click in tab pages line also works
!                                * when window contents changes. */
!                               || (mouse_row == 0 && firstwin->w_winrow > 0))
!                           )
!                       ++orig_num_clicks;
!                   else
!                       orig_num_clicks = 1;
!                   orig_mouse_col = mouse_col;
!                   orig_mouse_row = mouse_row;
!                   orig_topline = curwin->w_topline;
! #ifdef FEAT_DIFF
!                   orig_topfill = curwin->w_topfill;
! #endif
!               }
! #  if defined(FEAT_GUI) || defined(FEAT_MOUSE_GPM)
!               else
!                   orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
! #  endif
! # else
!               orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code);
! # endif
!               is_click = TRUE;
!               orig_mouse_code = mouse_code;
!           }
!           if (!is_drag)
!               held_button = mouse_code & MOUSE_CLICK_MASK;
! 
!           /*
!            * Translate the actual mouse event into a pseudo mouse event.
!            * First work out what modifiers are to be used.
!            */
!           if (orig_mouse_code & MOUSE_SHIFT)
!               modifiers |= MOD_MASK_SHIFT;
!           if (orig_mouse_code & MOUSE_CTRL)
!               modifiers |= MOD_MASK_CTRL;
!           if (orig_mouse_code & MOUSE_ALT)
!               modifiers |= MOD_MASK_ALT;
!           if (orig_num_clicks == 2)
!               modifiers |= MOD_MASK_2CLICK;
!           else if (orig_num_clicks == 3)
!               modifiers |= MOD_MASK_3CLICK;
!           else if (orig_num_clicks == 4)
!               modifiers |= MOD_MASK_4CLICK;
! 
!           /* Work out our pseudo mouse event. Note that MOUSE_RELEASE gets
!            * added, then it's not mouse up/down. */
!           key_name[0] = KS_EXTRA;
!           if (wheel_code != 0
!                             && (wheel_code & MOUSE_RELEASE) != MOUSE_RELEASE)
!           {
!               if (wheel_code & MOUSE_CTRL)
!                   modifiers |= MOD_MASK_CTRL;
!               if (wheel_code & MOUSE_ALT)
!                   modifiers |= MOD_MASK_ALT;
!               key_name[1] = (wheel_code & 1)
!                                       ? (int)KE_MOUSEUP : (int)KE_MOUSEDOWN;
!               held_button = MOUSE_RELEASE;
!           }
!           else
!               key_name[1] = get_pseudo_mouse_code(current_button,
!                                                          is_click, is_drag);
! 
!           /* Make sure the mouse position is valid.  Some terminals may
!            * return weird values. */
!           if (mouse_col >= Columns)
!               mouse_col = Columns - 1;
!           if (mouse_row >= Rows)
!               mouse_row = Rows - 1;
        }
  #endif /* FEAT_MOUSE */
  
--- 4990,4998 ----
                || key_name[0] == KS_SGR_MOUSE
                || key_name[0] == KS_SGR_MOUSE_RELEASE)
        {
!           if (check_termcode_mouse(tp, &slen, key_name, modifiers_start, idx,
!                                                            &modifiers) == -1)
!               return -1;
        }
  #endif /* FEAT_MOUSE */
  
***************
*** 5707,5714 ****
        else if (key_name[0] == (int)KS_MENU)
        {
            long_u      val;
  
-           num_bytes = get_long_from_buf(tp + slen, &val);
            if (num_bytes == -1)
                return -1;
            current_menu = (vimmenu_T *)val;
--- 5019,5026 ----
        else if (key_name[0] == (int)KS_MENU)
        {
            long_u      val;
+           int         num_bytes = get_long_from_buf(tp + slen, &val);
  
            if (num_bytes == -1)
                return -1;
            current_menu = (vimmenu_T *)val;
***************
*** 5726,5733 ****
  # ifdef FEAT_GUI_TABLINE
        else if (key_name[0] == (int)KS_TABLINE)
        {
!           /* Selecting tabline tab or using its menu. */
!           num_bytes = get_bytes_from_buf(tp + slen, bytes, 1);
            if (num_bytes == -1)
                return -1;
            current_tab = (int)bytes[0];
--- 5038,5047 ----
  # ifdef FEAT_GUI_TABLINE
        else if (key_name[0] == (int)KS_TABLINE)
        {
!           // Selecting tabline tab or using its menu.
!           char_u      bytes[6];
!           int         num_bytes = get_bytes_from_buf(tp + slen, bytes, 1);
! 
            if (num_bytes == -1)
                return -1;
            current_tab = (int)bytes[0];
***************
*** 5737,5744 ****
        }
        else if (key_name[0] == (int)KS_TABMENU)
        {
!           /* Selecting tabline tab or using its menu. */
!           num_bytes = get_bytes_from_buf(tp + slen, bytes, 2);
            if (num_bytes == -1)
                return -1;
            current_tab = (int)bytes[0];
--- 5051,5060 ----
        }
        else if (key_name[0] == (int)KS_TABMENU)
        {
!           // Selecting tabline tab or using its menu.
!           char_u      bytes[6];
!           int         num_bytes = get_bytes_from_buf(tp + slen, bytes, 2);
! 
            if (num_bytes == -1)
                return -1;
            current_tab = (int)bytes[0];
***************
*** 5750,5755 ****
--- 5066,5073 ----
        else if (key_name[0] == (int)KS_VER_SCROLLBAR)
        {
            long_u      val;
+           char_u      bytes[6];
+           int         num_bytes;
  
            /* Get the last scrollbar event in the queue of the same type */
            j = 0;
***************
*** 5778,5783 ****
--- 5096,5102 ----
        else if (key_name[0] == (int)KS_HOR_SCROLLBAR)
        {
            long_u      val;
+           int         num_bytes;
  
            /* Get the last horiz. scrollbar event in the queue */
            j = 0;
*** ../vim-8.1.2069/src/version.c       2019-09-22 23:24:09.810153903 +0200
--- src/version.c       2019-09-23 21:04:36.619093086 +0200
***************
*** 759,760 ****
--- 759,762 ----
  {   /* Add new patch number below this line */
+ /**/
+     2070,
  /**/

-- 
Not too long ago, a keyboard was something to make music with...

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/201909231917.x8NJHbiL018163%40masaka.moolenaar.net.

Raspunde prin e-mail lui