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