]> granicus.if.org Git - vim/commitdiff
patch 8.1.2070: mouse code is spread out v8.1.2070
authorBram Moolenaar <Bram@vim.org>
Mon, 23 Sep 2019 19:16:54 +0000 (21:16 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 23 Sep 2019 19:16:54 +0000 (21:16 +0200)
Problem:    Mouse code is spread out.
Solution:   Move mouse terminal code parsing to mouse.c. (Yegappan Lakshmanan,
            closes #4966)

src/mouse.c
src/proto/mouse.pro
src/proto/term.pro
src/term.c
src/version.c

index bf3973b021acd56800790947f52a254ed874cc87..498ff049bfd9f38403a2bb763d2c465b26aaf6e2 100644 (file)
@@ -2089,6 +2089,727 @@ nv_mouse(cmdarg_T *cap)
 {
     (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.
index fe5cda13422916bdeca1a77a2011bcdd8271a741..3faf056d9491a058774c1200022c1d133d4105ba 100644 (file)
@@ -13,6 +13,7 @@ int mouse_model_popup(void);
 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);
index 50e2f5ea1d6925feafcf5011c0d37f4f0ef27caa..a7a051c34ad09b6eac9f21d08075bf06d777a6d8 100644 (file)
@@ -32,6 +32,7 @@ void term_push_title(int which);
 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,8 +60,10 @@ void clear_termcodes(void);
 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);
index 7d41a6100ee8e909c130fcc28f48717a73945ae8..2319453fb7cf2bd41c7facdacf2666bf83d807e9 100644 (file)
@@ -82,11 +82,6 @@ static void req_more_codes_from_term(void);
 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);
@@ -3160,7 +3155,7 @@ get_long_from_buf(char_u *buf, long_u *val)
  * from buf (between num_bytes and num_bytes*2), or -1 if not enough bytes were
  * available.
  */
-    static int
+    int
 get_bytes_from_buf(char_u *buf, char_u *bytes, int num_bytes)
 {
     int            len = 0;
@@ -4094,6 +4089,15 @@ get_termcode(int i)
     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,6 +4182,20 @@ set_mouse_topline(win_T *wp)
     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,28 +4234,6 @@ check_termcode(
     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);
@@ -4958,8 +4954,10 @@ check_termcode(
                    || 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 */
+           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,695 +4990,9 @@ check_termcode(
                || 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;
+           if (check_termcode_mouse(tp, &slen, key_name, modifiers_start, idx,
+                                                            &modifiers) == -1)
+               return -1;
        }
 #endif /* FEAT_MOUSE */
 
@@ -5707,8 +5019,8 @@ check_termcode(
        else if (key_name[0] == (int)KS_MENU)
        {
            long_u      val;
+           int         num_bytes = get_long_from_buf(tp + slen, &val);
 
-           num_bytes = get_long_from_buf(tp + slen, &val);
            if (num_bytes == -1)
                return -1;
            current_menu = (vimmenu_T *)val;
@@ -5726,8 +5038,10 @@ check_termcode(
 # 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);
+           // 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,8 +5051,10 @@ check_termcode(
        }
        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);
+           // 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,6 +5066,8 @@ check_termcode(
        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,6 +5096,7 @@ check_termcode(
        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;
index bfe483e28a525e6b2275b8e87c7063590bb5da89..7f34d2ac9686b76dea42345bd7e787876df57b5d 100644 (file)
@@ -757,6 +757,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2070,
 /**/
     2069,
 /**/