Mercurial > vim
comparison src/mouse.c @ 18150:0ec6521e9d80 v8.1.2070
patch 8.1.2070: mouse code is spread out
Commit: https://github.com/vim/vim/commit/b8ff5c271ee5dcef6f63436b77e228e062ff9a0e
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Sep 23 21:16:54 2019 +0200
patch 8.1.2070: mouse code is spread out
Problem: Mouse code is spread out.
Solution: Move mouse terminal code parsing to mouse.c. (Yegappan Lakshmanan,
closes #4966)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Mon, 23 Sep 2019 21:30:04 +0200 |
parents | 2cc67e54edf8 |
children | 9f51d0cef8da |
comparison
equal
deleted
inserted
replaced
18149:275fec3af04a | 18150:0ec6521e9d80 |
---|---|
2087 void | 2087 void |
2088 nv_mouse(cmdarg_T *cap) | 2088 nv_mouse(cmdarg_T *cap) |
2089 { | 2089 { |
2090 (void)do_mouse(cap->oap, cap->cmdchar, BACKWARD, cap->count1, 0); | 2090 (void)do_mouse(cap->oap, cap->cmdchar, BACKWARD, cap->count1, 0); |
2091 } | 2091 } |
2092 | |
2093 /* | |
2094 * Check if typebuf 'tp' contains a terminal mouse code and returns the | |
2095 * modifiers found in typebuf in 'modifiers'. | |
2096 */ | |
2097 int | |
2098 check_termcode_mouse( | |
2099 char_u *tp, | |
2100 int *slen, | |
2101 char_u *key_name, | |
2102 char_u *modifiers_start, | |
2103 int idx, | |
2104 int *modifiers) | |
2105 { | |
2106 int j; | |
2107 char_u *p; | |
2108 # if !defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_GUI) \ | |
2109 || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE) | |
2110 char_u bytes[6]; | |
2111 int num_bytes; | |
2112 # endif | |
2113 int mouse_code = 0; // init for GCC | |
2114 int is_click, is_drag; | |
2115 int wheel_code = 0; | |
2116 int current_button; | |
2117 static int held_button = MOUSE_RELEASE; | |
2118 static int orig_num_clicks = 1; | |
2119 static int orig_mouse_code = 0x0; | |
2120 # ifdef CHECK_DOUBLE_CLICK | |
2121 static int orig_mouse_col = 0; | |
2122 static int orig_mouse_row = 0; | |
2123 static struct timeval orig_mouse_time = {0, 0}; | |
2124 // time of previous mouse click | |
2125 struct timeval mouse_time; // time of current mouse click | |
2126 long timediff; // elapsed time in msec | |
2127 # endif | |
2128 | |
2129 is_click = is_drag = FALSE; | |
2130 | |
2131 # if !defined(UNIX) || defined(FEAT_MOUSE_XTERM) || defined(FEAT_GUI) \ | |
2132 || defined(FEAT_MOUSE_GPM) || defined(FEAT_SYSMOUSE) | |
2133 if (key_name[0] == KS_MOUSE | |
2134 # ifdef FEAT_MOUSE_GPM | |
2135 || key_name[0] == KS_GPM_MOUSE | |
2136 # endif | |
2137 ) | |
2138 { | |
2139 /* | |
2140 * For xterm we get "<t_mouse>scr", where | |
2141 * s == encoded button state: | |
2142 * 0x20 = left button down | |
2143 * 0x21 = middle button down | |
2144 * 0x22 = right button down | |
2145 * 0x23 = any button release | |
2146 * 0x60 = button 4 down (scroll wheel down) | |
2147 * 0x61 = button 5 down (scroll wheel up) | |
2148 * add 0x04 for SHIFT | |
2149 * add 0x08 for ALT | |
2150 * add 0x10 for CTRL | |
2151 * add 0x20 for mouse drag (0x40 is drag with left button) | |
2152 * add 0x40 for mouse move (0x80 is move, 0x81 too) | |
2153 * 0x43 (drag + release) is also move | |
2154 * c == column + ' ' + 1 == column + 33 | |
2155 * r == row + ' ' + 1 == row + 33 | |
2156 * | |
2157 * The coordinates are passed on through global variables. | |
2158 * Ugly, but this avoids trouble with mouse clicks at an | |
2159 * unexpected moment and allows for mapping them. | |
2160 */ | |
2161 for (;;) | |
2162 { | |
2163 # ifdef FEAT_GUI | |
2164 if (gui.in_use) | |
2165 { | |
2166 // GUI uses more bits for columns > 223 | |
2167 num_bytes = get_bytes_from_buf(tp + *slen, bytes, 5); | |
2168 if (num_bytes == -1) // not enough coordinates | |
2169 return -1; | |
2170 mouse_code = bytes[0]; | |
2171 mouse_col = 128 * (bytes[1] - ' ' - 1) | |
2172 + bytes[2] - ' ' - 1; | |
2173 mouse_row = 128 * (bytes[3] - ' ' - 1) | |
2174 + bytes[4] - ' ' - 1; | |
2175 } | |
2176 else | |
2177 # endif | |
2178 { | |
2179 num_bytes = get_bytes_from_buf(tp + *slen, bytes, 3); | |
2180 if (num_bytes == -1) // not enough coordinates | |
2181 return -1; | |
2182 mouse_code = bytes[0]; | |
2183 mouse_col = bytes[1] - ' ' - 1; | |
2184 mouse_row = bytes[2] - ' ' - 1; | |
2185 } | |
2186 *slen += num_bytes; | |
2187 | |
2188 // If the following bytes is also a mouse code and it has | |
2189 // the same code, dump this one and get the next. This | |
2190 // makes dragging a whole lot faster. | |
2191 # ifdef FEAT_GUI | |
2192 if (gui.in_use) | |
2193 j = 3; | |
2194 else | |
2195 # endif | |
2196 j = get_termcode_len(idx); | |
2197 if (STRNCMP(tp, tp + *slen, (size_t)j) == 0 | |
2198 && tp[*slen + j] == mouse_code | |
2199 && tp[*slen + j + 1] != NUL | |
2200 && tp[*slen + j + 2] != NUL | |
2201 # ifdef FEAT_GUI | |
2202 && (!gui.in_use | |
2203 || (tp[*slen + j + 3] != NUL | |
2204 && tp[*slen + j + 4] != NUL)) | |
2205 # endif | |
2206 ) | |
2207 *slen += j; | |
2208 else | |
2209 break; | |
2210 } | |
2211 } | |
2212 | |
2213 if (key_name[0] == KS_URXVT_MOUSE | |
2214 || key_name[0] == KS_SGR_MOUSE | |
2215 || key_name[0] == KS_SGR_MOUSE_RELEASE) | |
2216 { | |
2217 // URXVT 1015 mouse reporting mode: | |
2218 // Almost identical to xterm mouse mode, except the values | |
2219 // are decimal instead of bytes. | |
2220 // | |
2221 // \033[%d;%d;%dM | |
2222 // ^-- row | |
2223 // ^----- column | |
2224 // ^-------- code | |
2225 // | |
2226 // SGR 1006 mouse reporting mode: | |
2227 // Almost identical to xterm mouse mode, except the values | |
2228 // are decimal instead of bytes. | |
2229 // | |
2230 // \033[<%d;%d;%dM | |
2231 // ^-- row | |
2232 // ^----- column | |
2233 // ^-------- code | |
2234 // | |
2235 // \033[<%d;%d;%dm : mouse release event | |
2236 // ^-- row | |
2237 // ^----- column | |
2238 // ^-------- code | |
2239 p = modifiers_start; | |
2240 if (p == NULL) | |
2241 return -1; | |
2242 | |
2243 mouse_code = getdigits(&p); | |
2244 if (*p++ != ';') | |
2245 return -1; | |
2246 | |
2247 // when mouse reporting is SGR, add 32 to mouse code | |
2248 if (key_name[0] == KS_SGR_MOUSE | |
2249 || key_name[0] == KS_SGR_MOUSE_RELEASE) | |
2250 mouse_code += 32; | |
2251 | |
2252 if (key_name[0] == KS_SGR_MOUSE_RELEASE) | |
2253 mouse_code |= MOUSE_RELEASE; | |
2254 | |
2255 mouse_col = getdigits(&p) - 1; | |
2256 if (*p++ != ';') | |
2257 return -1; | |
2258 | |
2259 mouse_row = getdigits(&p) - 1; | |
2260 | |
2261 // The modifiers were the mouse coordinates, not the | |
2262 // modifier keys (alt/shift/ctrl/meta) state. | |
2263 *modifiers = 0; | |
2264 } | |
2265 | |
2266 if (key_name[0] == KS_MOUSE | |
2267 # ifdef FEAT_MOUSE_GPM | |
2268 || key_name[0] == KS_GPM_MOUSE | |
2269 # endif | |
2270 # ifdef FEAT_MOUSE_URXVT | |
2271 || key_name[0] == KS_URXVT_MOUSE | |
2272 # endif | |
2273 || key_name[0] == KS_SGR_MOUSE | |
2274 || key_name[0] == KS_SGR_MOUSE_RELEASE) | |
2275 { | |
2276 # if !defined(MSWIN) | |
2277 /* | |
2278 * Handle mouse events. | |
2279 * Recognize the xterm mouse wheel, but not in the GUI, the | |
2280 * Linux console with GPM and the MS-DOS or Win32 console | |
2281 * (multi-clicks use >= 0x60). | |
2282 */ | |
2283 if (mouse_code >= MOUSEWHEEL_LOW | |
2284 # ifdef FEAT_GUI | |
2285 && !gui.in_use | |
2286 # endif | |
2287 # ifdef FEAT_MOUSE_GPM | |
2288 && key_name[0] != KS_GPM_MOUSE | |
2289 # endif | |
2290 ) | |
2291 { | |
2292 # if defined(UNIX) && defined(FEAT_MOUSE_TTY) | |
2293 if (use_xterm_mouse() > 1 && mouse_code >= 0x80) | |
2294 // mouse-move event, using MOUSE_DRAG works | |
2295 mouse_code = MOUSE_DRAG; | |
2296 else | |
2297 # endif | |
2298 // Keep the mouse_code before it's changed, so that we | |
2299 // remember that it was a mouse wheel click. | |
2300 wheel_code = mouse_code; | |
2301 } | |
2302 # ifdef FEAT_MOUSE_XTERM | |
2303 else if (held_button == MOUSE_RELEASE | |
2304 # ifdef FEAT_GUI | |
2305 && !gui.in_use | |
2306 # endif | |
2307 && (mouse_code == 0x23 || mouse_code == 0x24 | |
2308 || mouse_code == 0x40 || mouse_code == 0x41)) | |
2309 { | |
2310 // Apparently 0x23 and 0x24 are used by rxvt scroll wheel. | |
2311 // And 0x40 and 0x41 are used by some xterm emulator. | |
2312 wheel_code = mouse_code - (mouse_code >= 0x40 ? 0x40 : 0x23) | |
2313 + MOUSEWHEEL_LOW; | |
2314 } | |
2315 # endif | |
2316 | |
2317 # if defined(UNIX) && defined(FEAT_MOUSE_TTY) | |
2318 else if (use_xterm_mouse() > 1) | |
2319 { | |
2320 if (mouse_code & MOUSE_DRAG_XTERM) | |
2321 mouse_code |= MOUSE_DRAG; | |
2322 } | |
2323 # endif | |
2324 # ifdef FEAT_XCLIPBOARD | |
2325 else if (!(mouse_code & MOUSE_DRAG & ~MOUSE_CLICK_MASK)) | |
2326 { | |
2327 if ((mouse_code & MOUSE_RELEASE) == MOUSE_RELEASE) | |
2328 stop_xterm_trace(); | |
2329 else | |
2330 start_xterm_trace(mouse_code); | |
2331 } | |
2332 # endif | |
2333 # endif | |
2334 } | |
2335 # endif // !UNIX || FEAT_MOUSE_XTERM | |
2336 # ifdef FEAT_MOUSE_NET | |
2337 if (key_name[0] == KS_NETTERM_MOUSE) | |
2338 { | |
2339 int mc, mr; | |
2340 | |
2341 // expect a rather limited sequence like: balancing { | |
2342 // \033}6,45\r | |
2343 // '6' is the row, 45 is the column | |
2344 p = tp + *slen; | |
2345 mr = getdigits(&p); | |
2346 if (*p++ != ',') | |
2347 return -1; | |
2348 mc = getdigits(&p); | |
2349 if (*p++ != '\r') | |
2350 return -1; | |
2351 | |
2352 mouse_col = mc - 1; | |
2353 mouse_row = mr - 1; | |
2354 mouse_code = MOUSE_LEFT; | |
2355 *slen += (int)(p - (tp + *slen)); | |
2356 } | |
2357 # endif // FEAT_MOUSE_NET | |
2358 # ifdef FEAT_MOUSE_JSB | |
2359 if (key_name[0] == KS_JSBTERM_MOUSE) | |
2360 { | |
2361 int mult, val, iter, button, status; | |
2362 | |
2363 /* | |
2364 * JSBTERM Input Model | |
2365 * \033[0~zw uniq escape sequence | |
2366 * (L-x) Left button pressed - not pressed x not reporting | |
2367 * (M-x) Middle button pressed - not pressed x not reporting | |
2368 * (R-x) Right button pressed - not pressed x not reporting | |
2369 * (SDmdu) Single , Double click, m mouse move d button down | |
2370 * u button up | |
2371 * ### X cursor position padded to 3 digits | |
2372 * ### Y cursor position padded to 3 digits | |
2373 * (s-x) SHIFT key pressed - not pressed x not reporting | |
2374 * (c-x) CTRL key pressed - not pressed x not reporting | |
2375 * \033\\ terminating sequence | |
2376 */ | |
2377 p = tp + *slen; | |
2378 button = mouse_code = 0; | |
2379 switch (*p++) | |
2380 { | |
2381 case 'L': button = 1; break; | |
2382 case '-': break; | |
2383 case 'x': break; // ignore sequence | |
2384 default: return -1; // Unknown Result | |
2385 } | |
2386 switch (*p++) | |
2387 { | |
2388 case 'M': button |= 2; break; | |
2389 case '-': break; | |
2390 case 'x': break; // ignore sequence | |
2391 default: return -1; // Unknown Result | |
2392 } | |
2393 switch (*p++) | |
2394 { | |
2395 case 'R': button |= 4; break; | |
2396 case '-': break; | |
2397 case 'x': break; // ignore sequence | |
2398 default: return -1; // Unknown Result | |
2399 } | |
2400 status = *p++; | |
2401 for (val = 0, mult = 100, iter = 0; iter < 3; iter++, | |
2402 mult /= 10, p++) | |
2403 if (*p >= '0' && *p <= '9') | |
2404 val += (*p - '0') * mult; | |
2405 else | |
2406 return -1; | |
2407 mouse_col = val; | |
2408 for (val = 0, mult = 100, iter = 0; iter < 3; iter++, | |
2409 mult /= 10, p++) | |
2410 if (*p >= '0' && *p <= '9') | |
2411 val += (*p - '0') * mult; | |
2412 else | |
2413 return -1; | |
2414 mouse_row = val; | |
2415 switch (*p++) | |
2416 { | |
2417 case 's': button |= 8; break; // SHIFT key Pressed | |
2418 case '-': break; // Not Pressed | |
2419 case 'x': break; // Not Reporting | |
2420 default: return -1; // Unknown Result | |
2421 } | |
2422 switch (*p++) | |
2423 { | |
2424 case 'c': button |= 16; break; // CTRL key Pressed | |
2425 case '-': break; // Not Pressed | |
2426 case 'x': break; // Not Reporting | |
2427 default: return -1; // Unknown Result | |
2428 } | |
2429 if (*p++ != '\033') | |
2430 return -1; | |
2431 if (*p++ != '\\') | |
2432 return -1; | |
2433 switch (status) | |
2434 { | |
2435 case 'D': // Double Click | |
2436 case 'S': // Single Click | |
2437 if (button & 1) mouse_code |= MOUSE_LEFT; | |
2438 if (button & 2) mouse_code |= MOUSE_MIDDLE; | |
2439 if (button & 4) mouse_code |= MOUSE_RIGHT; | |
2440 if (button & 8) mouse_code |= MOUSE_SHIFT; | |
2441 if (button & 16) mouse_code |= MOUSE_CTRL; | |
2442 break; | |
2443 case 'm': // Mouse move | |
2444 if (button & 1) mouse_code |= MOUSE_LEFT; | |
2445 if (button & 2) mouse_code |= MOUSE_MIDDLE; | |
2446 if (button & 4) mouse_code |= MOUSE_RIGHT; | |
2447 if (button & 8) mouse_code |= MOUSE_SHIFT; | |
2448 if (button & 16) mouse_code |= MOUSE_CTRL; | |
2449 if ((button & 7) != 0) | |
2450 { | |
2451 held_button = mouse_code; | |
2452 mouse_code |= MOUSE_DRAG; | |
2453 } | |
2454 is_drag = TRUE; | |
2455 showmode(); | |
2456 break; | |
2457 case 'd': // Button Down | |
2458 if (button & 1) mouse_code |= MOUSE_LEFT; | |
2459 if (button & 2) mouse_code |= MOUSE_MIDDLE; | |
2460 if (button & 4) mouse_code |= MOUSE_RIGHT; | |
2461 if (button & 8) mouse_code |= MOUSE_SHIFT; | |
2462 if (button & 16) mouse_code |= MOUSE_CTRL; | |
2463 break; | |
2464 case 'u': // Button Up | |
2465 if (button & 1) | |
2466 mouse_code |= MOUSE_LEFT | MOUSE_RELEASE; | |
2467 if (button & 2) | |
2468 mouse_code |= MOUSE_MIDDLE | MOUSE_RELEASE; | |
2469 if (button & 4) | |
2470 mouse_code |= MOUSE_RIGHT | MOUSE_RELEASE; | |
2471 if (button & 8) | |
2472 mouse_code |= MOUSE_SHIFT; | |
2473 if (button & 16) | |
2474 mouse_code |= MOUSE_CTRL; | |
2475 break; | |
2476 default: return -1; // Unknown Result | |
2477 } | |
2478 | |
2479 *slen += (p - (tp + *slen)); | |
2480 } | |
2481 # endif // FEAT_MOUSE_JSB | |
2482 # ifdef FEAT_MOUSE_DEC | |
2483 if (key_name[0] == KS_DEC_MOUSE) | |
2484 { | |
2485 /* | |
2486 * The DEC Locator Input Model | |
2487 * Netterm delivers the code sequence: | |
2488 * \033[2;4;24;80&w (left button down) | |
2489 * \033[3;0;24;80&w (left button up) | |
2490 * \033[6;1;24;80&w (right button down) | |
2491 * \033[7;0;24;80&w (right button up) | |
2492 * CSI Pe ; Pb ; Pr ; Pc ; Pp & w | |
2493 * Pe is the event code | |
2494 * Pb is the button code | |
2495 * Pr is the row coordinate | |
2496 * Pc is the column coordinate | |
2497 * Pp is the third coordinate (page number) | |
2498 * Pe, the event code indicates what event caused this report | |
2499 * The following event codes are defined: | |
2500 * 0 - request, the terminal received an explicit request | |
2501 * for a locator report, but the locator is unavailable | |
2502 * 1 - request, the terminal received an explicit request | |
2503 * for a locator report | |
2504 * 2 - left button down | |
2505 * 3 - left button up | |
2506 * 4 - middle button down | |
2507 * 5 - middle button up | |
2508 * 6 - right button down | |
2509 * 7 - right button up | |
2510 * 8 - fourth button down | |
2511 * 9 - fourth button up | |
2512 * 10 - locator outside filter rectangle | |
2513 * Pb, the button code, ASCII decimal 0-15 indicating which | |
2514 * buttons are down if any. The state of the four buttons | |
2515 * on the locator correspond to the low four bits of the | |
2516 * decimal value, | |
2517 * "1" means button depressed | |
2518 * 0 - no buttons down, | |
2519 * 1 - right, | |
2520 * 2 - middle, | |
2521 * 4 - left, | |
2522 * 8 - fourth | |
2523 * Pr is the row coordinate of the locator position in the page, | |
2524 * encoded as an ASCII decimal value. | |
2525 * If Pr is omitted, the locator position is undefined | |
2526 * (outside the terminal window for example). | |
2527 * Pc is the column coordinate of the locator position in the | |
2528 * page, encoded as an ASCII decimal value. | |
2529 * If Pc is omitted, the locator position is undefined | |
2530 * (outside the terminal window for example). | |
2531 * Pp is the page coordinate of the locator position | |
2532 * encoded as an ASCII decimal value. | |
2533 * The page coordinate may be omitted if the locator is on | |
2534 * page one (the default). We ignore it anyway. | |
2535 */ | |
2536 int Pe, Pb, Pr, Pc; | |
2537 | |
2538 p = tp + *slen; | |
2539 | |
2540 // get event status | |
2541 Pe = getdigits(&p); | |
2542 if (*p++ != ';') | |
2543 return -1; | |
2544 | |
2545 // get button status | |
2546 Pb = getdigits(&p); | |
2547 if (*p++ != ';') | |
2548 return -1; | |
2549 | |
2550 // get row status | |
2551 Pr = getdigits(&p); | |
2552 if (*p++ != ';') | |
2553 return -1; | |
2554 | |
2555 // get column status | |
2556 Pc = getdigits(&p); | |
2557 | |
2558 // the page parameter is optional | |
2559 if (*p == ';') | |
2560 { | |
2561 p++; | |
2562 (void)getdigits(&p); | |
2563 } | |
2564 if (*p++ != '&') | |
2565 return -1; | |
2566 if (*p++ != 'w') | |
2567 return -1; | |
2568 | |
2569 mouse_code = 0; | |
2570 switch (Pe) | |
2571 { | |
2572 case 0: return -1; // position request while unavailable | |
2573 case 1: // a response to a locator position request includes | |
2574 // the status of all buttons | |
2575 Pb &= 7; // mask off and ignore fourth button | |
2576 if (Pb & 4) | |
2577 mouse_code = MOUSE_LEFT; | |
2578 if (Pb & 2) | |
2579 mouse_code = MOUSE_MIDDLE; | |
2580 if (Pb & 1) | |
2581 mouse_code = MOUSE_RIGHT; | |
2582 if (Pb) | |
2583 { | |
2584 held_button = mouse_code; | |
2585 mouse_code |= MOUSE_DRAG; | |
2586 WantQueryMouse = TRUE; | |
2587 } | |
2588 is_drag = TRUE; | |
2589 showmode(); | |
2590 break; | |
2591 case 2: mouse_code = MOUSE_LEFT; | |
2592 WantQueryMouse = TRUE; | |
2593 break; | |
2594 case 3: mouse_code = MOUSE_RELEASE | MOUSE_LEFT; | |
2595 break; | |
2596 case 4: mouse_code = MOUSE_MIDDLE; | |
2597 WantQueryMouse = TRUE; | |
2598 break; | |
2599 case 5: mouse_code = MOUSE_RELEASE | MOUSE_MIDDLE; | |
2600 break; | |
2601 case 6: mouse_code = MOUSE_RIGHT; | |
2602 WantQueryMouse = TRUE; | |
2603 break; | |
2604 case 7: mouse_code = MOUSE_RELEASE | MOUSE_RIGHT; | |
2605 break; | |
2606 case 8: return -1; // fourth button down | |
2607 case 9: return -1; // fourth button up | |
2608 case 10: return -1; // mouse outside of filter rectangle | |
2609 default: return -1; // should never occur | |
2610 } | |
2611 | |
2612 mouse_col = Pc - 1; | |
2613 mouse_row = Pr - 1; | |
2614 | |
2615 *slen += (int)(p - (tp + *slen)); | |
2616 } | |
2617 # endif // FEAT_MOUSE_DEC | |
2618 # ifdef FEAT_MOUSE_PTERM | |
2619 if (key_name[0] == KS_PTERM_MOUSE) | |
2620 { | |
2621 int button, num_clicks, action; | |
2622 | |
2623 p = tp + *slen; | |
2624 | |
2625 action = getdigits(&p); | |
2626 if (*p++ != ';') | |
2627 return -1; | |
2628 | |
2629 mouse_row = getdigits(&p); | |
2630 if (*p++ != ';') | |
2631 return -1; | |
2632 mouse_col = getdigits(&p); | |
2633 if (*p++ != ';') | |
2634 return -1; | |
2635 | |
2636 button = getdigits(&p); | |
2637 mouse_code = 0; | |
2638 | |
2639 switch (button) | |
2640 { | |
2641 case 4: mouse_code = MOUSE_LEFT; break; | |
2642 case 1: mouse_code = MOUSE_RIGHT; break; | |
2643 case 2: mouse_code = MOUSE_MIDDLE; break; | |
2644 default: return -1; | |
2645 } | |
2646 | |
2647 switch (action) | |
2648 { | |
2649 case 31: // Initial press | |
2650 if (*p++ != ';') | |
2651 return -1; | |
2652 | |
2653 num_clicks = getdigits(&p); // Not used | |
2654 break; | |
2655 | |
2656 case 32: // Release | |
2657 mouse_code |= MOUSE_RELEASE; | |
2658 break; | |
2659 | |
2660 case 33: // Drag | |
2661 held_button = mouse_code; | |
2662 mouse_code |= MOUSE_DRAG; | |
2663 break; | |
2664 | |
2665 default: | |
2666 return -1; | |
2667 } | |
2668 | |
2669 if (*p++ != 't') | |
2670 return -1; | |
2671 | |
2672 *slen += (p - (tp + *slen)); | |
2673 } | |
2674 # endif // FEAT_MOUSE_PTERM | |
2675 | |
2676 // Interpret the mouse code | |
2677 current_button = (mouse_code & MOUSE_CLICK_MASK); | |
2678 if (current_button == MOUSE_RELEASE | |
2679 # ifdef FEAT_MOUSE_XTERM | |
2680 && wheel_code == 0 | |
2681 # endif | |
2682 ) | |
2683 { | |
2684 /* | |
2685 * If we get a mouse drag or release event when | |
2686 * there is no mouse button held down (held_button == | |
2687 * MOUSE_RELEASE), produce a K_IGNORE below. | |
2688 * (can happen when you hold down two buttons | |
2689 * and then let them go, or click in the menu bar, but not | |
2690 * on a menu, and drag into the text). | |
2691 */ | |
2692 if ((mouse_code & MOUSE_DRAG) == MOUSE_DRAG) | |
2693 is_drag = TRUE; | |
2694 current_button = held_button; | |
2695 } | |
2696 else if (wheel_code == 0) | |
2697 { | |
2698 # ifdef CHECK_DOUBLE_CLICK | |
2699 # ifdef FEAT_MOUSE_GPM | |
2700 /* | |
2701 * Only for Unix, when GUI not active, we handle | |
2702 * multi-clicks here, but not for GPM mouse events. | |
2703 */ | |
2704 # ifdef FEAT_GUI | |
2705 if (key_name[0] != KS_GPM_MOUSE && !gui.in_use) | |
2706 # else | |
2707 if (key_name[0] != KS_GPM_MOUSE) | |
2708 # endif | |
2709 # else | |
2710 # ifdef FEAT_GUI | |
2711 if (!gui.in_use) | |
2712 # endif | |
2713 # endif | |
2714 { | |
2715 /* | |
2716 * Compute the time elapsed since the previous mouse click. | |
2717 */ | |
2718 gettimeofday(&mouse_time, NULL); | |
2719 if (orig_mouse_time.tv_sec == 0) | |
2720 { | |
2721 /* | |
2722 * Avoid computing the difference between mouse_time | |
2723 * and orig_mouse_time for the first click, as the | |
2724 * difference would be huge and would cause | |
2725 * multiplication overflow. | |
2726 */ | |
2727 timediff = p_mouset; | |
2728 } | |
2729 else | |
2730 { | |
2731 timediff = (mouse_time.tv_usec | |
2732 - orig_mouse_time.tv_usec) / 1000; | |
2733 if (timediff < 0) | |
2734 --orig_mouse_time.tv_sec; | |
2735 timediff += (mouse_time.tv_sec | |
2736 - orig_mouse_time.tv_sec) * 1000; | |
2737 } | |
2738 orig_mouse_time = mouse_time; | |
2739 if (mouse_code == orig_mouse_code | |
2740 && timediff < p_mouset | |
2741 && orig_num_clicks != 4 | |
2742 && orig_mouse_col == mouse_col | |
2743 && orig_mouse_row == mouse_row | |
2744 && (is_mouse_topline(curwin) | |
2745 // Double click in tab pages line also works | |
2746 // when window contents changes. | |
2747 || (mouse_row == 0 && firstwin->w_winrow > 0)) | |
2748 ) | |
2749 ++orig_num_clicks; | |
2750 else | |
2751 orig_num_clicks = 1; | |
2752 orig_mouse_col = mouse_col; | |
2753 orig_mouse_row = mouse_row; | |
2754 set_mouse_topline(curwin); | |
2755 } | |
2756 # if defined(FEAT_GUI) || defined(FEAT_MOUSE_GPM) | |
2757 else | |
2758 orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code); | |
2759 # endif | |
2760 # else | |
2761 orig_num_clicks = NUM_MOUSE_CLICKS(mouse_code); | |
2762 # endif | |
2763 is_click = TRUE; | |
2764 orig_mouse_code = mouse_code; | |
2765 } | |
2766 if (!is_drag) | |
2767 held_button = mouse_code & MOUSE_CLICK_MASK; | |
2768 | |
2769 /* | |
2770 * Translate the actual mouse event into a pseudo mouse event. | |
2771 * First work out what modifiers are to be used. | |
2772 */ | |
2773 if (orig_mouse_code & MOUSE_SHIFT) | |
2774 *modifiers |= MOD_MASK_SHIFT; | |
2775 if (orig_mouse_code & MOUSE_CTRL) | |
2776 *modifiers |= MOD_MASK_CTRL; | |
2777 if (orig_mouse_code & MOUSE_ALT) | |
2778 *modifiers |= MOD_MASK_ALT; | |
2779 if (orig_num_clicks == 2) | |
2780 *modifiers |= MOD_MASK_2CLICK; | |
2781 else if (orig_num_clicks == 3) | |
2782 *modifiers |= MOD_MASK_3CLICK; | |
2783 else if (orig_num_clicks == 4) | |
2784 *modifiers |= MOD_MASK_4CLICK; | |
2785 | |
2786 // Work out our pseudo mouse event. Note that MOUSE_RELEASE gets | |
2787 // added, then it's not mouse up/down. | |
2788 key_name[0] = KS_EXTRA; | |
2789 if (wheel_code != 0 | |
2790 && (wheel_code & MOUSE_RELEASE) != MOUSE_RELEASE) | |
2791 { | |
2792 if (wheel_code & MOUSE_CTRL) | |
2793 *modifiers |= MOD_MASK_CTRL; | |
2794 if (wheel_code & MOUSE_ALT) | |
2795 *modifiers |= MOD_MASK_ALT; | |
2796 key_name[1] = (wheel_code & 1) | |
2797 ? (int)KE_MOUSEUP : (int)KE_MOUSEDOWN; | |
2798 held_button = MOUSE_RELEASE; | |
2799 } | |
2800 else | |
2801 key_name[1] = get_pseudo_mouse_code(current_button, | |
2802 is_click, is_drag); | |
2803 | |
2804 // Make sure the mouse position is valid. Some terminals may | |
2805 // return weird values. | |
2806 if (mouse_col >= Columns) | |
2807 mouse_col = Columns - 1; | |
2808 if (mouse_row >= Rows) | |
2809 mouse_row = Rows - 1; | |
2810 | |
2811 return 0; | |
2812 } | |
2092 #endif // FEAT_MOUSE | 2813 #endif // FEAT_MOUSE |
2093 | 2814 |
2094 // Functions also used for popup windows. | 2815 // Functions also used for popup windows. |
2095 #if defined(FEAT_MOUSE) || defined(FEAT_TEXT_PROP) || defined(PROTO) | 2816 #if defined(FEAT_MOUSE) || defined(FEAT_TEXT_PROP) || defined(PROTO) |
2096 | 2817 |