To: vim_dev@googlegroups.com Subject: Patch 8.1.2070 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 "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 "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 -- Bram@Moolenaar.net -- 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 ///